diff --git a/.github/workflows/Lint.yml b/.github/workflows/Lint.yml index 9c0409a2bd..58590a9176 100644 --- a/.github/workflows/Lint.yml +++ b/.github/workflows/Lint.yml @@ -5,8 +5,8 @@ jobs: strategy: fail-fast: false matrix: - ruby: [2.4] - os: [ubuntu-16.04] + ruby: [2.6] + os: [ubuntu-18.04] name: Lint runs-on: ${{ matrix.os }} @@ -32,7 +32,6 @@ jobs: gems@v1-${{ matrix.os }}-${{ env.ImageVersion }}-Ruby${{ matrix.ruby }}- - name: Run bundle install run: | - gem install bundler -v "~> 1.17" bundle config path vendor/bundle bundle install --jobs 4 --retry 3 --without debugging documentation diff --git a/.github/workflows/Specs.yml b/.github/workflows/Specs.yml index 5216fb891a..8dd2217dcd 100644 --- a/.github/workflows/Specs.yml +++ b/.github/workflows/Specs.yml @@ -6,8 +6,8 @@ jobs: fail-fast: false matrix: task: [SPECS] - ruby: [2.3.3, 2.4, 2.5, 2.6, 2.7] - os: [ubuntu-16.04] + ruby: [2.6, 2.7, 3.0] + os: [ubuntu-18.04] include: - task: SPECS os: macos-10.15 @@ -70,4 +70,3 @@ on: branches: - master - "*-stable" - diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index b7d8a37ce9..506cefff5f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -238,6 +238,8 @@ Lint/UselessAccessModifier: # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: Max: 1493 + Exclude: + - 'spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb' # Offense count: 7099 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. diff --git a/CHANGELOG.md b/CHANGELOG.md index cb2e615727..0b85a54317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,132 @@ To install or update CocoaPods see this [guide](https://guides.cocoapods.org/usi To install release candidates run `[sudo] gem install cocoapods --pre` -## 1.10.2 (2021-07-28) +## 1.11.2 (2021-09-13) + +##### Enhancements + +* None. + +##### Bug Fixes + +* Do not validate modular header dependencies for pre-built Swift pods. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10912](https://github.com/CocoaPods/CocoaPods/issues/10912) + + +## 1.11.1 (2021-09-13) + +##### Enhancements + +* None. + +##### Bug Fixes + +* Handle spec repo urls with user info when determining if they are CDN. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10941](https://github.com/CocoaPods/CocoaPods/issues/10941) + +* Set `INFOPLIST_FILE` build setting to `$(SRCROOT)/App/App-Info.plist` during lint. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10927](https://github.com/CocoaPods/CocoaPods/issues/10927) + +* Set `PRODUCT_BUNDLE_IDENTIFIER` for generated app during lint. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10933](https://github.com/CocoaPods/CocoaPods/issues/10933) + + +## 1.11.0 (2021-09-01) + +##### Enhancements + +* None. + +##### Bug Fixes + +* None. + + +## 1.11.0.rc.1 (2021-08-25) ##### Enhancements +* None. + +##### Bug Fixes + +* Correctly process multiple `xcframeworks` a pod provides. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10378](https://github.com/CocoaPods/CocoaPods/issues/10378) + + +## 1.11.0.beta.2 (2021-08-11) + +##### Enhancements + +* Integrate ODR categories into projects. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10855](https://github.com/CocoaPods/CocoaPods/pull/10855) + +##### Bug Fixes + +* Pass correct paths for `select_slice` method. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10430](https://github.com/CocoaPods/CocoaPods/issues/10430) + + +## 1.11.0.beta.1 (2021-08-09) + +##### Enhancements + +* Add support for integrating on demand resources. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [JunyiXie](https://github.com/JunyiXie) + [#9606](https://github.com/CocoaPods/CocoaPods/issues/9606) + [#10845](https://github.com/CocoaPods/CocoaPods/pull/10845) + +* Integrate `project_header_files` specified by specs. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#9820](https://github.com/CocoaPods/CocoaPods/issues/9820) + +* Mark RealityComposer-projects (`.rcproject`) files defined in resources for compilation. + [Hendrik von Prince](https://github.com/parallaxe) + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10793](https://github.com/CocoaPods/CocoaPods/pull/10793) + +* Integrate test specs and app specs of pre-built pods. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10795](https://github.com/CocoaPods/CocoaPods/pull/10795) + +* Add support for `before_headers` and `after_headers` script phase DSL. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10770](https://github.com/CocoaPods/CocoaPods/issues/10770) + +* Fix touch on a missing directory for dSYM copy phase script. + [alvarollmenezes](https://github.com/alvarollmenezes) + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10488](https://github.com/CocoaPods/CocoaPods/issues/10488) + +* Check the podfile sources and plugin sources when printing warnings without explicitly using the master source. + [gonghonglou](https://github.com/gonghonglou) + [#10764](https://github.com/CocoaPods/CocoaPods/pull/10764) + +* Use relative paths in copy dsyms script. + [Mickey Knox](https://github.com/knox) + [#10583](https://github.com/CocoaPods/CocoaPods/pull/10583) + +* Use `OpenURI.open_uri` instead. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10597](https://github.com/CocoaPods/CocoaPods/issues/10597) + +* Set minimum supported Ruby version to 2.6. + [Igor Makarov](https://github.com/igor-makarov) + [#10412](https://github.com/CocoaPods/CocoaPods/pull/10412) + * Improve compatibility with ActiveSupport 6 [Jun Jiang](https://github.com/jasl) [#10364](https://github.com/CocoaPods/CocoaPods/pull/10364) -* Add a post_integrate_hook API +* Add a `pre_integrate_hook` API [dcvz](https://github.com/dcvz) [#9935](https://github.com/CocoaPods/CocoaPods/pull/9935) @@ -20,7 +137,7 @@ To install release candidates run `[sudo] gem install cocoapods --pre` [Jun Jiang](https://github.com/jasl), [Igor Makarov](https://github.com/igor-makarov) [#10346](https://github.com/CocoaPods/CocoaPods/pull/10346) -* Add a `--update-sources` option to `pod repo push` so one can ensure sources are up-to-date. +* Add a `--update-sources` option to `pod repo push` so one can ensure sources are up-to-date. [Elton Gao](https://github.com/gyfelton) [Justin Martin](https://github.com/justinseanmartin) @@ -36,13 +153,69 @@ To install release candidates run `[sudo] gem install cocoapods --pre` [cltnschlosser](https://github.com/cltnschlosser) [#9916](https://github.com/CocoaPods/CocoaPods/pull/9916) +* Add possibility to skip modulemap generation + [till0xff](https://github.com/till0xff) + [#10235](https://github.com/CocoaPods/CocoaPods/issues/10235) + * Add a `--version` option to `pod spec cat` and `pod spec which` for listing the podspec of a specific version [pietbrauer](https://github.com/pietbrauer) [#10609](https://github.com/CocoaPods/CocoaPods/pull/10609) ##### Bug Fixes -* Respect `--configuration` option when analyzing via `pod lib lint --analyze`. +* Fix resource variant groups in static frameworks + [Igor Makarov](https://github.com/igor-makarov) + [#10834](https://github.com/CocoaPods/CocoaPods/pull/10834) + [#10605](https://github.com/CocoaPods/CocoaPods/issues/10605) + +* Fix adding embed frameworks script phase to unit test targets if xcframeworks are present. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10652](https://github.com/CocoaPods/CocoaPods/issues/10652) + +* Remove unused `install_xcframework_library` code. + [Gio Lodi](https://github.com/mokagio) + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10831](https://github.com/CocoaPods/CocoaPods/pull/10831) + +* Validate vendored library names after they have been expanded. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10832](https://github.com/CocoaPods/CocoaPods/pull/10832) + +* Place frameworks from xcframeworks into a unique folder name to avoid duplicate outputs. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10106](https://github.com/CocoaPods/CocoaPods/issues/10106) + +* Update pod in Pods folder when changing the pod from branch to version in Podfie. + [gonghonglou](https://github.com/gonghonglou) + [#10825](https://github.com/CocoaPods/CocoaPods/pull/10825) + +* Bump addressable dependency to 2.8. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10802](https://github.com/CocoaPods/CocoaPods/issues/10802) + +* Dedup bcsymbolmap paths found from multiple vendored frameworks. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10373](https://github.com/CocoaPods/CocoaPods/issues/10373) + +* Correctly filter dependencies for pod variants across different platforms. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10777](https://github.com/CocoaPods/CocoaPods/issues/10777) + +* Generate default `Info.plist` for consumer app during validation. + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#8570](https://github.com/CocoaPods/CocoaPods/issues/8570) + +* Fix lint subspec error when the name of subspec start with the pod name. + [XianpuMeng](https://github.com/XianpuMeng) + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#9906](https://github.com/CocoaPods/CocoaPods/issues/9906) + +* Update `ruby-macho` gem version to support 1.x and 2.x. + [Eric Chamberlain](https://github.com/PeqNP) + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#10390](https://github.com/CocoaPods/CocoaPods/issues/10390) + +* Respect `--configuration` option when analyzing via `pod lib lint --analyze`. [Jenn Magder](https://github.com/jmagman) [#10476](https://github.com/CocoaPods/CocoaPods/issues/10476) @@ -73,6 +246,16 @@ To install release candidates run `[sudo] gem install cocoapods --pre` * Serialize schemes that do not need to be rewritten by Xcode. [Samuel Giddins](https://github.com/segiddins) + + +## 1.10.2 (2021-07-28) + +##### Enhancements + +* None. + +##### Bug Fixes + * Fix errors when archiving a Catalyst app which depends on a pod which uses `header_mappings_dir`. [Thomas Goyne](https://github.com/tgoyne) [#10224](https://github.com/CocoaPods/CocoaPods/pull/10224) @@ -199,12 +382,11 @@ To install release candidates run `[sudo] gem install cocoapods --pre` [Gereon Steffens](https://github.com/gereons) [#9686](https://github.com/CocoaPods/CocoaPods/issues/9686) -* Add a post_integrate_hook API +* Add a `post_integrate_hook` API [lucasmpaim](https://github.com/lucasmpaim) [#7432](https://github.com/CocoaPods/CocoaPods/issues/7432) -* Set the `BUILD_LIBRARY_FOR_DISTRIBUTION` build setting if integrating with - a target that has the setting set to `YES` (directly or in an .xcconfig). +* Set the `BUILD_LIBRARY_FOR_DISTRIBUTION` build setting if integrating with a target that has the setting set to `YES`. [Juanjo López](https://github.com/juanjonol) [#9232](https://github.com/CocoaPods/CocoaPods/issues/9232) @@ -212,7 +394,7 @@ To install release candidates run `[sudo] gem install cocoapods --pre` [Paul Beusterien](https://github.com/paulb777) [#9392](https://github.com/CocoaPods/CocoaPods/pull/9392) -* Add --use-static-frameworks lint option +* Add `--use-static-frameworks` lint option [Paul Beusterien](https://github.com/paulb777) [#9632](https://github.com/CocoaPods/CocoaPods/pull/9632) diff --git a/Gemfile b/Gemfile index dc4e9feb88..ff98832948 100644 --- a/Gemfile +++ b/Gemfile @@ -20,7 +20,7 @@ gemspec group :development do cp_gem 'claide', 'CLAide' - cp_gem 'cocoapods-core', 'Core' + cp_gem 'cocoapods-core', 'Core', '1-11-stable' cp_gem 'cocoapods-deintegrate', 'cocoapods-deintegrate' cp_gem 'cocoapods-downloader', 'cocoapods-downloader' cp_gem 'cocoapods-plugins', 'cocoapods-plugins' @@ -48,7 +48,7 @@ group :development do # Integration tests gem 'diffy' - gem 'clintegracon' + gem 'clintegracon', :git => 'https://github.com/mrackwitz/CLIntegracon.git' # Code Quality gem 'inch_by_inch' diff --git a/Gemfile.lock b/Gemfile.lock index 2387d78f8d..03078b7b29 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,26 +7,26 @@ GIT GIT remote: https://github.com/CocoaPods/Core.git - revision: 79996f3e5f712f3d6337a7d9b440a3d036bc1619 - branch: 1-10-stable + revision: 57f9eeca434f1bdcf0ba34b8e0a7c551b51f3b66 + branch: 1-11-stable specs: - cocoapods-core (1.10.2) - activesupport (> 5.0, < 6) - addressable (~> 2.6) + cocoapods-core (1.11.2) + activesupport (>= 5.0, < 7) + addressable (~> 2.8) algoliasearch (~> 1.0) concurrent-ruby (~> 1.1) fuzzy_match (~> 2.0.4) nap (~> 1.0) netrc (~> 0.11) - public_suffix + public_suffix (~> 4.0) typhoeus (~> 1.0) GIT remote: https://github.com/CocoaPods/Molinillo.git - revision: 3bce9d12dcd9678109306eb2aef2275d1a05893b - tag: 0.6.6 + revision: 8053207d1184703a45f48d7bc00ad73aa03012b5 + branch: master specs: - molinillo (0.6.6) + molinillo (0.8.0) GIT remote: https://github.com/CocoaPods/Nanaimo.git @@ -37,10 +37,10 @@ GIT GIT remote: https://github.com/CocoaPods/Xcodeproj.git - revision: eeccae7275645753cbaf45d96fc4b23e4b8b3b9f + revision: 2a1f19ad039556a153dd888cc293b9330bdc0f7a branch: master specs: - xcodeproj (1.20.0) + xcodeproj (1.21.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) @@ -50,17 +50,17 @@ GIT GIT remote: https://github.com/CocoaPods/cocoapods-deintegrate.git - revision: c3372a2ea2c2134db78fc6f8d157ebb9bb943a83 + revision: 2e378b88c65a21a4b89fad989a81a23caec48cdf branch: master specs: - cocoapods-deintegrate (1.0.4) + cocoapods-deintegrate (1.0.5) GIT remote: https://github.com/CocoaPods/cocoapods-downloader.git - revision: 55c2937c19baadbd3529bf9919f9626af4dea597 + revision: eed7e8f6c42c2e2f582f5c6c34bf44dcf0a08120 branch: master specs: - cocoapods-downloader (1.4.0) + cocoapods-downloader (1.5.1) GIT remote: https://github.com/CocoaPods/cocoapods-plugins.git @@ -72,17 +72,17 @@ GIT GIT remote: https://github.com/CocoaPods/cocoapods-search.git - revision: 452eee08d6497c43afd4452c28f9d7b8da8686f1 + revision: 1d10b7a71e1b7de865560d4af5ab1d9dcce5ea1d branch: master specs: - cocoapods-search (1.0.0) + cocoapods-search (1.0.1) GIT remote: https://github.com/CocoaPods/cocoapods-trunk.git - revision: d3ae92f6364ccc02439bf439df2abc07fa58f259 + revision: 52932934618b7012f4b0c7469768b2d26b3792fe branch: master specs: - cocoapods-trunk (1.5.0) + cocoapods-trunk (1.6.0) nap (>= 0.8, < 2.0) netrc (~> 0.11) @@ -100,19 +100,20 @@ GIT bacon (1.2.0) GIT - remote: https://github.com/segiddins/json.git - revision: a9588bc4334c2f5bf985f255b61c05eafdcd8907 - branch: seg-1.7.7-ruby-2.2 + remote: https://github.com/mrackwitz/CLIntegracon.git + revision: ca88b7b8920b6b6542f9b4ad2b1748855783dbae specs: - json (1.7.7) + clintegracon (0.9.0) + colored2 (~> 3.1) + diffy PATH remote: . specs: - cocoapods (1.10.2) - addressable (~> 2.6) + cocoapods (1.11.2) + addressable (~> 2.8) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.10.2) + cocoapods-core (= 1.11.2) cocoapods-deintegrate (>= 1.0.3, < 2.0) cocoapods-downloader (>= 1.4.0, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) @@ -123,10 +124,10 @@ PATH escape (~> 0.0.4) fourflusher (>= 2.3.0, < 3.0) gh_inspector (~> 1.0) - molinillo (~> 0.6.6) + molinillo (~> 0.8.0) nap (~> 1.0) - ruby-macho (~> 1.4) - xcodeproj (>= 1.19.0, < 2.0) + ruby-macho (>= 1.0, < 3.0) + xcodeproj (>= 1.21.0, < 2.0) GEM remote: https://rubygems.org/ @@ -150,9 +151,6 @@ GEM cork nap open4 (~> 1.3) - clintegracon (0.9.0) - colored2 (~> 3.1) - diffy cocoapods-dependencies (1.0.0.beta.1) ruby-graphviz (~> 1.2) cocoapods_debug (0.1.0) @@ -162,8 +160,8 @@ GEM concurrent-ruby (1.1.9) cork (0.3.0) colored2 (~> 3.1) - crack (0.4.3) - safe_yaml (~> 1.0.0) + crack (0.4.5) + rexml danger (5.16.1) claide (~> 1.0) claide-plugins (>= 0.9.2) @@ -176,7 +174,7 @@ GEM no_proxy_fix octokit (~> 4.7) terminal-table (~> 1) - diffy (3.2.1) + diffy (3.4.0) docile (1.1.5) escape (0.0.4) ethon (0.14.0) @@ -185,13 +183,13 @@ GEM multipart-post (>= 1.2, < 3) faraday-http-cache (1.3.1) faraday (~> 0.8) - ffi (1.15.3) + ffi (1.15.4) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) git (1.7.0) rchardet (~> 1.8) - hashdiff (0.3.1) + hashdiff (1.0.1) httpclient (2.8.3) i18n (1.8.10) concurrent-ruby (~> 1.0) @@ -203,6 +201,7 @@ GEM inch_by_inch (1.0.1) inch (~> 0.8.0) rake (~> 10.0) + json (2.5.1) kicker (3.0.0) listen (~> 1.3.0) notify (~> 0.5.2) @@ -257,10 +256,9 @@ GEM ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) ruby-graphviz (1.2.2) - ruby-macho (1.4.0) + ruby-macho (2.5.1) ruby-prof (0.15.2) ruby-progressbar (1.10.1) - safe_yaml (1.0.4) sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) @@ -282,10 +280,10 @@ GEM tzinfo (1.2.9) thread_safe (~> 0.1) unicode-display_width (1.7.0) - webmock (2.3.1) + webmock (3.11.1) addressable (>= 2.3.6) crack (>= 0.3.2) - hashdiff + hashdiff (>= 0.4.0, < 2.0.0) yard (0.9.12) PLATFORMS @@ -296,9 +294,9 @@ DEPENDENCIES awesome_print bacon! bigdecimal (~> 1.3.0) - bundler (~> 1.3) + bundler (~> 2.0) claide! - clintegracon + clintegracon! cocoapods! cocoapods-core! cocoapods-deintegrate! @@ -312,7 +310,6 @@ DEPENDENCIES danger (~> 5.3) diffy inch_by_inch - json! kicker mocha (< 1.5) mocha-on-bacon @@ -332,4 +329,4 @@ DEPENDENCIES xcodeproj! BUNDLED WITH - 1.17.3 + 2.2.8 diff --git a/Rakefile b/Rakefile index 7bd48400c4..7d7d8c0c77 100644 --- a/Rakefile +++ b/Rakefile @@ -46,38 +46,16 @@ begin desc 'Prepares for a release' task :pre_release do - unless File.exist?('../Specs') - raise 'Ensure that the specs repo exits in the `../Specs` location' - end end # Post release #-----------------------------------------------------------------------------# - desc 'Updates the last know version of CocoaPods in the specs repo' + desc 'Updates the last known version of CocoaPods in the specs repo' task :post_release do - title 'Updating last known version in Specs repo' - specs_branch = 'master' - Dir.chdir('../Specs') do - puts Dir.pwd - sh "git checkout #{specs_branch}" - sh 'git pull' - - yaml_file = 'CocoaPods-version.yml' - unless File.exist?(yaml_file) - $stderr.puts red("[!] Unable to find #{yaml_file}!") - exit 1 - end - require 'yaml' - cocoapods_version = YAML.load_file(yaml_file) - cocoapods_version['last'] = gem_version - File.open(yaml_file, 'w') do |f| - f.write(cocoapods_version.to_yaml) - end - - sh "git commit #{yaml_file} -m 'CocoaPods release #{gem_version}'" - sh 'git push' - end + puts yellow("\n[!] The `post_release` task of CocoaPods no longer updates the master specs repo last known version. " \ + 'This is because of how slow it has become which can break the release process. ' \ + "Please use the GitHub UI to update it to the #{gem_version} version.\n") end # Spec @@ -207,8 +185,8 @@ begin task :rebuild => :check_for_pending_changes do tarballs.each do |tarball| basename = File.basename(tarball) - untarred_path = File.join(File.dirname(tarball), basename[0..-8]) - sh "rm #{tarball} && env COPYFILE_DISABLE=1 tar -zcf #{tarball} #{untarred_path}" + untarred_basename = File.basename(tarball, '.tar.gz') + sh "cd #{File.dirname(tarball)} rm #{basename} && env COPYFILE_DISABLE=1 tar -zcf #{basename} #{untarred_basename}" end end @@ -223,7 +201,7 @@ begin tarballs.each do |tarball| basename = File.basename(tarball) Dir.chdir(File.dirname(tarball)) do - sh "rm -rf #{basename[0..-8]} && tar zxf #{basename}" + sh "rm -rf #{basename[0..-8]} ; tar zxf #{basename}" end end end @@ -402,3 +380,7 @@ end def red(string) "\033[0;31m#{string}\e[0m" end + +def yellow(string) + "\033[0;33m#{string}\e[0m" +end diff --git a/cocoapods.gemspec b/cocoapods.gemspec index 73a7082de6..b3d57c40e5 100644 --- a/cocoapods.gemspec +++ b/cocoapods.gemspec @@ -36,25 +36,21 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'cocoapods-search', '>= 1.0.0', '< 2.0' s.add_runtime_dependency 'cocoapods-trunk', '>= 1.4.0', '< 2.0' s.add_runtime_dependency 'cocoapods-try', '>= 1.1.0', '< 2.0' - s.add_runtime_dependency 'molinillo', '~> 0.7.0' - s.add_runtime_dependency 'xcodeproj', '>= 1.19.0', '< 2.0' + s.add_runtime_dependency 'molinillo', '~> 0.8.0' + s.add_runtime_dependency 'xcodeproj', '>= 1.21.0', '< 2.0' s.add_runtime_dependency 'colored2', '~> 3.1' s.add_runtime_dependency 'escape', '~> 0.0.4' s.add_runtime_dependency 'fourflusher', '>= 2.3.0', '< 3.0' s.add_runtime_dependency 'gh_inspector', '~> 1.0' s.add_runtime_dependency 'nap', '~> 1.0' - s.add_runtime_dependency 'ruby-macho', '~> 1.4' + s.add_runtime_dependency 'ruby-macho', '>= 1.0', '< 3.0' - s.add_runtime_dependency 'addressable', '~> 2.6' + s.add_runtime_dependency 'addressable', '~> 2.8' s.add_development_dependency 'bacon', '~> 1.1' - s.add_development_dependency 'bundler', '~> 1.3' + s.add_development_dependency 'bundler', '~> 2.0' s.add_development_dependency 'rake', '~> 10.0' - ## Make sure you can build the gem on older versions of RubyGems too: - s.rubygems_version = "1.6.2" - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.required_ruby_version = '>= 2.3.3' - s.specification_version = 3 if s.respond_to? :specification_version + s.required_ruby_version = '>= 2.6' end diff --git a/examples/AppCenter Example/Examples.xcworkspace/contents.xcworkspacedata b/examples/AppCenter Example/Examples.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..0210f1c87d --- /dev/null +++ b/examples/AppCenter Example/Examples.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/examples/AppCenter Example/Examples.xcworkspace/xcshareddata/Examples.xcscmblueprint b/examples/AppCenter Example/Examples.xcworkspace/xcshareddata/Examples.xcscmblueprint new file mode 100644 index 0000000000..0311ab3f57 --- /dev/null +++ b/examples/AppCenter Example/Examples.xcworkspace/xcshareddata/Examples.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "9B3204A8D3160EB3616BC7CB1D3FCCFBB4BF3F2C", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "9B3204A8D3160EB3616BC7CB1D3FCCFBB4BF3F2C" : 9223372036854775807, + "9F9800D332981B4632368512DE7ED0F103520D36" : 9223372036854775807 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "421F3881-3A8F-419B-97D3-792E652539B9", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "9B3204A8D3160EB3616BC7CB1D3FCCFBB4BF3F2C" : "CocoaPods\/", + "9F9800D332981B4632368512DE7ED0F103520D36" : "" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "Examples", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "examples\/Alamofire Example\/Examples.xcworkspace", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:CocoaPods\/CocoaPods.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "9B3204A8D3160EB3616BC7CB1D3FCCFBB4BF3F2C" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/CocoaPods\/Rainforest.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "9F9800D332981B4632368512DE7ED0F103520D36" + } + ] +} \ No newline at end of file diff --git a/examples/AppCenter Example/Examples.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/AppCenter Example/Examples.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/examples/AppCenter Example/Examples.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/AppCenter Example/Podfile b/examples/AppCenter Example/Podfile new file mode 100644 index 0000000000..3def41ea2f --- /dev/null +++ b/examples/AppCenter Example/Podfile @@ -0,0 +1,13 @@ +if (repo = ENV['COCOAPODS_SPEC_REPO']) + source "#{repo}" +end + +workspace 'Examples.xcworkspace' +project 'iOS Example.xcodeproj' + +target 'iOS Example' do + platform :ios, '9.0' + use_frameworks! + pod 'AppCenter', '4.2.0' +end + diff --git a/examples/AppCenter Example/Source/AppDelegate.swift b/examples/AppCenter Example/Source/AppDelegate.swift new file mode 100644 index 0000000000..ecd2f440dc --- /dev/null +++ b/examples/AppCenter Example/Source/AppDelegate.swift @@ -0,0 +1,36 @@ +// +// AppDelegate.swift +// iOS Example +// +// Created by Dimitris Koutsogiorgas on 8/4/21. +// Copyright © 2021 AppCenter Example. All rights reserved. +// + +import UIKit +import AppCenter +import AppCenterAnalytics +import AppCenterCrashes + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self]) + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } +} diff --git a/examples/AppCenter Example/Source/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/AppCenter Example/Source/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..eb87897008 --- /dev/null +++ b/examples/AppCenter Example/Source/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/AppCenter Example/Source/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/AppCenter Example/Source/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..9221b9bb1a --- /dev/null +++ b/examples/AppCenter Example/Source/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/AppCenter Example/Source/Assets.xcassets/Contents.json b/examples/AppCenter Example/Source/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/examples/AppCenter Example/Source/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/AppCenter Example/Source/Base.lproj/LaunchScreen.storyboard b/examples/AppCenter Example/Source/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000..865e9329f3 --- /dev/null +++ b/examples/AppCenter Example/Source/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/AppCenter Example/Source/Base.lproj/Main.storyboard b/examples/AppCenter Example/Source/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..25a763858e --- /dev/null +++ b/examples/AppCenter Example/Source/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/AppCenter Example/Source/Info.plist b/examples/AppCenter Example/Source/Info.plist new file mode 100644 index 0000000000..dd3c9afdae --- /dev/null +++ b/examples/AppCenter Example/Source/Info.plist @@ -0,0 +1,25 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + + diff --git a/examples/AppCenter Example/Source/SceneDelegate.swift b/examples/AppCenter Example/Source/SceneDelegate.swift new file mode 100644 index 0000000000..e25103b1f4 --- /dev/null +++ b/examples/AppCenter Example/Source/SceneDelegate.swift @@ -0,0 +1,49 @@ +// +// SceneDelegate.swift +// iOS Example +// +// Created by Dimitris Koutsogiorgas on 8/4/21. +// Copyright © 2021 AppCenter Example. All rights reserved. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } +} diff --git a/examples/AppCenter Example/Source/ViewController.swift b/examples/AppCenter Example/Source/ViewController.swift new file mode 100644 index 0000000000..dc7c764a40 --- /dev/null +++ b/examples/AppCenter Example/Source/ViewController.swift @@ -0,0 +1,17 @@ +// +// ViewController.swift +// iOS Example +// +// Created by Dimitris Koutsogiorgas on 8/4/21. +// Copyright © 2021 AppCenter Example. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } +} diff --git a/examples/AppCenter Example/iOS Example.xcodeproj/project.pbxproj b/examples/AppCenter Example/iOS Example.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..eb36f09b91 --- /dev/null +++ b/examples/AppCenter Example/iOS Example.xcodeproj/project.pbxproj @@ -0,0 +1,424 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + B7AF655926BB276800B110C3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7AF655826BB276800B110C3 /* AppDelegate.swift */; }; + B7AF655B26BB276800B110C3 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7AF655A26BB276800B110C3 /* SceneDelegate.swift */; }; + B7AF655D26BB276800B110C3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7AF655C26BB276800B110C3 /* ViewController.swift */; }; + B7AF656026BB276800B110C3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B7AF655E26BB276800B110C3 /* Main.storyboard */; }; + B7AF656226BB276900B110C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B7AF656126BB276900B110C3 /* Assets.xcassets */; }; + B7AF656526BB276900B110C3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B7AF656326BB276900B110C3 /* LaunchScreen.storyboard */; }; + D5C46134CB36A7DACC0BCB81 /* Pods_iOS_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F6B1B2EDDA11E881E41FEC2 /* Pods_iOS_Example.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 32E57E48A641215EE938A9F4 /* Pods-iOS Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS Example.debug.xcconfig"; path = "Target Support Files/Pods-iOS Example/Pods-iOS Example.debug.xcconfig"; sourceTree = ""; }; + 4F6B1B2EDDA11E881E41FEC2 /* Pods_iOS_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iOS_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7E5904356E33E2E78515F010 /* Pods-iOS Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS Example.release.xcconfig"; path = "Target Support Files/Pods-iOS Example/Pods-iOS Example.release.xcconfig"; sourceTree = ""; }; + B7AF655626BB276800B110C3 /* iOS Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + B7AF655826BB276800B110C3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + B7AF655A26BB276800B110C3 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + B7AF655C26BB276800B110C3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + B7AF655F26BB276800B110C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + B7AF656126BB276900B110C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + B7AF656426BB276900B110C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + B7AF656626BB276900B110C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B7AF655326BB276800B110C3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D5C46134CB36A7DACC0BCB81 /* Pods_iOS_Example.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8AE89EDB3E4608D5851224F5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4F6B1B2EDDA11E881E41FEC2 /* Pods_iOS_Example.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + B7AF655726BB276800B110C3 /* Source */ = { + isa = PBXGroup; + children = ( + B7AF655826BB276800B110C3 /* AppDelegate.swift */, + B7AF655A26BB276800B110C3 /* SceneDelegate.swift */, + B7AF655C26BB276800B110C3 /* ViewController.swift */, + B7AF655E26BB276800B110C3 /* Main.storyboard */, + B7AF656126BB276900B110C3 /* Assets.xcassets */, + B7AF656326BB276900B110C3 /* LaunchScreen.storyboard */, + B7AF656626BB276900B110C3 /* Info.plist */, + ); + path = Source; + sourceTree = ""; + }; + E8DBABB31D3A1E1E4FC8DC4B /* Pods */ = { + isa = PBXGroup; + children = ( + 32E57E48A641215EE938A9F4 /* Pods-iOS Example.debug.xcconfig */, + 7E5904356E33E2E78515F010 /* Pods-iOS Example.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + F8111DFC19A951050040E7D1 = { + isa = PBXGroup; + children = ( + B7AF655726BB276800B110C3 /* Source */, + F8111E0619A951050040E7D1 /* Products */, + E8DBABB31D3A1E1E4FC8DC4B /* Pods */, + 8AE89EDB3E4608D5851224F5 /* Frameworks */, + ); + sourceTree = ""; + }; + F8111E0619A951050040E7D1 /* Products */ = { + isa = PBXGroup; + children = ( + B7AF655626BB276800B110C3 /* iOS Example.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + B7AF655526BB276800B110C3 /* iOS Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = B7AF656926BB276900B110C3 /* Build configuration list for PBXNativeTarget "iOS Example" */; + buildPhases = ( + 500C42F1ECCB1962C0B1B6E3 /* [CP] Check Pods Manifest.lock */, + B7AF655226BB276800B110C3 /* Sources */, + B7AF655326BB276800B110C3 /* Frameworks */, + B7AF655426BB276800B110C3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "iOS Example"; + productName = "iOS Example 2"; + productReference = B7AF655626BB276800B110C3 /* iOS Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + F8111DFD19A951050040E7D1 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1300; + LastUpgradeCheck = 0600; + ORGANIZATIONNAME = "AppCenter Example"; + TargetAttributes = { + B7AF655526BB276800B110C3 = { + CreatedOnToolsVersion = 13.0; + DevelopmentTeam = H5F7XRWJGF; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = F8111E0019A951050040E7D1 /* Build configuration list for PBXProject "iOS Example" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = F8111DFC19A951050040E7D1; + productRefGroup = F8111E0619A951050040E7D1 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B7AF655526BB276800B110C3 /* iOS Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + B7AF655426BB276800B110C3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B7AF656526BB276900B110C3 /* LaunchScreen.storyboard in Resources */, + B7AF656226BB276900B110C3 /* Assets.xcassets in Resources */, + B7AF656026BB276800B110C3 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 500C42F1ECCB1962C0B1B6E3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-iOS Example-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + B7AF655226BB276800B110C3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B7AF655D26BB276800B110C3 /* ViewController.swift in Sources */, + B7AF655926BB276800B110C3 /* AppDelegate.swift in Sources */, + B7AF655B26BB276800B110C3 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + B7AF655E26BB276800B110C3 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + B7AF655F26BB276800B110C3 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + B7AF656326BB276900B110C3 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + B7AF656426BB276900B110C3 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + B7AF656726BB276900B110C3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 32E57E48A641215EE938A9F4 /* Pods-iOS Example.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = H5F7XRWJGF; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Source/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.iOS-Example-2"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + B7AF656826BB276900B110C3 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7E5904356E33E2E78515F010 /* Pods-iOS Example.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = H5F7XRWJGF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Source/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.iOS-Example-2"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + F8111E2119A951050040E7D1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + F8111E2219A951050040E7D1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B7AF656926BB276900B110C3 /* Build configuration list for PBXNativeTarget "iOS Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B7AF656726BB276900B110C3 /* Debug */, + B7AF656826BB276900B110C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F8111E0019A951050040E7D1 /* Build configuration list for PBXProject "iOS Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F8111E2119A951050040E7D1 /* Debug */, + F8111E2219A951050040E7D1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = F8111DFD19A951050040E7D1 /* Project object */; +} diff --git a/examples/AppCenter Example/iOS Example.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme b/examples/AppCenter Example/iOS Example.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme new file mode 100644 index 0000000000..7f2b7cfcdb --- /dev/null +++ b/examples/AppCenter Example/iOS Example.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/Headers Example/BarHeadersPod/Bar.h b/examples/Headers Example/BarHeadersPod/Bar.h new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/examples/Headers Example/BarHeadersPod/Bar.h @@ -0,0 +1 @@ + diff --git a/examples/Headers Example/BarHeadersPod/Bar.m b/examples/Headers Example/BarHeadersPod/Bar.m new file mode 100644 index 0000000000..b4932f96b3 --- /dev/null +++ b/examples/Headers Example/BarHeadersPod/Bar.m @@ -0,0 +1 @@ +#import "Bar_Private.h" diff --git a/examples/Headers Example/BarHeadersPod/BarHeadersPod.podspec b/examples/Headers Example/BarHeadersPod/BarHeadersPod.podspec new file mode 100644 index 0000000000..aa2fd2abf6 --- /dev/null +++ b/examples/Headers Example/BarHeadersPod/BarHeadersPod.podspec @@ -0,0 +1,21 @@ +Pod::Spec.new do |s| + s.name = 'BarHeadersPod' + s.version = '0.1.0' + s.summary = 'Demonstrates using a set of different headers.' + s.description = <<-DESC + * has public headers + * has private headers + DESC + s.source = { :git => 'https://github.com/CocoaPods/CocoaPods.git', :tag => "v#{s.version}" } + s.homepage = "https://github.com/CocoaPods/CocoaPods" + s.author = { 'Example' => 'help@example.org' } + s.license = { :type => 'MIT', :file => '../../../LICENSE' } + + s.source_files = '*.{m,h}' + + s.public_header_files = 'Bar.h' + s.private_header_files = 'Bar_Project.h' + + s.osx.deployment_target = '10.9' + s.ios.deployment_target = '13.0' +end diff --git a/examples/Headers Example/BarHeadersPod/Bar_Private.h b/examples/Headers Example/BarHeadersPod/Bar_Private.h new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/examples/Headers Example/BarHeadersPod/Bar_Private.h @@ -0,0 +1 @@ + diff --git a/examples/Headers Example/Examples.xcworkspace/contents.xcworkspacedata b/examples/Headers Example/Examples.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..500612a2dc --- /dev/null +++ b/examples/Headers Example/Examples.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/examples/Headers Example/Examples.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/Headers Example/Examples.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/examples/Headers Example/Examples.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/Headers Example/FooHeadersPod/Foo.h b/examples/Headers Example/FooHeadersPod/Foo.h new file mode 100644 index 0000000000..cd78caf0ab --- /dev/null +++ b/examples/Headers Example/FooHeadersPod/Foo.h @@ -0,0 +1 @@ +#import diff --git a/examples/Headers Example/FooHeadersPod/Foo.m b/examples/Headers Example/FooHeadersPod/Foo.m new file mode 100644 index 0000000000..39351440a6 --- /dev/null +++ b/examples/Headers Example/FooHeadersPod/Foo.m @@ -0,0 +1,2 @@ +#import "Foo_Private.h" +#import "Foo_Project.h" diff --git a/examples/Headers Example/FooHeadersPod/FooHeadersPod.podspec b/examples/Headers Example/FooHeadersPod/FooHeadersPod.podspec new file mode 100644 index 0000000000..485d5e9399 --- /dev/null +++ b/examples/Headers Example/FooHeadersPod/FooHeadersPod.podspec @@ -0,0 +1,25 @@ +Pod::Spec.new do |s| + s.name = 'FooHeadersPod' + s.version = '0.1.0' + s.summary = 'Demonstrates using a set of different headers.' + s.description = <<-DESC + * has public headers + * has project headers + * has private headers + DESC + s.source = { :git => 'https://github.com/CocoaPods/CocoaPods.git', :tag => "v#{s.version}" } + s.homepage = "https://github.com/CocoaPods/CocoaPods" + s.author = { 'Example' => 'help@example.org' } + s.license = { :type => 'MIT', :file => '../../../LICENSE' } + + s.source_files = '*.{m,h}' + + s.public_header_files = 'Foo.h' + s.project_header_files = 'Foo_Project.h' + s.private_header_files = 'Foo_Private.h' + + s.osx.deployment_target = '10.9' + s.ios.deployment_target = '13.0' + + s.dependency 'BarHeadersPod' +end diff --git a/examples/Headers Example/FooHeadersPod/Foo_Private.h b/examples/Headers Example/FooHeadersPod/Foo_Private.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/Headers Example/FooHeadersPod/Foo_Project.h b/examples/Headers Example/FooHeadersPod/Foo_Project.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/Headers Example/Headers Example.xcodeproj/project.pbxproj b/examples/Headers Example/Headers Example.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..1751ea8829 --- /dev/null +++ b/examples/Headers Example/Headers Example.xcodeproj/project.pbxproj @@ -0,0 +1,363 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 295BB5621CEA95DE00E79F82 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 295BB5611CEA95DE00E79F82 /* AppDelegate.swift */; }; + 295BB5641CEA95DE00E79F82 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 295BB5631CEA95DE00E79F82 /* Assets.xcassets */; }; + 44CEACDCCD13E316EE074DA1 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + B4B33EF6E0070B20B05555D6 /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F60F2D3508AE8ED06682EB7 /* Pods_App.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 295BB55E1CEA95DE00E79F82 /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 295BB5611CEA95DE00E79F82 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 295BB5631CEA95DE00E79F82 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 295BB5681CEA95DE00E79F82 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 4F60F2D3508AE8ED06682EB7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8914945168DAAA34EFE099AF /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; + E1928C2D408B1D2E8B3E2FA3 /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 295BB55B1CEA95DE00E79F82 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 44CEACDCCD13E316EE074DA1 /* (null) in Frameworks */, + B4B33EF6E0070B20B05555D6 /* Pods_App.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 295BB5551CEA95DE00E79F82 = { + isa = PBXGroup; + children = ( + 83215639ECD12CBC1F4DC4E3 /* Frameworks */, + 295BB5601CEA95DE00E79F82 /* Headers Example */, + 66AD76830CE2BBB6379CA47B /* Pods */, + 295BB55F1CEA95DE00E79F82 /* Products */, + ); + sourceTree = ""; + }; + 295BB55F1CEA95DE00E79F82 /* Products */ = { + isa = PBXGroup; + children = ( + 295BB55E1CEA95DE00E79F82 /* App.app */, + ); + name = Products; + sourceTree = ""; + }; + 295BB5601CEA95DE00E79F82 /* Headers Example */ = { + isa = PBXGroup; + children = ( + 295BB5611CEA95DE00E79F82 /* AppDelegate.swift */, + 295BB5631CEA95DE00E79F82 /* Assets.xcassets */, + 295BB5681CEA95DE00E79F82 /* Info.plist */, + ); + path = "Headers Example"; + sourceTree = ""; + }; + 66AD76830CE2BBB6379CA47B /* Pods */ = { + isa = PBXGroup; + children = ( + E1928C2D408B1D2E8B3E2FA3 /* Pods-App.debug.xcconfig */, + 8914945168DAAA34EFE099AF /* Pods-App.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 83215639ECD12CBC1F4DC4E3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4F60F2D3508AE8ED06682EB7 /* Pods_App.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 295BB55D1CEA95DE00E79F82 /* App */ = { + isa = PBXNativeTarget; + buildConfigurationList = 295BB56B1CEA95DE00E79F82 /* Build configuration list for PBXNativeTarget "App" */; + buildPhases = ( + 62E9CD52D31153978437D4C2 /* [CP] Check Pods Manifest.lock */, + 295BB55A1CEA95DE00E79F82 /* Sources */, + 295BB55B1CEA95DE00E79F82 /* Frameworks */, + 295BB55C1CEA95DE00E79F82 /* Resources */, + 6E2B4891468DB661A63F8065 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = App; + productName = "HeaderMappingsDir Example"; + productReference = 295BB55E1CEA95DE00E79F82 /* App.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 295BB5561CEA95DE00E79F82 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = CocoaPods; + TargetAttributes = { + 295BB55D1CEA95DE00E79F82 = { + CreatedOnToolsVersion = 7.3; + }; + }; + }; + buildConfigurationList = 295BB5591CEA95DE00E79F82 /* Build configuration list for PBXProject "Headers Example" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 295BB5551CEA95DE00E79F82; + productRefGroup = 295BB55F1CEA95DE00E79F82 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 295BB55D1CEA95DE00E79F82 /* App */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 295BB55C1CEA95DE00E79F82 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 295BB5641CEA95DE00E79F82 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 62E9CD52D31153978437D4C2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 6E2B4891468DB661A63F8065 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/BarHeadersPod/BarHeadersPod.framework", + "${BUILT_PRODUCTS_DIR}/FooHeadersPod/FooHeadersPod.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BarHeadersPod.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FooHeadersPod.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 295BB55A1CEA95DE00E79F82 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 295BB5621CEA95DE00E79F82 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 295BB5691CEA95DE00E79F82 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 295BB56A1CEA95DE00E79F82 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; + 295BB56C1CEA95DE00E79F82 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E1928C2D408B1D2E8B3E2FA3 /* Pods-App.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "Headers Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.HeaderMappingsDir-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTS_MACCATALYST = YES; + TARGETED_DEVICE_FAMILY = "1,2,4"; + }; + name = Debug; + }; + 295BB56D1CEA95DE00E79F82 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8914945168DAAA34EFE099AF /* Pods-App.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "Headers Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.HeaderMappingsDir-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SUPPORTS_MACCATALYST = YES; + TARGETED_DEVICE_FAMILY = "1,2,4"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 295BB5591CEA95DE00E79F82 /* Build configuration list for PBXProject "Headers Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 295BB5691CEA95DE00E79F82 /* Debug */, + 295BB56A1CEA95DE00E79F82 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 295BB56B1CEA95DE00E79F82 /* Build configuration list for PBXNativeTarget "App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 295BB56C1CEA95DE00E79F82 /* Debug */, + 295BB56D1CEA95DE00E79F82 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 295BB5561CEA95DE00E79F82 /* Project object */; +} diff --git a/examples/Headers Example/Headers Example.xcodeproj/xcshareddata/xcschemes/Headers Example.xcscheme b/examples/Headers Example/Headers Example.xcodeproj/xcshareddata/xcschemes/Headers Example.xcscheme new file mode 100644 index 0000000000..28723f2ec7 --- /dev/null +++ b/examples/Headers Example/Headers Example.xcodeproj/xcshareddata/xcschemes/Headers Example.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/Headers Example/Headers Example/AppDelegate.swift b/examples/Headers Example/Headers Example/AppDelegate.swift new file mode 100644 index 0000000000..3f65b4542e --- /dev/null +++ b/examples/Headers Example/Headers Example/AppDelegate.swift @@ -0,0 +1,23 @@ + +import FooHeadersPod +import BarHeadersPod + +#if os(iOS) + +import UIKit +@UIApplicationMain +class AppDelegate: NSObject, UIApplicationDelegate { + + @IBOutlet weak var window: UIWindow? +} + +#else + +import Cocoa +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + @IBOutlet weak var window: NSWindow! +} + +#endif diff --git a/examples/Headers Example/Headers Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/Headers Example/Headers Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..2db2b1c7c6 --- /dev/null +++ b/examples/Headers Example/Headers Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/Headers Example/Headers Example/Info.plist b/examples/Headers Example/Headers Example/Info.plist new file mode 100644 index 0000000000..f610b24263 --- /dev/null +++ b/examples/Headers Example/Headers Example/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 CocoaPods. All rights reserved. + NSPrincipalClass + NSApplication + + diff --git a/examples/Headers Example/Podfile b/examples/Headers Example/Podfile new file mode 100644 index 0000000000..5f060986b0 --- /dev/null +++ b/examples/Headers Example/Podfile @@ -0,0 +1,14 @@ +if (repo = ENV['COCOAPODS_SPEC_REPO']) + source "#{repo}" +end + +use_frameworks! + +workspace 'Examples.xcworkspace' +project 'Headers Example.xcodeproj' + +target 'App' do + platform :osx, '10.9' + pod 'FooHeadersPod', :path => 'FooHeadersPod' + pod 'BarHeadersPod', :path => 'BarHeadersPod' +end diff --git a/examples/OnDemandResources Example/Examples.xcworkspace/contents.xcworkspacedata b/examples/OnDemandResources Example/Examples.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..ec2a970600 --- /dev/null +++ b/examples/OnDemandResources Example/Examples.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo.xcodeproj/project.pbxproj b/examples/OnDemandResources Example/OnDemandResourcesDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..759b634a7f --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo.xcodeproj/project.pbxproj @@ -0,0 +1,456 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 5692934B2420BEDF00E13D4A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5692934A2420BEDF00E13D4A /* AppDelegate.m */; }; + 5692934E2420BEDF00E13D4A /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5692934D2420BEDF00E13D4A /* SceneDelegate.m */; }; + 569293512420BEDF00E13D4A /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 569293502420BEDF00E13D4A /* ViewController.m */; }; + 569293542420BEDF00E13D4A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 569293522420BEDF00E13D4A /* Main.storyboard */; }; + 569293562420BEE000E13D4A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 569293552420BEE000E13D4A /* Assets.xcassets */; }; + 569293592420BEE000E13D4A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 569293572420BEE000E13D4A /* LaunchScreen.storyboard */; }; + 5692935C2420BEE000E13D4A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5692935B2420BEE000E13D4A /* main.m */; }; + 6AC13EEBF0C02C2C2891C42D /* resource in Resources */ = {isa = PBXBuildFile; fileRef = 9EAFB14061A670BEACE5FCDE /* resource */; settings = {ASSET_TAGS = (t2, ); }; }; + 9E8BD66B51D4C2D4A5E102FD /* Pods_OnDemandResourcesDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67EC8C18D6B5C5D494A3A182 /* Pods_OnDemandResourcesDemo.framework */; }; + AD83258E3FF042BEDA475E37 /* on1_sub1 in Resources */ = {isa = PBXBuildFile; fileRef = 60073269DE805D2E252FD2CE /* on1_sub1 */; settings = {ASSET_TAGS = (t1, ); }; }; + E26C8974A0B1965FA8DE40B7 /* resource in Resources */ = {isa = PBXBuildFile; fileRef = 4D89CDF3C406CB7D630E7655 /* resource */; settings = {ASSET_TAGS = (t1, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0A20343E5E6B8B65EC4B04CD /* Pods-OnDemandResourcesDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OnDemandResourcesDemo.debug.xcconfig"; path = "Target Support Files/Pods-OnDemandResourcesDemo/Pods-OnDemandResourcesDemo.debug.xcconfig"; sourceTree = ""; }; + 4D89CDF3C406CB7D630E7655 /* resource */ = {isa = PBXFileReference; includeInIndex = 1; name = resource; path = ../TestLibrary/on_demand_bundle1/resource; sourceTree = ""; }; + 569293462420BEDF00E13D4A /* OnDemandResourcesDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OnDemandResourcesDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 569293492420BEDF00E13D4A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 5692934A2420BEDF00E13D4A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 5692934C2420BEDF00E13D4A /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; + 5692934D2420BEDF00E13D4A /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; }; + 5692934F2420BEDF00E13D4A /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 569293502420BEDF00E13D4A /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 569293532420BEDF00E13D4A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 569293552420BEE000E13D4A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 569293582420BEE000E13D4A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 5692935A2420BEE000E13D4A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5692935B2420BEE000E13D4A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 60073269DE805D2E252FD2CE /* on1_sub1 */ = {isa = PBXFileReference; includeInIndex = 1; name = on1_sub1; path = ../TestLibrary/on_demand_bundle1/on1_sub1; sourceTree = ""; }; + 67EC8C18D6B5C5D494A3A182 /* Pods_OnDemandResourcesDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OnDemandResourcesDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 79A18D27CEBB4A04D2C3527A /* Pods-OnDemandResourcesDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OnDemandResourcesDemo.release.xcconfig"; path = "Target Support Files/Pods-OnDemandResourcesDemo/Pods-OnDemandResourcesDemo.release.xcconfig"; sourceTree = ""; }; + 9EAFB14061A670BEACE5FCDE /* resource */ = {isa = PBXFileReference; includeInIndex = 1; name = resource; path = ../TestLibrary/on_demand_bundle2/resource; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 569293432420BEDF00E13D4A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9E8BD66B51D4C2D4A5E102FD /* Pods_OnDemandResourcesDemo.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0BF35FC55571FFD35310F216 /* Pods */ = { + isa = PBXGroup; + children = ( + 0A20343E5E6B8B65EC4B04CD /* Pods-OnDemandResourcesDemo.debug.xcconfig */, + 79A18D27CEBB4A04D2C3527A /* Pods-OnDemandResourcesDemo.release.xcconfig */, + E65BB08C42D68766114C3D4F /* TestLibrary-OnDemandResources */, + ); + path = Pods; + sourceTree = ""; + }; + 42C1ACF142C607E85E720165 /* t1 */ = { + isa = PBXGroup; + children = ( + 4D89CDF3C406CB7D630E7655 /* resource */, + 60073269DE805D2E252FD2CE /* on1_sub1 */, + ); + name = t1; + sourceTree = ""; + }; + 5692933D2420BEDF00E13D4A = { + isa = PBXGroup; + children = ( + 569293482420BEDF00E13D4A /* OnDemandResourcesDemo */, + 569293472420BEDF00E13D4A /* Products */, + 0BF35FC55571FFD35310F216 /* Pods */, + 6F84E045D20395066A43950A /* Frameworks */, + ); + sourceTree = ""; + }; + 569293472420BEDF00E13D4A /* Products */ = { + isa = PBXGroup; + children = ( + 569293462420BEDF00E13D4A /* OnDemandResourcesDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 569293482420BEDF00E13D4A /* OnDemandResourcesDemo */ = { + isa = PBXGroup; + children = ( + 569293492420BEDF00E13D4A /* AppDelegate.h */, + 5692934A2420BEDF00E13D4A /* AppDelegate.m */, + 5692934C2420BEDF00E13D4A /* SceneDelegate.h */, + 5692934D2420BEDF00E13D4A /* SceneDelegate.m */, + 5692934F2420BEDF00E13D4A /* ViewController.h */, + 569293502420BEDF00E13D4A /* ViewController.m */, + 569293522420BEDF00E13D4A /* Main.storyboard */, + 569293552420BEE000E13D4A /* Assets.xcassets */, + 569293572420BEE000E13D4A /* LaunchScreen.storyboard */, + 5692935A2420BEE000E13D4A /* Info.plist */, + 5692935B2420BEE000E13D4A /* main.m */, + ); + path = OnDemandResourcesDemo; + sourceTree = ""; + }; + 6F84E045D20395066A43950A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 67EC8C18D6B5C5D494A3A182 /* Pods_OnDemandResourcesDemo.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + D1EEE83485BB57DD90438A55 /* t2 */ = { + isa = PBXGroup; + children = ( + 9EAFB14061A670BEACE5FCDE /* resource */, + ); + name = t2; + sourceTree = ""; + }; + E65BB08C42D68766114C3D4F /* TestLibrary-OnDemandResources */ = { + isa = PBXGroup; + children = ( + 42C1ACF142C607E85E720165 /* t1 */, + D1EEE83485BB57DD90438A55 /* t2 */, + ); + name = "TestLibrary-OnDemandResources"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 569293452420BEDF00E13D4A /* OnDemandResourcesDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5692935F2420BEE000E13D4A /* Build configuration list for PBXNativeTarget "OnDemandResourcesDemo" */; + buildPhases = ( + BB7725E96B02D3ED1481B54A /* [CP] Check Pods Manifest.lock */, + 569293422420BEDF00E13D4A /* Sources */, + 569293432420BEDF00E13D4A /* Frameworks */, + 569293442420BEDF00E13D4A /* Resources */, + CCEFF20AD59216CD1B2A7804 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OnDemandResourcesDemo; + productName = OnDemandResourcesDemo; + productReference = 569293462420BEDF00E13D4A /* OnDemandResourcesDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5692933E2420BEDF00E13D4A /* Project object */ = { + isa = PBXProject; + attributes = { + KnownAssetTags = ( + t1, + t2, + ); + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = xiejunyi; + TargetAttributes = { + 569293452420BEDF00E13D4A = { + CreatedOnToolsVersion = 11.3.1; + }; + }; + }; + buildConfigurationList = 569293412420BEDF00E13D4A /* Build configuration list for PBXProject "OnDemandResourcesDemo" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 5692933D2420BEDF00E13D4A; + productRefGroup = 569293472420BEDF00E13D4A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 569293452420BEDF00E13D4A /* OnDemandResourcesDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 569293442420BEDF00E13D4A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 569293592420BEE000E13D4A /* LaunchScreen.storyboard in Resources */, + 569293562420BEE000E13D4A /* Assets.xcassets in Resources */, + 569293542420BEDF00E13D4A /* Main.storyboard in Resources */, + E26C8974A0B1965FA8DE40B7 /* resource in Resources */, + AD83258E3FF042BEDA475E37 /* on1_sub1 in Resources */, + 6AC13EEBF0C02C2C2891C42D /* resource in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + BB7725E96B02D3ED1481B54A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-OnDemandResourcesDemo-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + CCEFF20AD59216CD1B2A7804 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-OnDemandResourcesDemo/Pods-OnDemandResourcesDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-OnDemandResourcesDemo/Pods-OnDemandResourcesDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-OnDemandResourcesDemo/Pods-OnDemandResourcesDemo-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 569293422420BEDF00E13D4A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 569293512420BEDF00E13D4A /* ViewController.m in Sources */, + 5692934B2420BEDF00E13D4A /* AppDelegate.m in Sources */, + 5692935C2420BEE000E13D4A /* main.m in Sources */, + 5692934E2420BEDF00E13D4A /* SceneDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 569293522420BEDF00E13D4A /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 569293532420BEDF00E13D4A /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 569293572420BEE000E13D4A /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 569293582420BEE000E13D4A /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 5692935D2420BEE000E13D4A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 5692935E2420BEE000E13D4A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 569293602420BEE000E13D4A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0A20343E5E6B8B65EC4B04CD /* Pods-OnDemandResourcesDemo.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = OnDemandResourcesDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + ON_DEMAND_RESOURCES_PREFETCH_ORDER = t2; + PRODUCT_BUNDLE_IDENTIFIER = com.junyixie..OnDemandResourcesDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 569293612420BEE000E13D4A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 79A18D27CEBB4A04D2C3527A /* Pods-OnDemandResourcesDemo.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = OnDemandResourcesDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + ON_DEMAND_RESOURCES_PREFETCH_ORDER = t2; + PRODUCT_BUNDLE_IDENTIFIER = com.junyixie..OnDemandResourcesDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 569293412420BEDF00E13D4A /* Build configuration list for PBXProject "OnDemandResourcesDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5692935D2420BEE000E13D4A /* Debug */, + 5692935E2420BEE000E13D4A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5692935F2420BEE000E13D4A /* Build configuration list for PBXNativeTarget "OnDemandResourcesDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 569293602420BEE000E13D4A /* Debug */, + 569293612420BEE000E13D4A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5692933E2420BEDF00E13D4A /* Project object */; +} diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/AppDelegate.h b/examples/OnDemandResources Example/OnDemandResourcesDemo/AppDelegate.h new file mode 100644 index 0000000000..8085cd7872 --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// OnDemandResourcesDemo +// +// Created by xiejunyi on 2020/3/17. +// Copyright © 2020 xiejunyi. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + + +@end + diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/AppDelegate.m b/examples/OnDemandResources Example/OnDemandResourcesDemo/AppDelegate.m new file mode 100644 index 0000000000..d4e54670ee --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// OnDemandResourcesDemo +// +// Created by xiejunyi on 2020/3/17. +// Copyright © 2020 xiejunyi. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + + +#pragma mark - UISceneSession lifecycle + + +- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role]; +} + + +- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet *)sceneSessions { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. +} + + +@end diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/OnDemandResources Example/OnDemandResourcesDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..d8db8d65fd --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/Assets.xcassets/Contents.json b/examples/OnDemandResources Example/OnDemandResourcesDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/Base.lproj/LaunchScreen.storyboard b/examples/OnDemandResources Example/OnDemandResourcesDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000..865e9329f3 --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/Base.lproj/Main.storyboard b/examples/OnDemandResources Example/OnDemandResourcesDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..808a21ce77 --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/Info.plist b/examples/OnDemandResources Example/OnDemandResourcesDemo/Info.plist new file mode 100644 index 0000000000..7b6037c25e --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/SceneDelegate.h b/examples/OnDemandResources Example/OnDemandResourcesDemo/SceneDelegate.h new file mode 100644 index 0000000000..1a73a59e68 --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/SceneDelegate.h @@ -0,0 +1,16 @@ +// +// SceneDelegate.h +// OnDemandResourcesDemo +// +// Created by xiejunyi on 2020/3/17. +// Copyright © 2020 xiejunyi. All rights reserved. +// + +#import + +@interface SceneDelegate : UIResponder + +@property (strong, nonatomic) UIWindow * window; + +@end + diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/SceneDelegate.m b/examples/OnDemandResources Example/OnDemandResourcesDemo/SceneDelegate.m new file mode 100644 index 0000000000..d6698dd7cb --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/SceneDelegate.m @@ -0,0 +1,50 @@ +#import "SceneDelegate.h" + +@interface SceneDelegate () + +@end + +@implementation SceneDelegate + + +- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). +} + + +- (void)sceneDidDisconnect:(UIScene *)scene { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). +} + + +- (void)sceneDidBecomeActive:(UIScene *)scene { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. +} + + +- (void)sceneWillResignActive:(UIScene *)scene { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). +} + + +- (void)sceneWillEnterForeground:(UIScene *)scene { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. +} + + +- (void)sceneDidEnterBackground:(UIScene *)scene { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. +} + + +@end diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/ViewController.h b/examples/OnDemandResources Example/OnDemandResourcesDemo/ViewController.h new file mode 100644 index 0000000000..c8a226b8cf --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// OnDemandResourcesDemo +// +// Created by xiejunyi on 2020/3/17. +// Copyright © 2020 xiejunyi. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/ViewController.m b/examples/OnDemandResources Example/OnDemandResourcesDemo/ViewController.m new file mode 100644 index 0000000000..7115dcba6c --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/ViewController.m @@ -0,0 +1,23 @@ +// +// ViewController.m +// OnDemandResourcesDemo +// +// Created by xiejunyi on 2020/3/17. +// Copyright © 2020 xiejunyi. All rights reserved. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + + +@end diff --git a/examples/OnDemandResources Example/OnDemandResourcesDemo/main.m b/examples/OnDemandResources Example/OnDemandResourcesDemo/main.m new file mode 100644 index 0000000000..d4c966d757 --- /dev/null +++ b/examples/OnDemandResources Example/OnDemandResourcesDemo/main.m @@ -0,0 +1,19 @@ +// +// main.m +// OnDemandResourcesDemo +// +// Created by xiejunyi on 2020/3/17. +// Copyright © 2020 xiejunyi. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + NSString * appDelegateClassName; + @autoreleasepool { + // Setup code that might create autoreleased objects goes here. + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +} diff --git a/examples/OnDemandResources Example/Podfile b/examples/OnDemandResources Example/Podfile new file mode 100644 index 0000000000..f700c43d9a --- /dev/null +++ b/examples/OnDemandResources Example/Podfile @@ -0,0 +1,12 @@ +workspace 'Examples.xcworkspace' +project 'OnDemandResourcesDemo.xcodeproj' + +target 'OnDemandResourcesDemo' do + platform :ios, '13.2' + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + pod 'TestLibrary', :path => './TestLibrary', :appspecs => ['App1', 'App2'], :testspecs => ['Tests'] + + # Pods for OnDemandResourcesDemo + +end diff --git a/examples/OnDemandResources Example/TestLibrary/App1/Classes/AppDelegate.swift b/examples/OnDemandResources Example/TestLibrary/App1/Classes/AppDelegate.swift new file mode 100644 index 0000000000..5769211821 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/App1/Classes/AppDelegate.swift @@ -0,0 +1,20 @@ +import UIKit + +class ViewController: UIViewController { + override func viewDidLoad() { + view.backgroundColor = .green + } +} + +@UIApplicationMain +class AppDelegate: NSObject, UIApplicationDelegate { + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + window?.rootViewController = UINavigationController(rootViewController: ViewController()) + window?.makeKeyAndVisible() + + return true + } +} diff --git a/examples/OnDemandResources Example/TestLibrary/App1/app1_on_demand_bundle1/resource b/examples/OnDemandResources Example/TestLibrary/App1/app1_on_demand_bundle1/resource new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/OnDemandResources Example/TestLibrary/App2/Classes/AppDelegate.swift b/examples/OnDemandResources Example/TestLibrary/App2/Classes/AppDelegate.swift new file mode 100644 index 0000000000..5769211821 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/App2/Classes/AppDelegate.swift @@ -0,0 +1,20 @@ +import UIKit + +class ViewController: UIViewController { + override func viewDidLoad() { + view.backgroundColor = .green + } +} + +@UIApplicationMain +class AppDelegate: NSObject, UIApplicationDelegate { + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + window?.rootViewController = UINavigationController(rootViewController: ViewController()) + window?.makeKeyAndVisible() + + return true + } +} diff --git a/examples/OnDemandResources Example/TestLibrary/App2/app2_on_demand_bundle1/resource b/examples/OnDemandResources Example/TestLibrary/App2/app2_on_demand_bundle1/resource new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/OnDemandResources Example/TestLibrary/Example/Podfile b/examples/OnDemandResources Example/TestLibrary/Example/Podfile new file mode 100644 index 0000000000..d30773f419 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/Podfile @@ -0,0 +1,6 @@ +use_frameworks! +target 'TestLibrary_Tests' do + pod 'TestLibrary', :path => '../' + + +end diff --git a/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcodeproj/project.pbxproj b/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..bec8444141 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcodeproj/project.pbxproj @@ -0,0 +1,395 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 01F2950BC73F180DBF3F7B08 /* Pods_TestLibrary_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26C2C317B4F0CF7BAED25827 /* Pods_TestLibrary_Tests.framework */; }; + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; + 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0FBF93E45BCAAFBB75A4E992 /* Pods-TestLibrary_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestLibrary_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-TestLibrary_Tests/Pods-TestLibrary_Tests.release.xcconfig"; sourceTree = ""; }; + 145FA18D62F802074B072A15 /* Pods-TestLibrary_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestLibrary_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TestLibrary_Tests/Pods-TestLibrary_Tests.debug.xcconfig"; sourceTree = ""; }; + 26C2C317B4F0CF7BAED25827 /* Pods_TestLibrary_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TestLibrary_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 313871E80E9F1127FD8FB8A9 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; + 3DE8448E3FCF84A1D316A16E /* TestLibrary.podspec */ = {isa = PBXFileReference; includeInIndex = 1; name = TestLibrary.podspec; path = ../TestLibrary.podspec; sourceTree = ""; }; + 51900F4B721964541F6C1099 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; name = README.md; path = ../README.md; sourceTree = ""; }; + 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 6003F5AE195388D20070C39A /* TestLibrary_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestLibrary_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; + 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 6003F5AB195388D20070C39A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, + 01F2950BC73F180DBF3F7B08 /* Pods_TestLibrary_Tests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6003F581195388D10070C39A = { + isa = PBXGroup; + children = ( + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, + 6003F5B5195388D20070C39A /* Tests */, + 6003F58C195388D20070C39A /* Frameworks */, + 6003F58B195388D20070C39A /* Products */, + C191746DE462E6085687FB63 /* Pods */, + ); + sourceTree = ""; + }; + 6003F58B195388D20070C39A /* Products */ = { + isa = PBXGroup; + children = ( + 6003F5AE195388D20070C39A /* TestLibrary_Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 6003F58C195388D20070C39A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6003F58D195388D20070C39A /* Foundation.framework */, + 6003F58F195388D20070C39A /* CoreGraphics.framework */, + 6003F591195388D20070C39A /* UIKit.framework */, + 6003F5AF195388D20070C39A /* XCTest.framework */, + 26C2C317B4F0CF7BAED25827 /* Pods_TestLibrary_Tests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 6003F5B5195388D20070C39A /* Tests */ = { + isa = PBXGroup; + children = ( + 6003F5BB195388D20070C39A /* Tests.m */, + 6003F5B6195388D20070C39A /* Supporting Files */, + ); + path = Tests; + sourceTree = ""; + }; + 6003F5B6195388D20070C39A /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6003F5B7195388D20070C39A /* Tests-Info.plist */, + 6003F5B8195388D20070C39A /* InfoPlist.strings */, + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { + isa = PBXGroup; + children = ( + 3DE8448E3FCF84A1D316A16E /* TestLibrary.podspec */, + 51900F4B721964541F6C1099 /* README.md */, + 313871E80E9F1127FD8FB8A9 /* LICENSE */, + ); + name = "Podspec Metadata"; + sourceTree = ""; + }; + C191746DE462E6085687FB63 /* Pods */ = { + isa = PBXGroup; + children = ( + 145FA18D62F802074B072A15 /* Pods-TestLibrary_Tests.debug.xcconfig */, + 0FBF93E45BCAAFBB75A4E992 /* Pods-TestLibrary_Tests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 6003F5AD195388D20070C39A /* TestLibrary_Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "TestLibrary_Tests" */; + buildPhases = ( + 94970AD7DC6172E36C30C22C /* [CP] Check Pods Manifest.lock */, + 6003F5AA195388D20070C39A /* Sources */, + 6003F5AB195388D20070C39A /* Frameworks */, + 6003F5AC195388D20070C39A /* Resources */, + CB4A848008B422E3212AE655 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TestLibrary_Tests; + productName = TestLibraryTests; + productReference = 6003F5AE195388D20070C39A /* TestLibrary_Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6003F582195388D10070C39A /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = Test; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "lizhuoli1126@126.com"; + TargetAttributes = { + 6003F5AD195388D20070C39A = { + TestTargetID = 6003F589195388D20070C39A; + }; + }; + }; + buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "TestLibrary" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6003F581195388D10070C39A; + productRefGroup = 6003F58B195388D20070C39A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6003F5AD195388D20070C39A /* TestLibrary_Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 6003F5AC195388D20070C39A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 94970AD7DC6172E36C30C22C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-TestLibrary_Tests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + CB4A848008B422E3212AE655 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-TestLibrary_Tests/Pods-TestLibrary_Tests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/TestLibrary/TestLibrary.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TestLibrary.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-TestLibrary_Tests/Pods-TestLibrary_Tests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 6003F5AA195388D20070C39A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6003F5BC195388D20070C39A /* Tests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 6003F5B9195388D20070C39A /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 6003F5BD195388D20070C39A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6003F5BE195388D20070C39A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6003F5C3195388D20070C39A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 145FA18D62F802074B072A15 /* Pods-TestLibrary_Tests.debug.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "Tests/Tests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestLibrary_Example.app/TestLibrary_Example"; + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + 6003F5C4195388D20070C39A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0FBF93E45BCAAFBB75A4E992 /* Pods-TestLibrary_Tests.release.xcconfig */; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; + INFOPLIST_FILE = "Tests/Tests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TestLibrary_Example.app/TestLibrary_Example"; + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 6003F585195388D10070C39A /* Build configuration list for PBXProject "TestLibrary" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6003F5BD195388D20070C39A /* Debug */, + 6003F5BE195388D20070C39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "TestLibrary_Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6003F5C3195388D20070C39A /* Debug */, + 6003F5C4195388D20070C39A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6003F582195388D10070C39A /* Project object */; +} diff --git a/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcodeproj/xcshareddata/xcschemes/TestLibrary-Example.xcscheme b/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcodeproj/xcshareddata/xcschemes/TestLibrary-Example.xcscheme new file mode 100644 index 0000000000..92fb3459de --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcodeproj/xcshareddata/xcschemes/TestLibrary-Example.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcworkspace/contents.xcworkspacedata b/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..16f286106b --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/TestLibrary.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests-Info.plist b/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests-Info.plist new file mode 100644 index 0000000000..169b6f710e --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests-Prefix.pch b/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests-Prefix.pch new file mode 100644 index 0000000000..0bfb741d05 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests-Prefix.pch @@ -0,0 +1,7 @@ +// The contents of this file are implicitly included at the beginning of every test case source file. + +#ifdef __OBJC__ + + + +#endif diff --git a/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests.m b/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests.m new file mode 100644 index 0000000000..09b5a61d48 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/Tests/Tests.m @@ -0,0 +1,35 @@ +// +// TestLibraryTests.m +// TestLibraryTests +// +// Created by lizhuoli1126@126.com on 01/18/2019. +// Copyright (c) 2019 lizhuoli1126@126.com. All rights reserved. +// + +@import XCTest; + +@interface Tests : XCTestCase + +@end + +@implementation Tests + +- (void)setUp +{ + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample +{ + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); +} + +@end + diff --git a/examples/OnDemandResources Example/TestLibrary/Example/Tests/en.lproj/InfoPlist.strings b/examples/OnDemandResources Example/TestLibrary/Example/Tests/en.lproj/InfoPlist.strings new file mode 100644 index 0000000000..477b28ff8f --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/Example/Tests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/examples/OnDemandResources Example/TestLibrary/LICENSE b/examples/OnDemandResources Example/TestLibrary/LICENSE new file mode 100644 index 0000000000..210c9a85d6 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019 lizhuoli1126@126.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary.podspec b/examples/OnDemandResources Example/TestLibrary/TestLibrary.podspec new file mode 100644 index 0000000000..c46340e718 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary.podspec @@ -0,0 +1,73 @@ +# +# Be sure to run `pod lib lint TestLibrary.podspec' to ensure this is a +# valid spec before submitting. +# +# Any lines starting with a # are optional, but their use is encouraged +# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html +# + +Pod::Spec.new do |s| + s.name = 'TestLibrary' + s.version = '0.1.0' + s.summary = 'A short description of TestLibrary.' + +# This description is used to generate tags and improve search results. +# * Think: What does it do? Why did you write it? What is the focus? +# * Try to keep it short, snappy and to the point. +# * Write the description between the DESC delimiters below. +# * Finally, don't worry about the indent, CocoaPods strips it! + + s.description = <<-DESC +TODO: Add long description of the pod here. + DESC + + s.homepage = 'https://github.com/lizhuoli1126@126.com/TestLibrary' + # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.author = { 'lizhuoli1126@126.com' => 'lizhuoli1126@126.com' } + s.source = { :git => 'https://github.com/lizhuoli1126@126.com/TestLibrary.git', :tag => s.version.to_s } + # s.social_media_url = 'https://twitter.com/' + + s.ios.deployment_target = '9.0' + + s.swift_version = '4' + + s.source_files = 'TestLibrary/Classes/**/*' + + s.on_demand_resources = { + 't1' => ['on_demand_bundle1/*'], + 't2' => { :paths => ['on_demand_bundle2/*'], :category => :prefetched }, + } + + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES' + } + + s.app_spec 'App1' do |app_spec| + app_spec.source_files = 'App1/Classes/**/*' + + app_spec.on_demand_resources = { + 'a1' => { :paths => ['App1/app1_on_demand_bundle1/*'], :category => :initial_install } + } + end + + s.app_spec 'App2' do |app_spec| + app_spec.source_files = 'App2/Classes/**/*' + + app_spec.on_demand_resources = { + 'a2' => { :paths => ['App2/app2_on_demand_bundle1/*'], :category => :initial_install } + } + end + + s.test_spec 'Tests' do |test_spec| + test_spec.source_files = 'Tests/Classes/**/*' + + test_spec.app_host_name = 'TestLibrary/App1' + test_spec.requires_app_host = true + test_spec.dependency 'TestLibrary/App1' + + test_spec.on_demand_resources = { + 'test1' => ['Tests/test_on_demand_bundle/*'] + } + end +end diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/1.imageset/1.jpg b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/1.imageset/1.jpg new file mode 100644 index 0000000000..a285fd8640 Binary files /dev/null and b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/1.imageset/1.jpg differ diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/1.imageset/Contents.json b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/1.imageset/Contents.json new file mode 100644 index 0000000000..5017a6be1c --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/2.imageset/2.jpg b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/2.imageset/2.jpg new file mode 100644 index 0000000000..529ea49b6e Binary files /dev/null and b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/2.imageset/2.jpg differ diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/2.imageset/Contents.json b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/2.imageset/Contents.json new file mode 100644 index 0000000000..d0a044aeff --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "2.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/3.imageset/3.jpg b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/3.imageset/3.jpg new file mode 100644 index 0000000000..fbcfc75ffd Binary files /dev/null and b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/3.imageset/3.jpg differ diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/3.imageset/Contents.json b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/3.imageset/Contents.json new file mode 100644 index 0000000000..f2cc5e2cea --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "3.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/4.imageset/4.jpg b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/4.imageset/4.jpg new file mode 100644 index 0000000000..286bba8c6f Binary files /dev/null and b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/4.imageset/4.jpg differ diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/4.imageset/Contents.json b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/4.imageset/Contents.json new file mode 100644 index 0000000000..a21b3afdca --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "4.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/5.imageset/5.jpg b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/5.imageset/5.jpg new file mode 100644 index 0000000000..01abef0afe Binary files /dev/null and b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/5.imageset/5.jpg differ diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/5.imageset/Contents.json b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/5.imageset/Contents.json new file mode 100644 index 0000000000..4d133b635e --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/5.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "5.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/Contents.json b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Assets/TestLibrary.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Classes/TestLibrary.h b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Classes/TestLibrary.h new file mode 100644 index 0000000000..3486df0779 --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Classes/TestLibrary.h @@ -0,0 +1,16 @@ +// +// TestLibrary.h +// TestLibrary +// +// Created by lizhuoli on 2019/1/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TestLibrary : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/examples/OnDemandResources Example/TestLibrary/TestLibrary/Classes/TestLibrary.m b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Classes/TestLibrary.m new file mode 100644 index 0000000000..c4f1aca61b --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/TestLibrary/Classes/TestLibrary.m @@ -0,0 +1,12 @@ +// +// TestLibrary.m +// TestLibrary +// +// Created by lizhuoli on 2019/1/28. +// + +#import "TestLibrary.h" + +@implementation TestLibrary + +@end diff --git a/examples/OnDemandResources Example/TestLibrary/Tests/Classes/TestLibraryTests.m b/examples/OnDemandResources Example/TestLibrary/Tests/Classes/TestLibraryTests.m new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/OnDemandResources Example/TestLibrary/Tests/test_on_demand_bundle/on1_sub1/resource b/examples/OnDemandResources Example/TestLibrary/Tests/test_on_demand_bundle/on1_sub1/resource new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/OnDemandResources Example/TestLibrary/Tests/test_on_demand_bundle/resource b/examples/OnDemandResources Example/TestLibrary/Tests/test_on_demand_bundle/resource new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/OnDemandResources Example/TestLibrary/_Pods.xcodeproj b/examples/OnDemandResources Example/TestLibrary/_Pods.xcodeproj new file mode 120000 index 0000000000..3c5a8e715a --- /dev/null +++ b/examples/OnDemandResources Example/TestLibrary/_Pods.xcodeproj @@ -0,0 +1 @@ +Example/Pods/Pods.xcodeproj \ No newline at end of file diff --git a/examples/OnDemandResources Example/TestLibrary/on_demand_bundle1/on1_sub1/resource b/examples/OnDemandResources Example/TestLibrary/on_demand_bundle1/on1_sub1/resource new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/OnDemandResources Example/TestLibrary/on_demand_bundle1/resource b/examples/OnDemandResources Example/TestLibrary/on_demand_bundle1/resource new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/OnDemandResources Example/TestLibrary/on_demand_bundle2/resource b/examples/OnDemandResources Example/TestLibrary/on_demand_bundle2/resource new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/cocoapods/external_sources/podspec_source.rb b/lib/cocoapods/external_sources/podspec_source.rb index 79ae87fae9..02b11a379e 100644 --- a/lib/cocoapods/external_sources/podspec_source.rb +++ b/lib/cocoapods/external_sources/podspec_source.rb @@ -16,7 +16,7 @@ def fetch(sandbox) else require 'cocoapods/open-uri' begin - open(podspec_uri) { |io| store_podspec(sandbox, io.read, is_json) } + OpenURI.open_uri(podspec_uri) { |io| store_podspec(sandbox, io.read, is_json) } rescue OpenURI::HTTPError => e status = e.io.status.join(' ') raise Informative, "Failed to fetch podspec for `#{name}` at `#{podspec_uri}`.\n Error: #{status}" diff --git a/lib/cocoapods/gem_version.rb b/lib/cocoapods/gem_version.rb index 9261810570..62a87eae9c 100644 --- a/lib/cocoapods/gem_version.rb +++ b/lib/cocoapods/gem_version.rb @@ -1,5 +1,5 @@ module Pod # The version of the CocoaPods command line tool. # - VERSION = '1.10.2'.freeze unless defined? Pod::VERSION + VERSION = '1.11.2'.freeze unless defined? Pod::VERSION end diff --git a/lib/cocoapods/generator/acknowledgements.rb b/lib/cocoapods/generator/acknowledgements.rb index aae1a4e08c..15f810fbfe 100644 --- a/lib/cocoapods/generator/acknowledgements.rb +++ b/lib/cocoapods/generator/acknowledgements.rb @@ -67,7 +67,7 @@ def specs # the specification for which license is needed. # # @return [String] The text of the license. - # @return [Nil] If not license text could be found. + # @return [Nil] If no license text could be found. # def license_text(spec) return nil unless spec.license diff --git a/lib/cocoapods/generator/copy_dsyms_script.rb b/lib/cocoapods/generator/copy_dsyms_script.rb index fa87946e86..6dd7797bbe 100644 --- a/lib/cocoapods/generator/copy_dsyms_script.rb +++ b/lib/cocoapods/generator/copy_dsyms_script.rb @@ -1,18 +1,18 @@ module Pod module Generator class CopydSYMsScript - # @return [Array] dsym_paths the dSYM paths to include in the script contents. + # @return [Array] dsym_paths the dSYM paths to include in the script contents. # attr_reader :dsym_paths - # @return [Array] bcsymbolmap_paths the bcsymbolmap paths to include in the script contents. + # @return [Array] bcsymbolmap_paths the bcsymbolmap paths to include in the script contents. # attr_reader :bcsymbolmap_paths # Initialize a new instance # - # @param [Array] dsym_paths @see dsym_paths - # @param [Array] bcsymbolmap_paths @see bcsymbolmap_paths + # @param [Array] dsym_paths @see dsym_paths + # @param [Array] bcsymbolmap_paths @see bcsymbolmap_paths # def initialize(dsym_paths, bcsymbolmap_paths) @dsym_paths = Array(dsym_paths) diff --git a/lib/cocoapods/generator/copy_xcframework_script.rb b/lib/cocoapods/generator/copy_xcframework_script.rb index a7ae47cde6..4f744f1682 100644 --- a/lib/cocoapods/generator/copy_xcframework_script.rb +++ b/lib/cocoapods/generator/copy_xcframework_script.rb @@ -70,8 +70,8 @@ def script local destination="$2" # Use filter instead of exclude so missing patterns don't throw errors. - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}\\" \\"${destination}\\"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}" "${destination}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}*\\" \\"${destination}\\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}"/* "${destination}" } SELECT_SLICE_RETVAL="" @@ -130,54 +130,11 @@ def script done } -install_library() { - local source="$1" - local name="$2" - local destination="#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/${name}" - - # Libraries can contain headers, module maps, and a binary, so we'll copy everything in the folder over - - local source="$binary" - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}/*\\" \\"${destination}\\"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}/*" "${destination}" -} - -# Copies a framework to derived data for use in later build phases -install_framework() -{ - local source="$1" - local name="$2" - local destination="#{Pod::Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/${name}" - - if [ ! -d "$destination" ]; then - mkdir -p "$destination" - fi - - copy_dir "$source" "$destination" - echo "Copied $source to $destination" -} - -install_xcframework_library() { - local basepath="$1" - local name="$2" - local paths=("$@") - - # Locate the correct slice of the .xcframework for the current architectures - select_slice "${paths[@]}" - local target_path="$SELECT_SLICE_RETVAL" - if [[ -z "$target_path" ]]; then - echo "warning: [CP] Unable to find matching .xcframework slice in '${paths[@]}' for the current build architectures ($ARCHS)." - return - fi - - install_framework "$basepath/$target_path" "$name" -} - install_xcframework() { local basepath="$1" local name="$2" local package_type="$3" - local paths=("$@") + local paths=("${@:4}") # Locate the correct slice of the .xcframework for the current architectures select_slice "${paths[@]}" @@ -195,7 +152,6 @@ def script fi copy_dir "$source/" "$destination" - echo "Copied $source to $destination" } @@ -218,7 +174,7 @@ def shell_escape(value) def install_xcframework_args(xcframework, slices) root = xcframework.path args = [shell_escape("${PODS_ROOT}/#{root.relative_path_from(sandbox_root)}")] - args << shell_escape(xcframework.name) + args << shell_escape(xcframework.target_name) is_framework = xcframework.build_type.framework? args << shell_escape(is_framework ? 'framework' : 'library') slices.each do |slice| diff --git a/lib/cocoapods/generator/embed_frameworks_script.rb b/lib/cocoapods/generator/embed_frameworks_script.rb index e23299aae1..d1772ebb08 100644 --- a/lib/cocoapods/generator/embed_frameworks_script.rb +++ b/lib/cocoapods/generator/embed_frameworks_script.rb @@ -159,8 +159,9 @@ def script end xcframeworks_by_config.each do |config, xcframeworks| xcframeworks.select { |xcf| xcf.build_type.dynamic_framework? }.each do |xcframework| + target_name = xcframework.target_name name = xcframework.name - contents_by_config[config] << %( install_framework "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{name}/#{name}.framework"\n) + contents_by_config[config] << %( install_framework "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{target_name}/#{name}.framework"\n) end end script << "\n" unless contents_by_config.empty? diff --git a/lib/cocoapods/generator/script_phase_constants.rb b/lib/cocoapods/generator/script_phase_constants.rb index c99d983ff5..ff9560554d 100644 --- a/lib/cocoapods/generator/script_phase_constants.rb +++ b/lib/cocoapods/generator/script_phase_constants.rb @@ -79,6 +79,7 @@ module ScriptPhaseConstants rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" else # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + mkdir -p "${DWARF_DSYM_FOLDER_PATH}" touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" fi fi diff --git a/lib/cocoapods/installer.rb b/lib/cocoapods/installer.rb index 74de104ce5..067b5fe38a 100644 --- a/lib/cocoapods/installer.rb +++ b/lib/cocoapods/installer.rb @@ -783,9 +783,11 @@ def warn_for_installed_script_phases # def warn_for_removing_git_master_specs_repo return unless installation_options.warn_for_unused_master_specs_repo? - podfile_master_source = podfile.sources.find { |source| source == MASTER_SPECS_REPO_GIT_URL } + plugin_sources = run_source_provider_hooks + all_sources = podfile.sources + plugin_sources.map(&:url) + master_source = all_sources.find { |source| source == MASTER_SPECS_REPO_GIT_URL } master_repo = config.sources_manager.all.find { |s| s.url == MASTER_SPECS_REPO_GIT_URL } - if podfile_master_source.nil? && !master_repo.nil? + if master_source.nil? && !master_repo.nil? UI.warn 'Your project does not explicitly specify the CocoaPods master specs repo. Since CDN is now used as the' \ ' default, you may safely remove it from your repos directory via `pod repo remove master`. To suppress this warning' \ ' please add `warn_for_unused_master_specs_repo => false` to your Podfile.' diff --git a/lib/cocoapods/installer/analyzer.rb b/lib/cocoapods/installer/analyzer.rb index 00243daf5b..97027364a4 100644 --- a/lib/cocoapods/installer/analyzer.rb +++ b/lib/cocoapods/installer/analyzer.rb @@ -35,7 +35,7 @@ class Analyzer # attr_reader :podfile - # @return [Lockfile] The Lockfile, if available, that stores the information about the Pods previously installed. + # @return [Lockfile, nil] The Lockfile, if available, that stores the information about the Pods previously installed. # attr_reader :lockfile @@ -67,7 +67,7 @@ class Analyzer # # @param [Sandbox] sandbox @see #sandbox # @param [Podfile] podfile @see #podfile - # @param [Lockfile] lockfile @see #lockfile + # @param [Lockfile, nil] lockfile @see #lockfile # @param [Array] plugin_sources @see #plugin_sources # @param [Boolean] has_dependencies @see #has_dependencies # @param [Hash, Boolean, nil] pods_to_update @see #pods_to_update @@ -713,7 +713,12 @@ def filter_dependencies(dependencies, pod_targets_by_name, target) dependencies.map do |root_spec, deps| pod_targets_by_name[root_spec.name].find do |t| next false if t.platform.symbolic_name != target.platform.symbolic_name || - t.build_as_framework? != target.build_as_framework? # rather than target type or requires_frameworks? since we want to group by what was specified in that _target definition_ + # In the case of variants we must ensure that the platform this target is meant for is the same + # as the one we are interested in. + t.target_definitions.first.platform != target.target_definitions.first.platform || + # rather than target type or requires_frameworks? since we want to group by what was specified in that + # _target definition_. + t.build_as_framework? != target.build_as_framework? spec_names = t.specs.map(&:name) deps.all? { |dep| spec_names.include?(dep.name) } end @@ -1114,7 +1119,7 @@ def generate_specifications(resolver_specs_by_target) def generate_sandbox_state(specifications) sandbox_state = nil UI.section 'Comparing resolved specification to the sandbox manifest' do - sandbox_analyzer = SandboxAnalyzer.new(sandbox, specifications, update_mode?) + sandbox_analyzer = SandboxAnalyzer.new(sandbox, podfile, specifications, update_mode?) sandbox_state = sandbox_analyzer.analyze sandbox_state.print end diff --git a/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb b/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb index aa944e52ba..d1df698aa3 100644 --- a/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +++ b/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb @@ -31,6 +31,10 @@ class SandboxAnalyzer # attr_reader :sandbox + # @return [Podfile] The Podfile to analyze dependencies. + # + attr_reader :podfile + # @return [Array] The specifications returned by the # resolver. # @@ -45,11 +49,13 @@ class SandboxAnalyzer # Init a new SandboxAnalyzer # # @param [Sandbox] sandbox @see sandbox + # @param [Podfile] podfile @see podfile # @param [Array] specs @see specs # @param [Bool] update_mode @see update_mode # - def initialize(sandbox, specs, update_mode) + def initialize(sandbox, podfile, specs, update_mode) @sandbox = sandbox + @podfile = podfile @specs = specs @update_mode = update_mode end @@ -139,6 +145,7 @@ def pod_changed?(pod) return true if spec.version != sandbox_version(pod) return true if spec.checksum != sandbox_checksum(pod) return true if resolved_spec_names(pod) != sandbox_spec_names(pod) + return true if podfile_dependency(pod) != sandbox_dependency(pod) return true if sandbox.predownloaded?(pod) return true if folder_empty?(pod) false @@ -223,6 +230,26 @@ def sandbox_checksum(pod) sandbox_manifest.checksum(pod) end + # @return [Dependency, nil] The dependency with the given name stored in the sandbox. + # + # @param [String] pod + # the name of the Pod. + # + def sandbox_dependency(pod) + sandbox_manifest.dependencies.find { |d| d.name == pod } + end + + #--------------------------------------# + + # @return [Dependency, nil] The dependency with the given name from the podfile. + # + # @param [String] pod + # the name of the Pod. + # + def podfile_dependency(pod) + podfile.dependencies.find { |d| d.name == pod } + end + #--------------------------------------# def folder_exist?(pod) diff --git a/lib/cocoapods/installer/project_cache/target_cache_key.rb b/lib/cocoapods/installer/project_cache/target_cache_key.rb index 9a88319349..71969f9aff 100644 --- a/lib/cocoapods/installer/project_cache/target_cache_key.rb +++ b/lib/cocoapods/installer/project_cache/target_cache_key.rb @@ -161,9 +161,12 @@ def self.from_aggregate_target(sandbox, aggregate_target) contents = { 'BUILD_SETTINGS_CHECKSUM' => build_settings, } - if aggregate_target.includes_resources? - relative_file_paths = aggregate_target.resource_paths_by_config.values.flatten.uniq - contents['FILES'] = relative_file_paths.sort_by(&:downcase) + if aggregate_target.includes_resources? || aggregate_target.includes_on_demand_resources? + relative_resource_file_paths = aggregate_target.resource_paths_by_config.values.flatten.uniq + relative_on_demand_resource_file_paths = aggregate_target.on_demand_resources.map do |res| + res.relative_path_from(sandbox.project_path.dirname).to_s + end + contents['FILES'] = (relative_resource_file_paths + relative_on_demand_resource_file_paths).sort_by(&:downcase) end TargetCacheKey.new(sandbox, :aggregate, contents) end diff --git a/lib/cocoapods/installer/user_project_integrator/target_integrator.rb b/lib/cocoapods/installer/user_project_integrator/target_integrator.rb index 0cc46f1d0d..caec8dcd39 100644 --- a/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +++ b/lib/cocoapods/installer/user_project_integrator/target_integrator.rb @@ -32,7 +32,8 @@ class TargetIntegrator # For messages extensions, this only applies if it's embedded in a messages # application. # - EMBED_FRAMEWORK_TARGET_TYPES = [:application, :application_on_demand_install_capable, :unit_test_bundle, :ui_test_bundle, :watch2_extension, :messages_application].freeze + EMBED_FRAMEWORK_TARGET_TYPES = [:application, :application_on_demand_install_capable, :unit_test_bundle, + :ui_test_bundle, :watch2_extension, :messages_application].freeze # @return [String] the name of the embed frameworks phase # @@ -326,11 +327,18 @@ def create_or_update_user_script_phases(script_phases, native_target) def reorder_script_phase(native_target, script_phase, execution_position) return if execution_position == :any || execution_position.to_s.empty? - target_phase_type = Xcodeproj::Project::Object::PBXSourcesBuildPhase + target_phase_type = case execution_position + when :before_compile, :after_compile + Xcodeproj::Project::Object::PBXSourcesBuildPhase + when :before_headers, :after_headers + Xcodeproj::Project::Object::PBXHeadersBuildPhase + else + raise ArgumentError, "Unknown execution position `#{execution_position}`" + end order_before = case execution_position - when :before_compile + when :before_compile, :before_headers true - when :after_compile + when :after_compile, :after_headers false else raise ArgumentError, "Unknown execution position `#{execution_position}`" @@ -387,10 +395,10 @@ def resource_output_paths(resource_input_paths) # Returns the framework input paths for the given framework paths # - # @param [Hash>] framework_paths + # @param [Array] framework_paths # The target's framework paths to map to input paths. # - # @param [Hash>] xcframeworks + # @param [Array] xcframeworks # The target's xcframeworks to map to input paths. # # @return [Array] The embed frameworks script input paths @@ -426,6 +434,119 @@ def embed_frameworks_output_paths(framework_paths, xcframeworks) end paths + xcframework_paths end + + # Updates a projects native targets to include on demand resources specified by the supplied parameters. + # Note that currently, only app level targets are allowed to include on demand resources. + # + # @param [Sandbox] sandbox + # The sandbox to use for calculating ODR file references. + # + # @param [Xcodeproj::Project] project + # The project to update known asset tags as well as add the ODR group. + # + # @param [Xcodeproj::PBXNativeTarget, Array] native_targets + # The native targets to integrate on demand resources into. + # + # @param [Sandbox::FileAccessor, Array] file_accessors + # The file accessors that that provide the ODRs to integrate. + # + # @param [Xcodeproj::PBXGroup] parent_odr_group + # The group to use as the parent to add ODR file references into. + # + # @param [String] target_odr_group_name + # The name to use for the group created that contains the ODR file references. + # + # @return [void] + # + def update_on_demand_resources(sandbox, project, native_targets, file_accessors, parent_odr_group, + target_odr_group_name) + category_to_tags = {} + file_accessors = Array(file_accessors) + native_targets = Array(native_targets) + + # Target no longer provides ODR references so remove everything related to this target. + if file_accessors.all? { |fa| fa.on_demand_resources.empty? } + old_target_odr_group = parent_odr_group[target_odr_group_name] + old_odr_file_refs = old_target_odr_group&.recursive_children_groups&.each_with_object({}) do |group, hash| + hash[group.name] = group.files + end || {} + native_targets.each do |native_target| + native_target.remove_on_demand_resources(old_odr_file_refs) + update_on_demand_resources_build_settings(native_target, nil => old_odr_file_refs.keys) + end + old_target_odr_group&.remove_from_project + return + end + + target_odr_group = parent_odr_group[target_odr_group_name] || parent_odr_group.new_group(target_odr_group_name) + current_file_refs = target_odr_group.recursive_children_groups.flat_map(&:files) + + added_file_refs = file_accessors.flat_map do |file_accessor| + target_odr_files_refs = Hash[file_accessor.on_demand_resources.map do |tag, value| + tag_group = target_odr_group[tag] || target_odr_group.new_group(tag) + category_to_tags[value[:category]] ||= [] + category_to_tags[value[:category]] << tag + resources_file_refs = value[:paths].map do |resource| + odr_resource_file_ref = Pathname.new(resource).relative_path_from(sandbox.root) + tag_group.find_file_by_path(odr_resource_file_ref.to_s) || tag_group.new_file(odr_resource_file_ref) + end + [tag, resources_file_refs] + end] + native_targets.each do |native_target| + native_target.add_on_demand_resources(target_odr_files_refs) + end + target_odr_files_refs.values.flatten + end + + # if the target ODR file references were updated, make sure we remove the ones that are no longer present + # for the target. + remaining_refs = current_file_refs - added_file_refs + remaining_refs.each do |ref| + native_targets.each do |user_target| + user_target.resources_build_phase.remove_file_reference(ref) + end + ref.remove_from_project + end + target_odr_group.recursive_children_groups.each { |g| g.remove_from_project if g.empty? } + + attributes = project.root_object.attributes + attributes['KnownAssetTags'] = (attributes['KnownAssetTags'] ||= []) | category_to_tags.values.flatten + project.root_object.attributes = attributes + + native_targets.each do |native_target| + update_on_demand_resources_build_settings(native_target, category_to_tags) + end + end + + def update_on_demand_resources_build_settings(native_target, category_to_tags) + %w[ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS ON_DEMAND_RESOURCES_PREFETCH_ORDER].each do |category_key| + native_target.build_configurations.each do |c| + key = case category_key + when 'ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS' + :initial_install + when 'ON_DEMAND_RESOURCES_PREFETCH_ORDER' + :prefetched + else + :download_on_demand + end + tags_for_category = (c.build_settings[category_key] || '').split + category_to_tags_dup = category_to_tags.dup + tags_to_add = category_to_tags_dup.delete(key) || [] + tags_to_delete = category_to_tags_dup.values.flatten + tags_for_category = (tags_for_category + tags_to_add - tags_to_delete).flatten.compact.uniq + if tags_for_category.empty? + val = c.build_settings.delete(category_key) + native_target.project.mark_dirty! unless val.nil? + else + tags = tags_for_category.join(' ') + unless c.build_settings[category_key] == tags + c.build_settings[category_key] = tags + native_target.project.mark_dirty! + end + end + end + end + end end # Integrates the user project targets. Only the targets that do **not** @@ -445,6 +566,7 @@ def integrate! add_copy_resources_script_phase add_check_manifest_lock_script_phase add_user_script_phases + add_on_demand_resources end end @@ -509,10 +631,12 @@ def add_copy_resources_script_phase output_paths_by_config = {} if use_input_output_paths target.resource_paths_by_config.each do |config, resource_paths| - input_paths_key = XCFileListConfigKey.new(target.copy_resources_script_input_files_path(config), target.copy_resources_script_input_files_relative_path) + input_paths_key = XCFileListConfigKey.new(target.copy_resources_script_input_files_path(config), + target.copy_resources_script_input_files_relative_path) input_paths_by_config[input_paths_key] = [script_path] + resource_paths - output_paths_key = XCFileListConfigKey.new(target.copy_resources_script_output_files_path(config), target.copy_resources_script_output_files_relative_path) + output_paths_key = XCFileListConfigKey.new(target.copy_resources_script_output_files_path(config), + target.copy_resources_script_output_files_relative_path) output_paths_by_config[output_paths_key] = TargetIntegrator.resource_output_paths(resource_paths) end end @@ -520,7 +644,9 @@ def add_copy_resources_script_phase native_targets.each do |native_target| # Static library targets cannot include resources. Skip this phase from being added instead. next if native_target.symbol_type == :static_library - TargetIntegrator.create_or_update_copy_resources_script_phase_to_target(native_target, script_path, input_paths_by_config, output_paths_by_config) + TargetIntegrator.create_or_update_copy_resources_script_phase_to_target(native_target, script_path, + input_paths_by_config, + output_paths_by_config) end end @@ -624,6 +750,20 @@ def remove_obsolete_script_phases(removed_phase_names = REMOVED_SCRIPT_PHASE_NAM end end + def add_on_demand_resources + target.pod_targets.each do |pod_target| + # When integrating with the user's project we are only interested in integrating ODRs from library specs + # and not test specs or app specs. + library_file_accessors = pod_target.file_accessors.select { |fa| fa.spec.library_specification? } + target_odr_group_name = "#{pod_target.label}-OnDemandResources" + # The 'Pods' group would always be there for production code however for tests its sometimes not added. + # This ensures its always present and makes it easier for existing and new tests. + parent_odr_group = target.user_project.main_group['Pods'] || target.user_project.new_group('Pods') + TargetIntegrator.update_on_demand_resources(target.sandbox, target.user_project, target.user_targets, + library_file_accessors, parent_odr_group, target_odr_group_name) + end + end + private # @!group Private Helpers diff --git a/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb b/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb index 8d7bcbf078..dfffa0b48d 100644 --- a/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +++ b/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb @@ -62,7 +62,8 @@ class AppHostInstaller # @param [Hash] info_plist_entries see #info_plist_entries # @param [String] product_basename see #product_basename # - def initialize(sandbox, project, platform, subgroup_name, group_name, app_target_label, add_main: true, add_launchscreen_storyboard: platform == :ios, info_plist_entries: {}, product_basename: nil) + def initialize(sandbox, project, platform, subgroup_name, group_name, app_target_label, add_main: true, + add_launchscreen_storyboard: platform == :ios, info_plist_entries: {}, product_basename: nil) @sandbox = sandbox @project = project @platform = platform diff --git a/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb b/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb index 7ff2384ded..9ae38b9198 100644 --- a/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +++ b/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb @@ -43,18 +43,14 @@ def install! test_file_accessors = target.file_accessors.select { |fa| fa.spec.test_specification? } app_file_accessors = target.file_accessors.select { |fa| fa.spec.app_specification? } - unless target.should_build? - # For targets that should not be built (e.g. pre-built vendored frameworks etc), we add a placeholder - # PBXAggregateTarget that will be used to wire up dependencies later. - native_target = add_placeholder_target - resource_bundle_targets = add_resources_bundle_targets(library_file_accessors).values.flatten - create_copy_dsyms_script - create_copy_xcframeworks_script unless target.xcframeworks.values.all?(&:empty?) - create_xcconfig_file(native_target, resource_bundle_targets) - return TargetInstallationResult.new(target, native_target, resource_bundle_targets) - end + native_target = if target.should_build? + add_target + else + # For targets that should not be built (e.g. pre-built vendored frameworks etc), we add a placeholder + # PBXAggregateTarget that will be used to wire up dependencies later. + add_placeholder_target + end - native_target = add_target resource_bundle_targets = add_resources_bundle_targets(library_file_accessors).values.flatten test_native_targets = add_test_targets @@ -65,8 +61,10 @@ def install! app_resource_bundle_targets = add_resources_bundle_targets(app_file_accessors) add_files_to_build_phases(native_target, test_native_targets, app_native_targets) - validate_targets_contain_sources(test_native_targets + app_native_targets.values + [native_target]) - validate_xcframeworks + targets_to_validate = test_native_targets + app_native_targets.values + targets_to_validate << native_target if target.should_build? + validate_targets_contain_sources(targets_to_validate) + validate_xcframeworks if target.should_build? create_copy_xcframeworks_script unless target.xcframeworks.values.all?(&:empty?) @@ -74,7 +72,7 @@ def install! create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets) create_app_xcconfig_files(app_native_targets, app_resource_bundle_targets) - if target.defines_module? + if target.should_build? && target.defines_module? && !skip_modulemap?(target.library_specs) create_module_map(native_target) do |generator| generator.headers.concat module_map_additional_headers end @@ -99,20 +97,21 @@ def install! end end - if target.build_as_framework? + if target.should_build? && target.build_as_framework? unless skip_info_plist?(native_target) - create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform, :additional_entries => target.info_plist_entries) + create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform, + :additional_entries => target.info_plist_entries) end create_build_phase_to_symlink_header_folders(native_target) end - if target.build_as_library? && target.uses_swift? + if target.should_build? && target.build_as_library? && target.uses_swift? add_swift_library_compatibility_header_phase(native_target) end project_directory = project.path.dirname - unless skip_pch?(target.library_specs) + if target.should_build? && !skip_pch?(target.library_specs) path = target.prefix_header_path create_prefix_header(path, library_file_accessors, target.platform, native_target, project_directory) add_file_to_support_group(path) @@ -135,7 +134,7 @@ def install! add_file_to_support_group(path) end end - create_dummy_source(native_target) + create_dummy_source(native_target) if target.should_build? create_copy_dsyms_script clean_support_files_temp_dir TargetInstallationResult.new(target, native_target, resource_bundle_targets, @@ -191,6 +190,10 @@ def skip_pch?(specs) specs.any? { |spec| spec.root.prefix_header_file.is_a?(FalseClass) } end + def skip_modulemap?(specs) + specs.any? { |spec| spec.module_map.is_a?(FalseClass) } + end + # True if info.plist generation should be skipped # # @param [PXNativeTarget] native_target @@ -264,10 +267,10 @@ def info_plist_bundle_id # @yield_param [Array} The filtered resource file references to be installed # in the compile sources phase. # - # @note Core Data model directories (.xcdatamodeld) used to be added to the - # `Copy Resources` build phase like all other resources, since they would - # compile correctly in either the resources or compile phase. In recent - # versions of xcode, there's an exception for data models that generate + # @note Core Data model directories (.xcdatamodeld) and RealityKit projects (.rcproject) + # used to be added to the `Copy Resources` build phase like all other resources, + # since they would compile correctly in either the resources or compile phase. In + # recent versions of xcode, there's an exception for data models that generate # headers. These need to be added to the compile sources phase of a real # target for the headers to be built in time for code in the target to # use them. These kinds of models generally break when added to resource @@ -287,7 +290,7 @@ def filter_resource_file_references(resource_file_references) ref end.compact.uniq - compile_phase_matcher = lambda { |ref| !(ref.path =~ /.*\.xcdatamodeld/i).nil? } + compile_phase_matcher = lambda { |ref| !(ref.path =~ /.*\.(xcdatamodeld|rcproject)/i).nil? } compile_phase_refs, resources_phase_refs = file_references.partition(&compile_phase_matcher) yield compile_phase_refs, resources_phase_refs end @@ -307,21 +310,26 @@ def filter_resource_file_references(resource_file_references) # # @return [void] # - def add_files_to_build_phases(native_target, test_native_targets, app_native_targets) + def add_files_to_build_phases(library_native_target, test_native_targets, app_native_targets) target.file_accessors.each do |file_accessor| consumer = file_accessor.spec_consumer native_target = case consumer.spec.spec_type when :library - native_target + library_native_target when :test test_native_target_from_spec(consumer.spec, test_native_targets) when :app app_native_targets[consumer.spec] + else + raise ArgumentError, "Unknown spec type #{consumer.spec.spec_type}." end + next if native_target.is_a?(Xcodeproj::Project::Object::PBXAggregateTarget) + headers = file_accessor.headers public_headers = file_accessor.public_headers.map(&:realpath) + project_headers = file_accessor.project_headers.map(&:realpath) private_headers = file_accessor.private_headers.map(&:realpath) other_source_files = file_accessor.other_source_files @@ -344,7 +352,7 @@ def add_files_to_build_phases(native_target, test_native_targets, app_native_tar header_file_refs = project_file_references_array(headers, 'header') native_target.add_file_references(header_file_refs) do |build_file| - add_header(file_accessor, build_file, public_headers, private_headers, native_target) + add_header(file_accessor, build_file, public_headers, project_headers, private_headers, native_target) end other_file_refs = project_file_references_array(other_source_files, 'other source') @@ -356,7 +364,10 @@ def add_files_to_build_phases(native_target, test_native_targets, app_native_tar native_target.add_file_references(compile_phase_refs, nil) if target.build_as_static_framework? && consumer.spec.library_specification? - resource_phase_refs = resource_phase_refs.select { |ref| Target.resource_extension_compilable?(File.extname(ref.path)) } + resource_phase_refs = resource_phase_refs.select do |ref| + filename = ref.name || ref.path + Target.resource_extension_compilable?(File.extname(filename)) + end end native_target.add_resources(resource_phase_refs) @@ -988,7 +999,7 @@ def module_map_additional_headers end def create_umbrella_header(native_target) - return super(native_target) unless custom_module_map + super(native_target) unless custom_module_map end def custom_module_map @@ -1025,12 +1036,14 @@ def header_mappings_dir(file_accessor) end end - def add_header(file_accessor, build_file, public_headers, private_headers, native_target) + def add_header(file_accessor, build_file, public_headers, project_headers, private_headers, native_target) file_ref = build_file.file_ref acl = if !target.build_as_framework? # Headers are already rooted at ${PODS_ROOT}/Headers/P*/[pod]/... 'Project' elsif public_headers.include?(file_ref.real_path) 'Public' + elsif project_headers.include?(file_ref.real_path) + 'Project' elsif private_headers.include?(file_ref.real_path) 'Private' else @@ -1186,7 +1199,11 @@ class << self def dsym_paths(target) dsym_paths = target.framework_paths.values.flatten.reject { |fmwk_path| fmwk_path.dsym_path.nil? }.map(&:dsym_path) dsym_paths.concat(target.xcframeworks.values.flatten.flat_map { |xcframework| xcframework_dsyms(xcframework.path) }) - dsym_paths + dsym_paths.map do |dsym_path| + dsym_pathname = Pathname(dsym_path) + dsym_path = "${PODS_ROOT}/#{dsym_pathname.relative_path_from(target.sandbox.root)}" unless dsym_pathname.relative? + dsym_path + end end # @param [PodTarget] target the target to be installed @@ -1196,7 +1213,7 @@ def dsym_paths(target) def bcsymbolmap_paths(target) target.framework_paths.values.flatten.reject do |fmwk_path| fmwk_path.bcsymbolmap_paths.nil? - end.flat_map(&:bcsymbolmap_paths) + end.flat_map(&:bcsymbolmap_paths).uniq end # @param [Pathname] xcframework_path diff --git a/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb b/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb index e18f0186b4..a1df9bb554 100644 --- a/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +++ b/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb @@ -34,6 +34,7 @@ def integrate! target_installation_result.non_library_specs_by_native_target.each do |native_target, spec| add_embed_frameworks_script_phase(native_target, spec) add_copy_resources_script_phase(native_target, spec) + add_on_demand_resources(native_target, spec) if spec.app_specification? UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(spec), native_target) end add_copy_dsyms_script_phase(target_installation_result.native_target) @@ -134,20 +135,26 @@ def add_embed_frameworks_script_phase(native_target, spec) spec_paths_to_include << spec.name if dependent_target == target dependent_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact end.uniq + xcframework_paths = dependent_targets.flat_map do |dependent_target| + spec_paths_to_include = dependent_target.library_specs.map(&:name) + spec_paths_to_include -= host_target_spec_names + spec_paths_to_include << spec.name if dependent_target == target + dependent_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact + end.uniq - if use_input_output_paths? && !framework_paths.empty? + if use_input_output_paths? && !framework_paths.empty? || !xcframework_paths.empty? input_file_list_path = target.embed_frameworks_script_input_files_path_for_spec(spec) input_file_list_relative_path = "${PODS_ROOT}/#{input_file_list_path.relative_path_from(target.sandbox.root)}" input_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(input_file_list_path, input_file_list_relative_path) - input_paths_by_config[input_paths_key] = [script_path] + UserProjectIntegrator::TargetIntegrator.embed_frameworks_input_paths(framework_paths, []) + input_paths_by_config[input_paths_key] = [script_path] + UserProjectIntegrator::TargetIntegrator.embed_frameworks_input_paths(framework_paths, xcframework_paths) output_file_list_path = target.embed_frameworks_script_output_files_path_for_spec(spec) output_file_list_relative_path = "${PODS_ROOT}/#{output_file_list_path.relative_path_from(target.sandbox.root)}" output_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(output_file_list_path, output_file_list_relative_path) - output_paths_by_config[output_paths_key] = UserProjectIntegrator::TargetIntegrator.embed_frameworks_output_paths(framework_paths, []) + output_paths_by_config[output_paths_key] = UserProjectIntegrator::TargetIntegrator.embed_frameworks_output_paths(framework_paths, xcframework_paths) end - if framework_paths.empty? + if framework_paths.empty? && xcframework_paths.empty? UserProjectIntegrator::TargetIntegrator.remove_embed_frameworks_script_phase_from_target(native_target) else UserProjectIntegrator::TargetIntegrator.create_or_update_embed_frameworks_script_phase_to_target( @@ -183,7 +190,7 @@ def add_copy_xcframeworks_script_phase(native_target) output_file_list_relative_path = "${PODS_ROOT}/#{output_file_list_path.relative_path_from(target.sandbox.root)}" output_paths_key = UserProjectIntegrator::TargetIntegrator::XCFileListConfigKey.new(output_file_list_path, output_file_list_relative_path) output_paths_by_config[output_paths_key] = xcframeworks.map do |xcf| - "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcf.name}" + "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcf.target_name}/#{xcf.name}.framework" end end @@ -199,7 +206,7 @@ def add_copy_xcframeworks_script_phase(native_target) # vendored dSYMs. # # @param [PBXNativeTarget] native_target - # the native target for which to add the the copy dSYM files build phase. + # the native target for which to add the copy dSYM files build phase. # # @return [void] # @@ -242,6 +249,41 @@ def add_copy_dsyms_script_phase(native_target) UserProjectIntegrator::TargetIntegrator.set_input_output_paths(phase, input_paths_by_config, output_paths_by_config) end + # Adds the ODRs that are related to this app spec. This includes the app spec dependencies as well as the ODRs + # coming from the app spec itself. + # + # @param [Xcodeproj::PBXNativeTarget] native_target + # the native target for which to add the ODR file references into. + # + # @param [Specification] app_spec + # the app spec to integrate ODRs for. + # + # @return [void] + # + def add_on_demand_resources(native_target, app_spec) + dependent_targets = target.dependent_targets_for_app_spec(app_spec) + parent_odr_group = native_target.project.group_for_spec(app_spec.name) + + # Add ODRs of the app spec dependencies first. + dependent_targets.each do |pod_target| + file_accessors = pod_target.file_accessors.select do |fa| + fa.spec.library_specification? || + fa.spec.test_specification? && pod_target.test_app_hosts_by_spec[fa.spec]&.first == app_spec + end + target_odr_group_name = "#{pod_target.label}-OnDemandResources" + UserProjectIntegrator::TargetIntegrator.update_on_demand_resources(target.sandbox, native_target.project, + native_target, file_accessors, + parent_odr_group, target_odr_group_name) + end + + # Now add the ODRs of our own app spec declaration. + file_accessor = target.file_accessors.find { |fa| fa.spec == app_spec } + target_odr_group_name = "#{target.subspec_label(app_spec)}-OnDemandResources" + UserProjectIntegrator::TargetIntegrator.update_on_demand_resources(target.sandbox, native_target.project, + native_target, file_accessor, + parent_odr_group, target_odr_group_name) + end + # @return [String] the message that should be displayed for the target # integration. # diff --git a/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb b/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb index 2a072b7e05..3e1d55e632 100644 --- a/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +++ b/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb @@ -79,12 +79,12 @@ def initialize(target, native_target, resource_bundle_targets = [], test_native_ # @param [Specification] spec # The specification to base from in order to find the native target. # - # @return [PBXNativeTarget] the native target to use or `nil` if none is found. + # @return [PBXNativeTarget, Nil] the native target to use or `nil` if none is found. # def native_target_for_spec(spec) return native_target if spec.library_specification? return test_native_target_from_spec(spec) if spec.test_specification? - return app_native_target_from_spec(spec) if spec.app_specification? + app_native_target_from_spec(spec) if spec.app_specification? end # @return [Hash{PBXNativeTarget => Specification}] a hash where the keys are the test native targets and the value diff --git a/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb b/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb index c9fd0bb7cd..72b16b6a54 100644 --- a/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +++ b/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb @@ -48,17 +48,23 @@ def update_changed_file(generator, path) # @param [Hash] additional_entries # any additional entries to include in this Info.plist file. # + # @param [String] build_setting_value + # an optional value to set for the `INFOPLIST_FILE` build setting on the + # native target. If none is specified then the value is calculated from the + # Info.plist path relative to the sandbox root. + # # @return [void] # def create_info_plist_file_with_sandbox(sandbox, path, native_target, version, platform, - bundle_package_type = :fmwk, additional_entries: {}) + bundle_package_type = :fmwk, additional_entries: {}, + build_setting_value: nil) UI.message "- Generating Info.plist file at #{UI.path(path)}" do generator = Generator::InfoPlistFile.new(version, platform, bundle_package_type, additional_entries) update_changed_file(generator, path) - relative_path_string = path.relative_path_from(sandbox.root).to_s + build_setting_value ||= path.relative_path_from(sandbox.root).to_s native_target.build_configurations.each do |c| - c.build_settings['INFOPLIST_FILE'] = relative_path_string + c.build_settings['INFOPLIST_FILE'] = build_setting_value end end end diff --git a/lib/cocoapods/installer/xcode/target_validator.rb b/lib/cocoapods/installer/xcode/target_validator.rb index e0c214e1d4..738e3b7d08 100644 --- a/lib/cocoapods/installer/xcode/target_validator.rb +++ b/lib/cocoapods/installer/xcode/target_validator.rb @@ -129,7 +129,7 @@ def verify_swift_pods_swift_version def verify_swift_pods_have_module_dependencies error_messages = [] pod_targets.each do |pod_target| - next unless pod_target.uses_swift? + next unless pod_target.uses_swift? && pod_target.should_build? non_module_dependencies = [] pod_target.dependent_targets.each do |dependent_target| diff --git a/lib/cocoapods/sandbox/file_accessor.rb b/lib/cocoapods/sandbox/file_accessor.rb index 58768d7f5d..b7771a185f 100644 --- a/lib/cocoapods/sandbox/file_accessor.rb +++ b/lib/cocoapods/sandbox/file_accessor.rb @@ -128,6 +128,7 @@ def headers # def public_headers(include_frameworks = false) public_headers = public_header_files + project_headers = project_header_files private_headers = private_header_files if public_headers.nil? || public_headers.empty? header_files = headers @@ -135,7 +136,13 @@ def public_headers(include_frameworks = false) header_files = public_headers end header_files += vendored_frameworks_headers if include_frameworks - header_files - private_headers + header_files - project_headers - private_headers + end + + # @return [Array] The project headers of the specification. + # + def project_headers + project_header_files end # @return [Array] The private headers of the specification. @@ -177,7 +184,7 @@ def vendored_dynamic_frameworks # def vendored_static_xcframeworks vendored_xcframeworks.select do |path| - Xcode::XCFramework.new(path).build_type == BuildType.static_framework + Xcode::XCFramework.new(spec.name, path).build_type == BuildType.static_framework end end @@ -212,6 +219,7 @@ def self.all_files(file_accessors) file_accessors.map(&:preserve_paths), file_accessors.map(&:readme), file_accessors.map(&:resources), + file_accessors.map(&:on_demand_resources_files), file_accessors.map(&:source_files), file_accessors.map(&:module_map), ] @@ -238,14 +246,17 @@ def self.vendored_frameworks_headers(framework) Pathname.glob(headers_dir + '**/' + GLOB_PATTERNS[:public_header_files]) end - # @param [Pathname] framework + # @param [String] target_name + # The target name this .xcframework belongs to + # + # @param [Pathname] framework_path # The path to the .xcframework # # @return [Array] The paths to all the headers included in the # vendored xcframework # - def self.vendored_xcframework_headers(framework) - xcframework = Xcode::XCFramework.new(framework) + def self.vendored_xcframework_headers(target_name, framework_path) + xcframework = Xcode::XCFramework.new(target_name, framework_path) xcframework.slices.flat_map do |slice| vendored_frameworks_headers(slice.path) end @@ -259,7 +270,7 @@ def vendored_frameworks_headers self.class.vendored_frameworks_headers(framework) end.uniq paths.concat Array.new(vendored_xcframeworks.flat_map do |framework| - self.class.vendored_xcframework_headers(framework) + self.class.vendored_xcframework_headers(spec.name, framework) end) paths end @@ -323,6 +334,26 @@ def resource_bundle_files resource_bundles.values.flatten end + # @return [Hash{String => Hash] The expanded paths of the on demand resources specified + # keyed by their tag including their category. + # + def on_demand_resources + result = {} + spec_consumer.on_demand_resources.each do |tag_name, file_patterns| + paths = expanded_paths(file_patterns[:paths], + :exclude_patterns => spec_consumer.exclude_files, + :include_dirs => true) + result[tag_name] = { :paths => paths, :category => file_patterns[:category] } + end + result + end + + # @return [Array] The expanded paths of the on demand resources. + # + def on_demand_resources_files + on_demand_resources.values.flat_map { |v| v[:paths] } + end + # @return [Pathname] The of the prefix header file of the specification. # def prefix_header @@ -331,7 +362,7 @@ def prefix_header end end - # @return [Pathname] The path of the auto-detected README file. + # @return [Pathname, nil] The path of the auto-detected README file. # def readme path_list.glob([GLOB_PATTERNS[:readme]]).first @@ -413,7 +444,14 @@ def public_header_files paths_for_attribute(:public_header_files) end - # @return [Array] The paths of the user-specified public header + # @return [Array] The paths of the user-specified project header + # files. + # + def project_header_files + paths_for_attribute(:project_header_files) + end + + # @return [Array] The paths of the user-specified private header # files. # def private_header_files diff --git a/lib/cocoapods/sources_manager.rb b/lib/cocoapods/sources_manager.rb index 174afde3d2..540915db4c 100644 --- a/lib/cocoapods/sources_manager.rb +++ b/lib/cocoapods/sources_manager.rb @@ -71,12 +71,15 @@ def create_source_with_url(url) # The URL of the source. # def cdn_url?(url) - return unless url =~ %r{^https?:\/\/} + return false unless url =~ %r{^https?:\/\/} uri_options = {} netrc_info = Netrc.read - netrc_host = URI.parse(url).host + uri = URI.parse(url) + return false unless uri.userinfo.nil? + + netrc_host = uri.host credentials = netrc_info[netrc_host] uri_options[:http_basic_authentication] = credentials if credentials diff --git a/lib/cocoapods/target/aggregate_target.rb b/lib/cocoapods/target/aggregate_target.rb index 34e7db58bc..081b642f3b 100644 --- a/lib/cocoapods/target/aggregate_target.rb +++ b/lib/cocoapods/target/aggregate_target.rb @@ -225,6 +225,12 @@ def includes_resources? !resource_paths_by_config.each_value.all?(&:empty?) end + # @return [Boolean] Whether the target contains any on demand resources + # + def includes_on_demand_resources? + !on_demand_resources.empty? + end + # @return [Boolean] Whether the target contains frameworks to be embedded into # the user target # @@ -273,6 +279,20 @@ def xcframeworks_by_config end end + # @return [Array] Uniqued On Demand Resources for this target. + # + # @note On Demand Resources are not separated by config as they are integrated directly into the users target via + # the resources build phase. + # + def on_demand_resources + @on_demand_resources ||= begin + pod_targets.flat_map do |pod_target| + library_file_accessors = pod_target.file_accessors.select { |fa| fa.spec.library_specification? } + library_file_accessors.flat_map(&:on_demand_resources_files) + end.uniq + end + end + # @return [Hash{String => Array}] Uniqued Resources grouped by config # def resource_paths_by_config @@ -292,7 +312,9 @@ def resource_paths_by_config extname = File.extname(resource_path) if self.class.resource_extension_compilable?(extname) output_extname = self.class.output_extension_for_resource(extname) - built_product_dir.join(File.basename(resource_path)).sub_ext(output_extname).to_s + output_path_components = Pathname(resource_path).each_filename.select { |component| File.extname(component) == '.lproj' } + output_path_components << File.basename(resource_path) + built_product_dir.join(*output_path_components).sub_ext(output_extname).to_s else resource_path end diff --git a/lib/cocoapods/target/build_settings.rb b/lib/cocoapods/target/build_settings.rb index bae52d1dfa..6c2d44ca8b 100644 --- a/lib/cocoapods/target/build_settings.rb +++ b/lib/cocoapods/target/build_settings.rb @@ -140,12 +140,12 @@ def self.define_build_settings_method(method_name, build_setting: false, end private_class_method :define_build_settings_method - # @param [XCFramework] xcframework the xcframework thats slice will be copied to the intermediates dir + # @param [XCFramework] xcframework the xcframework slice that will be copied to the intermediates dir # # @return [String] the path to the directory containing the xcframework slice # def self.xcframework_intermediate_dir(xcframework) - "#{XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcframework.name}" + "#{XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcframework.target_name}" end class << self @@ -508,12 +508,14 @@ def select_maximal_pod_targets(pod_targets) pod_targets - subset_targets end + # @param [String] target_name the name of the target this xcframework belongs to + # # @param [Pathname,String] path the path to the xcframework bundle # # @return [Xcode::XCFramework] the xcframework at the given path # - def load_xcframework(path) - Xcode::XCFramework.new(path) + def load_xcframework(target_name, path) + Xcode::XCFramework.new(target_name, path) end # A subclass that generates build settings for a {PodTarget} @@ -735,7 +737,9 @@ def initialize(target, non_library_spec = nil, configuration: nil) # @return [Array] define_build_settings_method :vendored_xcframeworks, :memoized => true do - file_accessors.flat_map(&:vendored_xcframeworks).map { |path| load_xcframework(path) } + file_accessors.flat_map do |file_accessor| + file_accessor.vendored_xcframeworks.map { |path| load_xcframework(file_accessor.spec.name, path) } + end end # @return [Array] diff --git a/lib/cocoapods/target/pod_target.rb b/lib/cocoapods/target/pod_target.rb index c761036a2a..503e143da6 100644 --- a/lib/cocoapods/target/pod_target.rb +++ b/lib/cocoapods/target/pod_target.rb @@ -203,7 +203,7 @@ def label end end - # @return [Array] The list of all files tracked. + # @return [Array] The list of all files tracked. # def all_files Sandbox::FileAccessor.all_files(file_accessors) @@ -311,7 +311,7 @@ def test_spec_consumers test_specs.map { |test_spec| test_spec.consumer(platform) } end - # @return [Array] the test specification consumers for + # @return [Array] the app specification consumers for # the target. # def app_spec_consumers @@ -394,7 +394,7 @@ def contains_test_specifications? !test_specs.empty? end - # @return [Boolean] Whether the target has any tests specifications. + # @return [Boolean] Whether the target has any app specifications. # def contains_app_specifications? !app_specs.empty? @@ -443,7 +443,7 @@ def xcframeworks @xcframeworks ||= begin file_accessors.each_with_object({}) do |file_accessor, hash| frameworks = file_accessor.vendored_xcframeworks.map do |framework_path| - Xcode::XCFramework.new(framework_path) + Xcode::XCFramework.new(file_accessor.spec.name, framework_path) end hash[file_accessor.spec.name] = frameworks end diff --git a/lib/cocoapods/user_interface.rb b/lib/cocoapods/user_interface.rb index 5990424dbb..0540afefe6 100644 --- a/lib/cocoapods/user_interface.rb +++ b/lib/cocoapods/user_interface.rb @@ -137,6 +137,10 @@ def title(title, verbose_prefix = '', relative_indentation = 2) # The indentation level relative to the current, # when the message is printed. # + # @yield The action, this block is always executed. + # + # @return [void] + # def message(message, verbose_prefix = '', relative_indentation = 2) message = verbose_prefix + message if config.verbose? puts_indented message if config.verbose? diff --git a/lib/cocoapods/validator.rb b/lib/cocoapods/validator.rb index 82df6b85f7..c69b9314a9 100644 --- a/lib/cocoapods/validator.rb +++ b/lib/cocoapods/validator.rb @@ -118,7 +118,7 @@ def validate # Replace default spec with a subspec if asked for a_spec = spec if spec && @only_subspec - subspec_name = @only_subspec.start_with?(spec.root.name) ? @only_subspec : "#{spec.root.name}/#{@only_subspec}" + subspec_name = @only_subspec.start_with?("#{spec.root.name}/") ? @only_subspec : "#{spec.root.name}/#{@only_subspec}" a_spec = spec.subspec_by_name(subspec_name, true, true) @subspec_name = a_spec.name end @@ -581,11 +581,23 @@ def download_pod def create_app_project app_project = Xcodeproj::Project.new(validation_dir + 'App.xcodeproj') app_target = Pod::Generator::AppTargetHelper.add_app_target(app_project, consumer.platform_name, deployment_target) + sandbox = Sandbox.new(config.sandbox_root) + info_plist_path = app_project.path.dirname.+('App/App-Info.plist') + Pod::Installer::Xcode::PodsProjectGenerator::TargetInstallerHelper.create_info_plist_file_with_sandbox(sandbox, + info_plist_path, + app_target, + '1.0.0', + Platform.new(consumer.platform_name), + :appl, + :build_setting_value => '$(SRCROOT)/App/App-Info.plist') Pod::Generator::AppTargetHelper.add_swift_version(app_target, derived_swift_version) - # Lint will fail if a AppIcon is set but no image is found with such name - # Happens only with Static Frameworks enabled but shouldn't be set anyway app_target.build_configurations.each do |config| + # Lint will fail if a AppIcon is set but no image is found with such name + # Happens only with Static Frameworks enabled but shouldn't be set anyway config.build_settings.delete('ASSETCATALOG_COMPILER_APPICON_NAME') + # Ensure this is set generally but we have seen an issue with ODRs: + # see: https://github.com/CocoaPods/CocoaPods/issues/10933 + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' end app_project.save app_project.recreate_user_schemes @@ -775,7 +787,7 @@ def xcodebuild_available? FILE_PATTERNS = %i(source_files resources preserve_paths vendored_libraries vendored_frameworks public_header_files preserve_paths - private_header_files resource_bundles).freeze + project_header_files private_header_files resource_bundles).freeze # It checks that every file pattern specified in a spec yields # at least one file. It requires the pods to be already present @@ -811,6 +823,22 @@ def validate_nonempty_patterns(attr_name, message_type) add_result(message_type, 'file patterns', "The `#{attr_name}` pattern did not match any file.") end + def _validate_vendored_libraries + file_accessor.vendored_libraries.each do |lib| + basename = File.basename(lib) + lib_name = basename.downcase + unless lib_name.end_with?('.a') && lib_name.start_with?('lib') + warning('vendored_libraries', "`#{basename}` does not match the expected static library name format `lib[name].a`") + end + end + validate_nonempty_patterns(:vendored_libraries, :warning) + end + + def _validate_project_header_files + _validate_header_files(:project_header_files) + validate_nonempty_patterns(:project_header_files, :warning) + end + def _validate_private_header_files _validate_header_files(:private_header_files) validate_nonempty_patterns(:private_header_files, :warning) diff --git a/lib/cocoapods/xcode/xcframework.rb b/lib/cocoapods/xcode/xcframework.rb index b2fcfa7c2c..ed894f6b9e 100644 --- a/lib/cocoapods/xcode/xcframework.rb +++ b/lib/cocoapods/xcode/xcframework.rb @@ -5,6 +5,10 @@ module Pod module Xcode class XCFramework + # @return [String] target_name the target name this XCFramework belongs to + # + attr_reader :target_name + # @return [Pathname] path the path to the .xcframework on disk # attr_reader :path @@ -23,12 +27,13 @@ class XCFramework # Initializes an XCFramework instance with a path on disk # - # @param [Pathname, String] path - # The path to the .xcframework on disk + # @param [String] target_name @see target_name + # @param [Pathname, String] path @see path # # @return [XCFramework] the xcframework at the given path # - def initialize(path) + def initialize(target_name, path) + @target_name = target_name @path = Pathname.new(path).tap do |p| raise 'Absolute path is required' unless p.absolute? end diff --git a/spec/cocoapods-integration-specs b/spec/cocoapods-integration-specs index 6b7e796dbd..0f94813cd2 160000 --- a/spec/cocoapods-integration-specs +++ b/spec/cocoapods-integration-specs @@ -1 +1 @@ -Subproject commit 6b7e796dbda6d86012f4b03b90f15c69622b81a8 +Subproject commit 0f94813cd26d6dd54af72328bda3df243ab579e8 diff --git a/spec/fixtures/banana-lib.tar.gz b/spec/fixtures/banana-lib.tar.gz index 41900ba2cf..9eb2f7b6e4 100644 Binary files a/spec/fixtures/banana-lib.tar.gz and b/spec/fixtures/banana-lib.tar.gz differ diff --git a/spec/fixtures/spec-repos/test_repo b/spec/fixtures/spec-repos/test_repo index f70468c7b5..15bf64a7a2 160000 --- a/spec/fixtures/spec-repos/test_repo +++ b/spec/fixtures/spec-repos/test_repo @@ -1 +1 @@ -Subproject commit f70468c7b5cbcb5d4e476304c96d1c18461096e5 +Subproject commit 15bf64a7a2f2d80331c15a89cb0d4b207d705214 diff --git a/spec/unit/downloader/request_spec.rb b/spec/unit/downloader/request_spec.rb index 03108ae559..43844933f0 100644 --- a/spec/unit/downloader/request_spec.rb +++ b/spec/unit/downloader/request_spec.rb @@ -46,7 +46,7 @@ module Pod end it 'returns the slug' do - @request.slug.should == 'Release/BananaLib/1.0-5b1d7' + @request.slug.should == 'Release/BananaLib/1.0-09ac6' end end diff --git a/spec/unit/generator/copy_xcframeworks_script_spec.rb b/spec/unit/generator/copy_xcframeworks_script_spec.rb index 812d15276e..d1440e5379 100644 --- a/spec/unit/generator/copy_xcframeworks_script_spec.rb +++ b/spec/unit/generator/copy_xcframeworks_script_spec.rb @@ -3,7 +3,7 @@ module Pod describe CopyXCFrameworksScript = Generator::CopyXCFrameworksScript do it 'installs xcframeworks' do - xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework')) + xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')) generator = CopyXCFrameworksScript.new([xcframework], temporary_sandbox.root, Platform.ios) generator.send(:script).should.include <<-SH.strip_heredoc install_xcframework "${PODS_ROOT}/../../spec/fixtures/CoconutLib.xcframework" "CoconutLib" "framework" "ios-armv7_arm64" "ios-i386_x86_64-simulator" @@ -11,7 +11,7 @@ module Pod end it 'installs xcframeworks using the correct platform' do - xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework')) + xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')) generator = CopyXCFrameworksScript.new([xcframework], temporary_sandbox.root, Platform.macos) generator.send(:script).should.include <<-SH.strip_heredoc install_xcframework "${PODS_ROOT}/../../spec/fixtures/CoconutLib.xcframework" "CoconutLib" "framework" "macos-x86_64" @@ -31,7 +31,7 @@ module Pod end it 'does not embed static frameworks' do - xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework')) + xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')) generator = CopyXCFrameworksScript.new([xcframework], temporary_sandbox.root, Platform.ios) Xcode::LinkageAnalyzer.stubs(:dynamic_binary?).returns(false) # Second argument to `install_xcframework` is a boolean indicating whether to embed the framework diff --git a/spec/unit/generator/embed_frameworks_script_spec.rb b/spec/unit/generator/embed_frameworks_script_spec.rb index 4bc1c025a0..fd47a8c655 100644 --- a/spec/unit/generator/embed_frameworks_script_spec.rb +++ b/spec/unit/generator/embed_frameworks_script_spec.rb @@ -54,7 +54,7 @@ module Pod end it 'installs intermediate XCFramework slices' do - xcframework = Xcode::XCFramework.new(fixture('CoconutLib.xcframework')) + xcframework = Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')) generator = Pod::Generator::EmbedFrameworksScript.new({}, 'Debug' => [xcframework]) result = generator.send(:script) result.should.include <<-SH.strip_heredoc @@ -63,5 +63,16 @@ module Pod fi SH end + + it 'installs intermediate XCFramework slices based on the correct target name and framework name' do + xcframework = Xcode::XCFramework.new('SomeLib', fixture('CoconutLib.xcframework')) + generator = Pod::Generator::EmbedFrameworksScript.new({}, 'Debug' => [xcframework]) + result = generator.send(:script) + result.should.include <<-SH.strip_heredoc + if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${PODS_XCFRAMEWORKS_BUILD_DIR}/SomeLib/CoconutLib.framework" + fi + SH + end end end diff --git a/spec/unit/installer/analyzer/sandbox_analyzer_spec.rb b/spec/unit/installer/analyzer/sandbox_analyzer_spec.rb index 80f407c4de..730e2878a0 100644 --- a/spec/unit/installer/analyzer/sandbox_analyzer_spec.rb +++ b/spec/unit/installer/analyzer/sandbox_analyzer_spec.rb @@ -7,10 +7,11 @@ module Pod before do @spec = fixture_spec('banana-lib/BananaLib.podspec') @sandbox = config.sandbox + @podfile = Pod::Podfile.new lockfile_hash = { 'PODS' => ['BananaLib (1.0)'] } @manifest = Pod::Lockfile.new(lockfile_hash) @sandbox.stubs(:manifest).returns(@manifest) - @analyzer = Installer::Analyzer::SandboxAnalyzer.new(@sandbox, [@spec], false) + @analyzer = Installer::Analyzer::SandboxAnalyzer.new(@sandbox, @podfile, [@spec], false) end #-------------------------------------------------------------------------# @@ -83,6 +84,14 @@ module Pod @sandbox.stubs(:predownloaded?).returns(true) @analyzer.send(:pod_changed?, 'BananaLib').should == true end + + it 'considers a changed Pod whose dependency is changed' do + dep1 = Dependency.new('BananaLib', :git => 'https://github.com/grafiszti/bananalib.git') + dep2 = Dependency.new('BananaLib') + @analyzer.stubs(:sandbox_dependency).returns(dep1) + @analyzer.stubs(:podfile_dependency).returns(dep2) + @analyzer.send(:pod_changed?, 'BananaLib').should == true + end end #-------------------------------------------------------------------------# diff --git a/spec/unit/installer/analyzer_spec.rb b/spec/unit/installer/analyzer_spec.rb index a1ea755d21..9554e8c71d 100644 --- a/spec/unit/installer/analyzer_spec.rb +++ b/spec/unit/installer/analyzer_spec.rb @@ -810,6 +810,38 @@ module Pod ) end + it 'picks the right dependencies across different variants' do + @podfile = Pod::Podfile.new do + source SpecHelper.test_repo_url + project 'SampleProject/SampleProject' + + target 'TestRunner' do + platform :ios, '8.0' + pod 'OrangeFramework' + end + + target 'SampleProject' do + platform :ios, '9.0' + pod 'OrangeFramework' + end + end + @analyzer = Pod::Installer::Analyzer.new(config.sandbox, @podfile, nil, [], true, false, @sources_manager) + result = @analyzer.analyze + result.targets.count.should == 2 + + pod_target_ios8 = result.targets[0].pod_targets.find { |pt| pt.label == 'OrangeFramework-iOS8.0' } + pod_target_ios8.dependent_targets.count == 1 + pod_target_ios8.dependent_targets.map(&:label).should == %w( + matryoshka-iOS8.0 + ) + + pod_target_ios9 = result.targets[1].pod_targets.find { |pt| pt.label == 'OrangeFramework-iOS9.0' } + pod_target_ios9.dependent_targets.count == 1 + pod_target_ios9.dependent_targets.map(&:label).should == %w( + matryoshka-iOS9.0 + ) + end + it 'does not create multiple variants across different targets that require different set of testspecs' do @podfile = Pod::Podfile.new do source SpecHelper.test_repo_url @@ -1427,7 +1459,8 @@ module Pod it 'unlocks only local pod when specification checksum changes' do sandbox = config.sandbox - local_spec = Specification.from_hash('name' => 'LocalPod', 'version' => '1.1', 'dependencies' => { 'Expecta' => ['~> 0.0'] }) + spec_hash = { 'name' => 'LocalPod', 'version' => '1.1', 'dependencies' => { 'Expecta' => ['~> 0.0'] } } + local_spec = Specification.from_hash(spec_hash) sandbox.stubs(:specification).with('LocalPod').returns(local_spec) podfile = Podfile.new do platform :ios, '8.0' @@ -1454,7 +1487,8 @@ module Pod it 'raises if change in local pod specification conflicts with lockfile' do sandbox = config.sandbox - local_spec = Specification.from_hash('name' => 'LocalPod', 'version' => '1.0', 'dependencies' => { 'Expecta' => ['0.2.2'] }) + spec_hash = { 'name' => 'LocalPod', 'version' => '1.0', 'dependencies' => { 'Expecta' => ['0.2.2'] } } + local_spec = Specification.from_hash(spec_hash) sandbox.stubs(:specification).with('LocalPod').returns(local_spec) podfile = Podfile.new do platform :ios, '8.0' diff --git a/spec/unit/installer/project_cache/project_cache_analyzer_spec.rb b/spec/unit/installer/project_cache/project_cache_analyzer_spec.rb index f303c969cd..d43b2c5c79 100644 --- a/spec/unit/installer/project_cache/project_cache_analyzer_spec.rb +++ b/spec/unit/installer/project_cache/project_cache_analyzer_spec.rb @@ -275,7 +275,8 @@ module ProjectCache cache_key_by_aggregate_target_labels = { @main_aggregate_target.label => TargetCacheKey.from_aggregate_target(@sandbox, @main_aggregate_target) } cache_key_target_labels = cache_key_by_pod_target_labels.merge(cache_key_by_aggregate_target_labels) cache = ProjectInstallationCache.new(cache_key_target_labels, @build_configurations, @project_object_version, {}, 'share_schemes_for_development_pods' => false, 'lock_pod_sources' => true) - analyzer = ProjectCacheAnalyzer.new(@sandbox, cache, @build_configurations, @project_object_version, {}, @pod_targets, [@main_aggregate_target], 'share_schemes_for_development_pods' => false) + installation_options = { 'share_schemes_for_development_pods' => false } + analyzer = ProjectCacheAnalyzer.new(@sandbox, cache, @build_configurations, @project_object_version, {}, @pod_targets, [@main_aggregate_target], installation_options) result = analyzer.analyze result.pod_targets_to_generate.should.equal(@pod_targets) result.aggregate_targets_to_generate.should.equal([@main_aggregate_target]) @@ -286,7 +287,8 @@ module ProjectCache cache_key_by_aggregate_target_labels = { @main_aggregate_target.label => TargetCacheKey.from_aggregate_target(@sandbox, @main_aggregate_target) } cache_key_target_labels = cache_key_by_pod_target_labels.merge(cache_key_by_aggregate_target_labels) cache = ProjectInstallationCache.new(cache_key_target_labels, @build_configurations, @project_object_version, {}, 'share_schemes_for_development_pods' => false, 'lock_pod_sources' => true) - analyzer = ProjectCacheAnalyzer.new(@sandbox, cache, @build_configurations, @project_object_version, {}, @pod_targets, [@main_aggregate_target], 'lock_pod_sources' => true, 'share_schemes_for_development_pods' => false) + installation_options = { 'lock_pod_sources' => true, 'share_schemes_for_development_pods' => false } + analyzer = ProjectCacheAnalyzer.new(@sandbox, cache, @build_configurations, @project_object_version, {}, @pod_targets, [@main_aggregate_target], installation_options) result = analyzer.analyze result.pod_targets_to_generate.should.equal([]) result.aggregate_targets_to_generate.should.equal(nil) diff --git a/spec/unit/installer/project_cache/target_cache_key_spec.rb b/spec/unit/installer/project_cache/target_cache_key_spec.rb index 4bc6151b0e..3595c25711 100644 --- a/spec/unit/installer/project_cache/target_cache_key_spec.rb +++ b/spec/unit/installer/project_cache/target_cache_key_spec.rb @@ -32,6 +32,34 @@ module ProjectCache library_resources = @banana_pod_target.resource_paths.values.flatten.sort_by(&:downcase) aggregate_target_cache_key.to_h['FILES'].should.equal(library_resources) end + + it 'should output files for aggregate target if it has aggregate on demand resources' do + aggregate_target = AggregateTarget.new(config.sandbox, BuildType.static_library, { 'Debug' => :debug }, [], Platform.ios, + fixture_target_definition('MyApp'), config.sandbox.root.dirname, nil, + nil, 'Debug' => [@banana_pod_target]) + @banana_pod_target.stubs(:resource_paths).returns({}) + on_demand_resources = { 'tag1' => { :paths => [Pathname('/path/to/resource')], :category => :download_on_demand } } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + aggregate_target_cache_key = TargetCacheKey.from_aggregate_target(config.sandbox, aggregate_target) + library_on_demand_resources = @banana_pod_target.file_accessors.first.on_demand_resources_files.map do |p| + p.relative_path_from(config.sandbox.root).to_s.downcase + end + aggregate_target_cache_key.to_h['FILES'].should.equal(library_on_demand_resources) + end + + it 'should output files for aggregate target if it has aggregate both aggregate resources and on demand resources' do + aggregate_target = AggregateTarget.new(config.sandbox, BuildType.static_library, { 'Debug' => :debug }, [], Platform.ios, + fixture_target_definition('MyApp'), config.sandbox.root.dirname, nil, + nil, 'Debug' => [@banana_pod_target]) + on_demand_resources = { 'tag1' => { :paths => [Pathname('/path/to/resource')], :category => :download_on_demand } } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + aggregate_target_cache_key = TargetCacheKey.from_aggregate_target(config.sandbox, aggregate_target) + library_resources = @banana_pod_target.resource_paths.values.flatten.sort_by(&:downcase) + library_on_demand_resources = @banana_pod_target.file_accessors.first.on_demand_resources_files.map do |p| + p.relative_path_from(config.sandbox.root).to_s.downcase + end + aggregate_target_cache_key.to_h['FILES'].should.equal(library_resources + library_on_demand_resources) + end end describe 'key_difference with pod targets' do diff --git a/spec/unit/installer/user_project_integrator/target_integrator_spec.rb b/spec/unit/installer/user_project_integrator/target_integrator_spec.rb index 79ddd26e82..22bfb2dffd 100644 --- a/spec/unit/installer/user_project_integrator/target_integrator_spec.rb +++ b/spec/unit/installer/user_project_integrator/target_integrator_spec.rb @@ -15,9 +15,10 @@ module Pod target_definition = Podfile::TargetDefinition.new('Pods', nil) target_definition.abstract = false user_build_configurations = { 'Release' => :release, 'Debug' => :debug } + @banana_pod_target = fixture_pod_target('banana-lib/BananaLib.podspec') @pod_bundle = AggregateTarget.new(config.sandbox, BuildType.static_library, user_build_configurations, [], Platform.ios, target_definition, project_path.dirname, @project, - [@target.uuid], {}) + [@target.uuid], 'Release' => [@banana_pod_target], 'Debug' => [@banana_pod_target]) @pod_bundle.stubs(:resource_paths_by_config).returns('Release' => %w(${PODS_ROOT}/Lib/Resources/image.png)) @pod_bundle.stubs(:framework_paths_by_config).returns('Release' => [Xcode::FrameworkPaths.new('${PODS_BUILD_DIR}/Lib/Lib.framework')]) configuration = Xcodeproj::Config.new( @@ -622,11 +623,25 @@ module Pod end it 'moves custom shell scripts according to their execution position' do + @pod_bundle.target_definition.stubs(:script_phases).returns([]) + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + # By calling this, xcodeproj automatically adds this phase to the native target. + target.headers_build_phase + target.build_phases.map(&:display_name).should == [ + '[CP] Check Pods Manifest.lock', + 'Sources', + 'Frameworks', + 'Resources', + '[CP] Embed Pods Frameworks', + '[CP] Copy Pods Resources', + 'Headers', + ] shell_script_one = { :name => 'Custom Script', :script => 'echo "Hello World"', :execution_position => :before_compile } shell_script_two = { :name => 'Custom Script 2', :script => 'echo "Hello Aliens"' } - @pod_bundle.target_definition.stubs(:script_phases).returns([shell_script_one, shell_script_two]) + shell_script_three = { :name => 'Custom Script 3', :script => 'echo "Hello Aliens"', :execution_position => :before_headers } + @pod_bundle.target_definition.stubs(:script_phases).returns([shell_script_one, shell_script_two, shell_script_three]) @target_integrator.integrate! - target = @target_integrator.send(:native_targets).first target.build_phases.map(&:display_name).should == [ '[CP] Check Pods Manifest.lock', '[CP-User] Custom Script', @@ -635,11 +650,14 @@ module Pod 'Resources', '[CP] Embed Pods Frameworks', '[CP] Copy Pods Resources', + '[CP-User] Custom Script 3', + 'Headers', '[CP-User] Custom Script 2', ] shell_script_one = { :name => 'Custom Script', :script => 'echo "Hello World"', :execution_position => :after_compile } shell_script_two = { :name => 'Custom Script 2', :script => 'echo "Hello Aliens"', :execution_position => :before_compile } - @pod_bundle.target_definition.stubs(:script_phases).returns([shell_script_one, shell_script_two]) + shell_script_three = { :name => 'Custom Script 3', :script => 'echo "Hello Aliens"', :execution_position => :after_headers } + @pod_bundle.target_definition.stubs(:script_phases).returns([shell_script_one, shell_script_two, shell_script_three]) @target_integrator.integrate! target.build_phases.map(&:display_name).should == [ '[CP] Check Pods Manifest.lock', @@ -650,6 +668,8 @@ module Pod 'Resources', '[CP] Embed Pods Frameworks', '[CP] Copy Pods Resources', + 'Headers', + '[CP-User] Custom Script 3', ] shell_script_one = { :name => 'Custom Script', :script => 'echo "Hello World"' } shell_script_two = { :name => 'Custom Script 2', :script => 'echo "Hello Aliens"' } @@ -664,6 +684,7 @@ module Pod 'Resources', '[CP] Embed Pods Frameworks', '[CP] Copy Pods Resources', + 'Headers', ] end @@ -732,6 +753,180 @@ module Pod end end + it 'adds and remove on demand resources to the user target resources build phase' do + on_demand_resources = { 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :download_on_demand } } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + target.resources_build_phase.files.map(&:display_name).should == ['InfoPlist.strings', 'resource.png'] + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources').should.not.be.nil + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources/tag1').should.not.be.nil + @project['Pods']['BananaLib-OnDemandResources']['tag1'].files.map(&:display_name).should == ['resource.png'] + @project.root_object.attributes['KnownAssetTags'].should == ['tag1'] + # Now pretend target no longer specifies ODRs. + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns({}) + @target_integrator.integrate! + target.resources_build_phase.files.map(&:display_name).should == ['InfoPlist.strings'] + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources').should.be.nil + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources/tag1').should.be.nil + # Despite the fact we added this asset tag we can never guarantee it was added by CocoaPods so we can never + # delete any KnownAssetTags. We can let the user do this. + @project.root_object.attributes['KnownAssetTags'].should == ['tag1'] + end + + it 'removes stale on demand resource file references' do + on_demand_resources = { + 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :download_on_demand }, + 'tag2' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource2.png'], :category => :download_on_demand }, + } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + target.resources_build_phase.files.map(&:display_name).should == ['InfoPlist.strings', 'resource.png', 'resource2.png'] + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources').should.not.be.nil + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources/tag1').should.not.be.nil + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources/tag2').should.not.be.nil + @project['Pods']['BananaLib-OnDemandResources']['tag1'].files.map(&:display_name).should == ['resource.png'] + @project['Pods']['BananaLib-OnDemandResources']['tag2'].files.map(&:display_name).should == ['resource2.png'] + @project.root_object.attributes['KnownAssetTags'].should == %w[tag1 tag2] + on_demand_resources = { 'tag2' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource2.png'], :category => :download_on_demand } } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target.resources_build_phase.files.map(&:display_name).should == ['InfoPlist.strings', 'resource2.png'] + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources').should.not.be.nil + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources/tag1').should.be.nil + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources/tag2').should.not.be.nil + @project['Pods']['BananaLib-OnDemandResources']['tag2'].files.map(&:display_name).should == ['resource2.png'] + @project.main_group.find_subpath('Pods/BananaLib-OnDemandResources').should.not.be.nil + # Despite the fact we added this asset tag we can never guarantee it was added by CocoaPods so we can never + # delete any KnownAssetTags. We can let the user do this. + @project.root_object.attributes['KnownAssetTags'].should == %w[tag1 tag2] + end + + it 'completely removes build settings related to on demand resources if they are empty' do + on_demand_resources = { 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :initial_install } } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @project.dirty?.should.be.false + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'tag1' + end + @project.dirty?.should.be.true + @project.save + @project.dirty?.should.be.false + # Now pretend target no longer specifies ODRs. + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns({}) + @target_integrator.integrate! + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should.be.nil + end + @project.dirty?.should.be.true + end + + it 'maintains on demand resources build settings when a target no longer specifies on demand resources' do + target = @target_integrator.send(:native_targets).first + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'] = 'existing_tag' + end + @project.dirty?.should.be.false + on_demand_resources = { 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :initial_install } } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'existing_tag tag1' + end + @project.dirty?.should.be.true + @project.save + @project.dirty?.should.be.false + # Now pretend target no longer specifies ODRs. + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns({}) + @target_integrator.integrate! + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'existing_tag' + end + @project.dirty?.should.be.true + end + + it 'does not mark the project as dirty if on demand resources build settings did not change' do + on_demand_resources = { + 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :initial_install }, + 'tag2' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource2.png'], :category => :initial_install }, + } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'tag1 tag2' + end + @project.dirty?.should.be.true + @project.save + @project.dirty?.should.be.false + @target_integrator.integrate! + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'tag1 tag2' + end + @project.dirty?.should.be.false + end + + it 'sets on demand resource category build settings' do + on_demand_resources = { + 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :initial_install }, + 'tag2' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource2.png'], :category => :prefetched }, + } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + @project.root_object.attributes['KnownAssetTags'].should == %w[tag1 tag2] + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'tag1' + bc.build_settings['ON_DEMAND_RESOURCES_PREFETCH_ORDER'].should == 'tag2' + end + end + + it 'sets multiple on demand resource categories on a single build setting' do + on_demand_resources = { + 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :initial_install }, + 'tag2' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource2.png'], :category => :initial_install }, + } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + @project.root_object.attributes['KnownAssetTags'].should == %w[tag1 tag2] + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'tag1 tag2' + bc.build_settings['ON_DEMAND_RESOURCES_PREFETCH_ORDER'].should.be.nil + end + end + + it 'updates on demand resources build settings if they change' do + on_demand_resources = { + 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :initial_install }, + 'tag2' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource2.png'], :category => :initial_install }, + 'tag3' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource3.png'], :category => :initial_install }, + } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + target = @target_integrator.send(:native_targets).first + @project.root_object.attributes['KnownAssetTags'].should == %w[tag1 tag2 tag3] + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'tag1 tag2 tag3' + bc.build_settings['ON_DEMAND_RESOURCES_PREFETCH_ORDER'].should.be.nil + end + on_demand_resources = { + 'tag1' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource.png'], :category => :prefetched }, + 'tag2' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource2.png'], :category => :initial_install }, + 'tag3' => { :paths => [config.sandbox.root + 'banana-lib/path/to/resource3.png'], :category => :download_on_demand }, + } + @banana_pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + @target_integrator.integrate! + @project.root_object.attributes['KnownAssetTags'].should == %w[tag1 tag2 tag3] + target.build_configurations.each do |bc| + bc.build_settings['ON_DEMAND_RESOURCES_INITIAL_INSTALL_TAGS'].should == 'tag2' + bc.build_settings['ON_DEMAND_RESOURCES_PREFETCH_ORDER'].should == 'tag1' + end + end + describe 'Script paths' do it 'calculates the output paths of the embed frameworks script' do paths = [ @@ -743,7 +938,7 @@ module Pod Xcode::FrameworkPaths.new('${BUILT_PRODUCTS_DIR}/ReleaseCompiledFramework/CompiledFramework.framework'), ] xcframeworks = [ - Xcode::XCFramework.new(fixture('CoconutLib.xcframework')), + Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')), ] xcframeworks[0].stubs(:build_type).returns(BuildType.dynamic_framework) TargetIntegrator.embed_frameworks_output_paths(paths, xcframeworks).sort.should == %w( @@ -755,7 +950,7 @@ module Pod it 'does not include static xcframeworks in the embed frameworks output paths' do xcframeworks = [ - Xcode::XCFramework.new(fixture('CoconutLib.xcframework')), + Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')), ] xcframeworks[0].stubs(:build_type).returns(BuildType.static_framework) TargetIntegrator.embed_frameworks_output_paths([], xcframeworks).should == [] diff --git a/spec/unit/installer/xcode/pods_project_generator/file_references_installer_spec.rb b/spec/unit/installer/xcode/pods_project_generator/file_references_installer_spec.rb index 3fea75f066..ac6871420c 100644 --- a/spec/unit/installer/xcode/pods_project_generator/file_references_installer_spec.rb +++ b/spec/unit/installer/xcode/pods_project_generator/file_references_installer_spec.rb @@ -52,9 +52,9 @@ class PodsProjectGenerator it "adds file references for localization directories if glob doesn't include contained files" do @installer.install! - file_ref = @installer.pods_project['Pods/BananaLib/Resources/en.lproj'] + file_ref = @installer.pods_project['Pods/BananaLib/Resources/de.lproj'] file_ref.should.be.not.nil - file_ref.path.should == 'Resources/en.lproj' + file_ref.path.should == 'Resources/de.lproj' end it 'adds `knownRegions` for all resource localization regions' do diff --git a/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb b/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb index f743831ecb..59c4314291 100644 --- a/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb +++ b/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb @@ -647,6 +647,97 @@ class PodsProjectGenerator e = ->() { @ios_installer.install! }.should.raise(Informative) e.message.should.include '[!] Using Swift static libraries with custom module maps is currently not supported. Please build `WatermelonLib` as a framework or remove the custom module map.' end + + it 'integrates test specs and app specs even for targets that do not require building' do + @watermelon_ios_pod_target.stubs(:should_build?).returns(false) + @watermelon_spec.app_specs.each { |s| s.pod_target_xcconfig = {} } + installation_result = @ios_installer.install! + @project.targets.count.should == 9 + @project.targets.first.name.should == 'WatermelonLib' + @project.targets.first.class.should == Xcodeproj::Project::PBXAggregateTarget + unit_test_native_target = @project.targets[1] + unit_test_native_target.name.should == 'WatermelonLib-Unit-Tests' + unit_test_native_target.product_reference.name.should == 'WatermelonLib-Unit-Tests' + unit_test_native_target.product_reference.path.should == 'WatermelonLib-Unit-Tests.xctest' + unit_test_native_target.build_configurations.each do |bc| + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.unit-tests.#{bc.name.downcase}.xcconfig" + bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-Unit-Tests' + bc.build_settings['MACH_O_TYPE'].should.be.nil + bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil + bc.build_settings['CODE_SIGNING_REQUIRED'].should == 'YES' + bc.build_settings['CODE_SIGNING_ALLOWED'].should == 'YES' + bc.build_settings['CODE_SIGN_IDENTITY'].should == 'iPhone Developer' + bc.build_settings['INFOPLIST_FILE'].should == 'Target Support Files/WatermelonLib/WatermelonLib-Unit-Tests-Info.plist' + bc.build_settings['GCC_PREFIX_HEADER'].should == 'Target Support Files/WatermelonLib/WatermelonLib-Unit-Tests-prefix.pch' + end + unit_test_native_target.symbol_type.should == :unit_test_bundle + unit_test_native_target.source_build_phase.files.map(&:display_name).should == [ + 'WatermelonTests.m', + 'WatermelonSwiftTests.swift', + ] + + ui_test_native_target = @project.targets[2] + ui_test_native_target.name.should == 'WatermelonLib-UI-UITests' + ui_test_native_target.product_reference.name.should == 'WatermelonLib-UI-UITests' + ui_test_native_target.product_reference.path.should == 'WatermelonLib-UI-UITests.xctest' + ui_test_native_target.build_configurations.each do |bc| + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.ui-uitests.#{bc.name.downcase}.xcconfig" + bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-UI-UITests' + bc.build_settings['MACH_O_TYPE'].should.be.nil + bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil + bc.build_settings['CODE_SIGNING_REQUIRED'].should == 'YES' + bc.build_settings['CODE_SIGNING_ALLOWED'].should == 'YES' + bc.build_settings['CODE_SIGN_IDENTITY'].should == 'iPhone Developer' + bc.build_settings['INFOPLIST_FILE'].should == 'Target Support Files/WatermelonLib/WatermelonLib-UI-UITests-Info.plist' + bc.build_settings['GCC_PREFIX_HEADER'].should == 'Target Support Files/WatermelonLib/WatermelonLib-UI-UITests-prefix.pch' + end + ui_test_native_target.symbol_type.should == :ui_test_bundle + ui_test_native_target.source_build_phase.files.map(&:display_name).should == [ + 'WatermelonUITests.m', + ] + snapshot_test_native_target = @project.targets[3] + snapshot_test_native_target.name.should == 'WatermelonLib-Unit-SnapshotTests' + snapshot_test_native_target.product_reference.name.should == 'WatermelonLib-Unit-SnapshotTests' + snapshot_test_native_target.product_reference.path.should == 'WatermelonLib-Unit-SnapshotTests.xctest' + snapshot_test_native_target.build_configurations.each do |bc| + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.unit-snapshottests.#{bc.name.downcase}.xcconfig" + bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-Unit-SnapshotTests' + bc.build_settings['MACH_O_TYPE'].should.be.nil + bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil + bc.build_settings['CODE_SIGNING_REQUIRED'].should == 'YES' + bc.build_settings['CODE_SIGNING_ALLOWED'].should == 'YES' + bc.build_settings['CODE_SIGN_IDENTITY'].should == 'iPhone Developer' + bc.build_settings['INFOPLIST_FILE'].should == 'Target Support Files/WatermelonLib/WatermelonLib-Unit-SnapshotTests-Info.plist' + bc.build_settings['GCC_PREFIX_HEADER'].should == 'Target Support Files/WatermelonLib/WatermelonLib-Unit-SnapshotTests-prefix.pch' + end + snapshot_test_native_target.symbol_type.should == :unit_test_bundle + app_native_target = @project.targets[7] + app_native_target.name.should == 'WatermelonLib-App' + app_native_target.product_reference.name.should == 'WatermelonLib-App' + app_native_target.product_reference.path.should == 'WatermelonLib-App.app' + app_native_target.build_configurations.each do |bc| + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.app.#{bc.name.downcase}.xcconfig" + bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-App' + bc.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' + bc.build_settings['CURRENT_PROJECT_VERSION'].should == '1' + bc.build_settings['MACH_O_TYPE'].should.be.nil + bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil + bc.build_settings['CODE_SIGNING_REQUIRED'].should == 'YES' + bc.build_settings['CODE_SIGNING_ALLOWED'].should == 'YES' + bc.build_settings['CODE_SIGN_IDENTITY'].should == 'iPhone Developer' + bc.build_settings['CODE_SIGN_IDENTITY[sdk=appletvos*]'].should.be.nil + bc.build_settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'].should.be.nil + bc.build_settings['CODE_SIGN_IDENTITY[sdk=watchos*]'].should.be.nil + bc.build_settings['INFOPLIST_FILE'].should == 'App/WatermelonLib-App-Info.plist' + bc.build_settings['GCC_PREFIX_HEADER'].should == 'Target Support Files/WatermelonLib/WatermelonLib-App-prefix.pch' + end + app_native_target.symbol_type.should == :application + app_native_target.source_build_phase.files.map(&:display_name).should == [ + 'main.swift', + ] + installation_result.test_native_targets.count.should == 3 + installation_result.app_native_targets.count.should == 1 + end end describe 'test other files under sources' do @@ -741,11 +832,15 @@ class PodsProjectGenerator @installer.install! resources = @project.targets.first.resources_build_phase.files resources.count.should > 0 - resource = resources.find { |res| res.file_ref.path.include?('logo-sidebar.png') } + resource = resources.find { |res| res.file_ref.name == 'logo-sidebar.png' } resource.should.be.not.nil + resource.file_ref.class.should == Xcodeproj::Project::Object::PBXFileReference + resource.file_ref.path.should == 'Resources/logo-sidebar.png' - resource = resources.find { |res| res.file_ref.path.include?('en.lproj') } + resource = resources.find { |res| res.file_ref.name == 'Main.storyboard' } resource.should.be.not.nil + resource.file_ref.class.should == Xcodeproj::Project::Object::PBXVariantGroup + resource.file_ref.children.map(&:path).sort.should == %w[Base.lproj/Main.storyboard en.lproj/Main.strings] end it 'adds compilable framework resources to the static framework target' do @@ -753,8 +848,14 @@ class PodsProjectGenerator @installer.install! resources = @project.targets.first.resources_build_phase.files resources.count.should > 0 - resource = resources.find { |res| res.file_ref.path.include?('Migration.xcmappingmodel') } + resource = resources.find { |res| res.file_ref.name == 'Migration.xcmappingmodel' } + resource.should.be.not.nil + resource.file_ref.class.should == Xcodeproj::Project::Object::PBXFileReference + resource.file_ref.path.should == 'Resources/Migration.xcmappingmodel' + resource = resources.find { |res| res.file_ref.name == 'Main.storyboard' } resource.should.be.not.nil + resource.file_ref.class.should == Xcodeproj::Project::Object::PBXVariantGroup + resource.file_ref.children.map(&:path).sort.should == %w[Base.lproj/Main.storyboard en.lproj/Main.strings] end it 'doesn\'t add non-compilable framework resources to the static framework target' do @@ -918,6 +1019,19 @@ class PodsProjectGenerator ] end + it 'verifies disabling module map generation' do + @pod_target.stubs(:defines_module?).returns(true) + @pod_target.specs.first.stubs(:module_map).returns(false) + @installer.install! + group = @project['Pods/BananaLib/Support Files'] + group.children.map(&:display_name).sort.should == [ + 'BananaLib-Pods-SampleProject-dummy.m', + 'BananaLib-Pods-SampleProject-prefix.pch', + 'BananaLib-Pods-SampleProject.debug.xcconfig', + 'BananaLib-Pods-SampleProject.release.xcconfig', + ] + end + it 'adds the target for the static library to the project' do @installer.install! @project.targets.count.should == 1 @@ -1242,6 +1356,26 @@ class PodsProjectGenerator #--------------------------------------------------------------------------------# + describe '#bcsymbolmap_paths' do + it 'de dups bcsymbol map paths that are found across multiple frameworks' do + framework_a = Pod::Xcode::FrameworkPaths.new('/path/to/A.framework', '/path/to/A.framework.dSYM', [ + '${PODS_ROOT}/path/to/A9FE499F-68E9-3984-A291-CFB68F9C77EB.bcsymbolmap', + '${PODS_ROOT}/path/to/48874290-E5EB-391C-A715-28CBA7F8B4B8.bcsymbolmap', + ]) + framework_b = Pod::Xcode::FrameworkPaths.new('/path/to/B.framework', '/path/to/B.framework.dSYM', [ + '${PODS_ROOT}/path/to/A9FE499F-68E9-3984-A291-CFB68F9C77EB.bcsymbolmap', + '${PODS_ROOT}/path/to/48874290-E5EB-391C-A715-28CBA7F8B4B8.bcsymbolmap', + ]) + @pod_target.stubs(:framework_paths).returns('Spec' => [framework_a, framework_b]) + Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller.bcsymbolmap_paths(@pod_target).should == [ + '${PODS_ROOT}/path/to/A9FE499F-68E9-3984-A291-CFB68F9C77EB.bcsymbolmap', + '${PODS_ROOT}/path/to/48874290-E5EB-391C-A715-28CBA7F8B4B8.bcsymbolmap', + ] + end + end + + #--------------------------------------------------------------------------------# + describe 'concerning header_mappings_dirs' do before do @project = Project.new(config.sandbox.project_path) @@ -1642,6 +1776,22 @@ class PodsProjectGenerator end core_data_sources_file.should.be.not.nil end + + it 'adds RealityComposer projects to the compile sources phase (non-bundles only)' do + native_target = @project.targets.first + + # The project should not be in the resources phase. + reality_composer_resources_file = native_target.resources_build_phase.files.find do |bf| + bf.file_ref.path == 'Resources/Sample.rcproject' + end + reality_composer_resources_file.should.be.nil + + # The project should not be in the resources phase. + reality_composer_sources_file = native_target.source_build_phase.files.find do |bf| + bf.file_ref.path == 'Resources/Sample.rcproject' + end + reality_composer_sources_file.should.be.not.nil + end end describe 'concerning resource bundles' do @@ -1714,14 +1864,14 @@ class PodsProjectGenerator describe 'xcframeworks' do it 'raises if a vendored xcframework has slices of mixed linkage' do - @pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))]) + @pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))]) Pod::Xcode::LinkageAnalyzer.stubs(:dynamic_binary?).returns(true, false, true, false, true, false, true) e = ->() { @installer.install! }.should.raise Informative e.message.should.include? 'Unable to install vendored xcframework `CoconutLib` for Pod `BananaLib`, because it contains both static and dynamic frameworks.' end it 'raises if a vendored xcframework is empty' do - xcframework = Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework')) + xcframework = Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework')) xcframework.stubs(:slices).returns([]) @pod_target.stubs(:xcframeworks).returns('Debug' => [xcframework]) e = ->() { @installer.install! }.should.raise Informative @@ -1753,7 +1903,7 @@ class PodsProjectGenerator end it 'creates the copy xcframeworks script phase if needed' do - @pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))]) + @pod_target.stubs(:xcframeworks).returns('Debug' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))]) @installer.expects(:create_copy_xcframeworks_script).once @installer.install! end diff --git a/spec/unit/installer/xcode/pods_project_generator/pod_target_integrator_spec.rb b/spec/unit/installer/xcode/pods_project_generator/pod_target_integrator_spec.rb index 4ab2d47473..1d84b95b11 100644 --- a/spec/unit/installer/xcode/pods_project_generator/pod_target_integrator_spec.rb +++ b/spec/unit/installer/xcode/pods_project_generator/pod_target_integrator_spec.rb @@ -144,7 +144,7 @@ class PodTargetIntegrator resource_paths = ['${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle'] @watermelon_pod_target.stubs(:framework_paths).returns('WatermelonLib' => framework_paths) @watermelon_pod_target.stubs(:resource_paths).returns('WatermelonLib' => resource_paths) - @watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))]) + @watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))]) test_native_target = stub('TestNativeTarget', :symbol_type => :unit_test_bundle, :build_phases => [], :shell_script_build_phases => [], :project => @project, :name => 'WatermelonLib-Unit-Tests') @@ -176,7 +176,7 @@ class PodTargetIntegrator resource_paths = ['${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle'] @watermelon_pod_target.stubs(:framework_paths).returns('WatermelonLib' => framework_paths) @watermelon_pod_target.stubs(:resource_paths).returns('WatermelonLib' => resource_paths) - @watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))]) + @watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))]) test_native_target = stub('TestNativeTarget', :symbol_type => :unit_test_bundle, :build_phases => [], :shell_script_build_phases => [], :project => @project, :name => 'WatermelonLib-Unit-Tests') @@ -201,6 +201,28 @@ class PodTargetIntegrator ] end + it 'integrates xcframeworks with input and output file lists even when frameworks are empty' do + @project.root_object.stubs(:compatibility_version).returns('Xcode 9.3') + @watermelon_pod_target.stubs(:framework_paths).returns({}) + @watermelon_pod_target.stubs(:resource_paths).returns({}) + @watermelon_pod_target.stubs(:xcframeworks).returns('WatermelonLib' => [Pod::Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))]) + test_native_target = stub('TestNativeTarget', :symbol_type => :unit_test_bundle, :build_phases => [], + :shell_script_build_phases => [], :project => @project, + :name => 'WatermelonLib-Unit-Tests') + installation_result = TargetInstallationResult.new(@watermelon_pod_target, @native_target, + [], [test_native_target]) + PodTargetIntegrator.new(installation_result, :use_input_output_paths => true).integrate! + test_native_target.build_phases.map(&:display_name).should == [ + '[CP] Embed Pods Frameworks', + ] + test_native_target.build_phases[0].input_file_list_paths.should == [ + '${PODS_ROOT}/Target Support Files/WatermelonLib/WatermelonLib-Unit-Tests-frameworks-input-files.xcfilelist', + ] + test_native_target.build_phases[0].output_file_list_paths.should == [ + '${PODS_ROOT}/Target Support Files/WatermelonLib/WatermelonLib-Unit-Tests-frameworks-output-files.xcfilelist', + ] + end + it 'does not include input output paths when use_input_output_paths is false' do framework_paths = [Pod::Xcode::FrameworkPaths.new('${PODS_ROOT}/Vendored/Vendored.framework')] resource_paths = ['${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle'] diff --git a/spec/unit/installer/xcode/target_validator_spec.rb b/spec/unit/installer/xcode/target_validator_spec.rb index 5f6007b548..6c3c5259b9 100644 --- a/spec/unit/installer/xcode/target_validator_spec.rb +++ b/spec/unit/installer/xcode/target_validator_spec.rb @@ -448,6 +448,7 @@ def create_validator(sandbox, podfile, lockfile) @validator = create_validator(config.sandbox, podfile, lockfile) @validator.stubs(:pod_targets).returns([stub('MultiSwift', :uses_swift? => true, + :should_build? => true, :swift_version => nil, :dependent_targets => [], :spec_swift_versions => ['4.0'])]) @@ -519,6 +520,29 @@ def create_validator(sandbox, podfile, lockfile) @validator.pod_targets.find { |pt| pt.name == 'matryoshka' }.stubs(:should_build?).returns(false) lambda { @validator.validate! }.should.not.raise end + + it 'does not raise when a pre built swift target depends upon a target that requires building' do + fixture_path = ROOT + 'spec/fixtures' + config.repos_dir = fixture_path + 'spec-repos' + podfile = Podfile.new do + project(fixture_path + 'SampleProject/SampleProject').to_s + platform :ios, '12.0' + install! 'cocoapods', :integrate_targets => false + pod 'VendoredSwiftFramework', :path => (fixture_path + 'prebuilt-swift-framework').to_s + pod 'matryoshka', :path => (fixture_path + 'matryoshka').to_s + target 'SampleProject' + target 'TestRunner' + end + lockfile = generate_lockfile + + @validator = create_validator(config.sandbox, podfile, lockfile) + podfile.target_definition_list.find { |td| td.name == 'SampleProject' }.swift_version = '3.0' + podfile.target_definition_list.find { |td| td.name == 'TestRunner' }.swift_version = '3.0' + vendored_swift_framework_pod_target = @validator.pod_targets.find { |pt| pt.name == 'VendoredSwiftFramework' } + matryoshka_pod_target = @validator.pod_targets.find { |pt| pt.name == 'matryoshka' } + vendored_swift_framework_pod_target.stubs(:dependent_targets).returns([matryoshka_pod_target]) + lambda { @validator.validate! }.should.not.raise + end end describe '#verify_no_multiple_project_names' do diff --git a/spec/unit/installer_spec.rb b/spec/unit/installer_spec.rb index 1bc330976e..27726d6a93 100644 --- a/spec/unit/installer_spec.rb +++ b/spec/unit/installer_spec.rb @@ -380,6 +380,29 @@ def @installer.clean_pod_sources UI.warnings.should.be.empty end + it 'does not print a warning if the master specs repo is explicitly used by a plugin' do + podfile = Pod::Podfile.new do + plugin 'my-plugin' + install! 'cocoapods', :integrate_targets => false + platform :ios + end + podfile.stubs(:plugins).returns('my-plugin' => {}) + + Pod::HooksManager.register('my-plugin', :source_provider) do |context, _| + plugin_source = Source.new(Pod::Installer::MASTER_SPECS_REPO_GIT_URL) + plugin_source.stubs(:url).returns(Pod::Installer::MASTER_SPECS_REPO_GIT_URL) + context.add_source(plugin_source) + end + + @installer = Installer.new(config.sandbox, podfile) + @installer.stubs(:ensure_plugins_are_installed!) + master_source = Source.new(Pod::Installer::MASTER_SPECS_REPO_GIT_URL) + master_source.stubs(:url).returns(Pod::Installer::MASTER_SPECS_REPO_GIT_URL) + config.sources_manager.stubs(:all).returns([master_source]) + @installer.send(:warn_for_removing_git_master_specs_repo) + UI.warnings.should.be.empty + end + it 'does not print a warning if the master specs repo is not explicitly used but is also not present in the users repo dir' do podfile = Pod::Podfile.new do install! 'cocoapods', :integrate_targets => false diff --git a/spec/unit/resolver_spec.rb b/spec/unit/resolver_spec.rb index 980071cdd0..8a30b7c34b 100644 --- a/spec/unit/resolver_spec.rb +++ b/spec/unit/resolver_spec.rb @@ -228,7 +228,8 @@ def create_resolver(podfile = @podfile, locked_deps = empty_graph, specs_updated it 'raises an informative error when version conflict is caused by platform incompatibilities for local pods' do sandbox = config.sandbox - local_spec = Specification.from_hash('name' => 'LocalPod', 'version' => '1.0', 'platforms' => { 'ios' => '8.0' }) + spec_hash = { 'name' => 'LocalPod', 'version' => '1.0', 'platforms' => { 'ios' => '8.0' } } + local_spec = Specification.from_hash(spec_hash) sandbox.stubs(:specification).with('LocalPod').returns(local_spec) @podfile = Podfile.new do target 'SampleProject' do @@ -1249,8 +1250,10 @@ def create_resolver(podfile = @podfile, locked_deps = empty_graph, specs_updated it 'resolves when there is no prerelease dependency on an external source pod' do sandbox = config.sandbox - local_pod = Specification.from_hash('name' => 'LocalPod', 'version' => '1.0.0.LOCAL') - local_pod2 = Specification.from_hash('name' => 'LocalPod2', 'version' => '1.0.0.LOCAL', 'dependencies' => { 'LocalPod' => [] }) + spec_hash = { 'name' => 'LocalPod', 'version' => '1.0.0.LOCAL' } + spec_hash2 = { 'name' => 'LocalPod2', 'version' => '1.0.0.LOCAL', 'dependencies' => { 'LocalPod' => [] } } + local_pod = Specification.from_hash(spec_hash) + local_pod2 = Specification.from_hash(spec_hash2) sandbox.stubs(:specification).with('LocalPod').returns(local_pod) sandbox.stubs(:specification).with('LocalPod2').returns(local_pod2) podfile = Podfile.new do diff --git a/spec/unit/sandbox/file_accessor_spec.rb b/spec/unit/sandbox/file_accessor_spec.rb index 5933dea99b..c6525c6094 100644 --- a/spec/unit/sandbox/file_accessor_spec.rb +++ b/spec/unit/sandbox/file_accessor_spec.rb @@ -94,8 +94,9 @@ module Pod ] end - it 'filters the private headers from the public headers' do + it 'filters the private and project headers from the public headers' do @spec_consumer.stubs(:public_header_files).returns([]) + @spec_consumer.stubs(:project_header_files).returns(['**/*Project*']) @spec_consumer.stubs(:private_header_files).returns(['**/*Private*']) @accessor.public_headers.sort.should == [ @root + 'Classes/Banana.h', @@ -115,11 +116,14 @@ module Pod it 'returns the resources' do @accessor.resources.sort.should == [ @root + 'Resources/Base.lproj', + @root + 'Resources/Base.lproj/Main.storyboard', @root + 'Resources/Images.xcassets', @root + 'Resources/Migration.xcmappingmodel', + @root + 'Resources/Sample.rcproject', @root + 'Resources/Sample.xcdatamodeld', @root + 'Resources/de.lproj', @root + 'Resources/en.lproj', + @root + 'Resources/en.lproj/Main.strings', @root + 'Resources/logo-sidebar.png', @root + 'Resources/sub_dir', ] @@ -169,6 +173,7 @@ module Pod @root + 'Resources/en.lproj', @root + 'Resources/Images.xcassets', @root + 'Resources/Migration.xcmappingmodel', + @root + 'Resources/Sample.rcproject', @root + 'Resources/Sample.xcdatamodeld', @root + 'Resources/sub_dir', ] @@ -184,12 +189,52 @@ module Pod @root + 'Resources/en.lproj', @root + 'Resources/Images.xcassets', @root + 'Resources/Migration.xcmappingmodel', + @root + 'Resources/Sample.rcproject', @root + 'Resources/Sample.xcdatamodeld', @root + 'Resources/sub_dir', ] @accessor.resource_bundle_files.should == resource_paths end + it 'returns the expanded paths of the files of the on demand resources' do + on_demand_resources = { 'OnDemandResources' => { :paths => ['Resources/*'], :category => :download_on_demand } } + @spec_consumer.stubs(:on_demand_resources).returns(on_demand_resources) + expected_on_demand_resources = { + 'OnDemandResources' => { + :paths => [ + @root + 'Resources/logo-sidebar.png', + @root + 'Resources/Base.lproj', + @root + 'Resources/de.lproj', + @root + 'Resources/en.lproj', + @root + 'Resources/Images.xcassets', + @root + 'Resources/Migration.xcmappingmodel', + @root + 'Resources/Sample.rcproject', + @root + 'Resources/Sample.xcdatamodeld', + @root + 'Resources/sub_dir', + ], + :category => :download_on_demand, + }, + } + @accessor.on_demand_resources.should == expected_on_demand_resources + end + + it 'returns all the expanded paths of the files of the on demand resources' do + on_demand_resources = { 'OnDemandResources' => { :paths => ['Resources/*'], :category => :download_on_demand } } + @spec_consumer.stubs(:on_demand_resources).returns(on_demand_resources) + expected_on_demand_resources = [ + @root + 'Resources/logo-sidebar.png', + @root + 'Resources/Base.lproj', + @root + 'Resources/de.lproj', + @root + 'Resources/en.lproj', + @root + 'Resources/Images.xcassets', + @root + 'Resources/Migration.xcmappingmodel', + @root + 'Resources/Sample.rcproject', + @root + 'Resources/Sample.xcdatamodeld', + @root + 'Resources/sub_dir', + ] + @accessor.on_demand_resources_files.should == expected_on_demand_resources + end + it 'takes into account exclude_files when creating the resource bundles of the pod' do @spec_consumer.stubs(:exclude_files).returns(['**/*.png']) @spec_consumer.stubs(:resource_bundles).returns('BananaLib' => 'Resources/*') @@ -199,6 +244,7 @@ module Pod @root + 'Resources/en.lproj', @root + 'Resources/Images.xcassets', @root + 'Resources/Migration.xcmappingmodel', + @root + 'Resources/Sample.rcproject', @root + 'Resources/Sample.xcdatamodeld', @root + 'Resources/sub_dir', ] diff --git a/spec/unit/sandbox/path_list_spec.rb b/spec/unit/sandbox/path_list_spec.rb index 3d66dd08c4..58ad5805d5 100644 --- a/spec/unit/sandbox/path_list_spec.rb +++ b/spec/unit/sandbox/path_list_spec.rb @@ -28,6 +28,11 @@ module Pod Resources/Images.xcassets/Logo.imageset/Contents.json Resources/Images.xcassets/Logo.imageset/logo.png Resources/Migration.xcmappingmodel/xcmapping.xml + Resources/Sample.rcproject/Library/ProjectLibrary/Contents.json + Resources/Sample.rcproject/Library/ProjectLibrary/Version.json + Resources/Sample.rcproject/SceneThumbnails/A6BD9D7A-36EE-4D49-BF83-DEB3039A790C.thumbnails/square + Resources/Sample.rcproject/SceneThumbnails/A6BD9D7A-36EE-4D49-BF83-DEB3039A790C.thumbnails/wide + Resources/Sample.rcproject/com.apple.RCFoundation.Project Resources/Sample.xcdatamodeld/.xccurrentversion Resources/Sample.xcdatamodeld/Sample\ 2.xcdatamodel/contents Resources/Sample.xcdatamodeld/Sample.xcdatamodel/contents @@ -67,6 +72,11 @@ module Pod Resources/Images.xcassets Resources/Images.xcassets/Logo.imageset Resources/Migration.xcmappingmodel + Resources/Sample.rcproject + Resources/Sample.rcproject/Library + Resources/Sample.rcproject/Library/ProjectLibrary + Resources/Sample.rcproject/SceneThumbnails + Resources/Sample.rcproject/SceneThumbnails/A6BD9D7A-36EE-4D49-BF83-DEB3039A790C.thumbnails Resources/Sample.xcdatamodeld Resources/Sample.xcdatamodeld/Sample\ 2.xcdatamodel Resources/Sample.xcdatamodeld/Sample.xcdatamodel @@ -185,6 +195,7 @@ module Pod Resources/Base.lproj Resources/Images.xcassets Resources/Migration.xcmappingmodel + Resources/Sample.rcproject Resources/Sample.xcdatamodeld Resources/de.lproj Resources/en.lproj diff --git a/spec/unit/sandbox/pod_dir_cleaner_spec.rb b/spec/unit/sandbox/pod_dir_cleaner_spec.rb index aad2ecfcb9..74b3a04560 100644 --- a/spec/unit/sandbox/pod_dir_cleaner_spec.rb +++ b/spec/unit/sandbox/pod_dir_cleaner_spec.rb @@ -47,11 +47,14 @@ module Pod LICENSE README Resources/Base.lproj + Resources/Base.lproj/Main.storyboard Resources/Images.xcassets Resources/Migration.xcmappingmodel + Resources/Sample.rcproject Resources/Sample.xcdatamodeld Resources/de.lproj Resources/en.lproj + Resources/en.lproj/Main.strings Resources/logo-sidebar.png Resources/sub_dir framework/Source/MoreBanana.h @@ -82,11 +85,14 @@ module Pod LICENSE README Resources/Base.lproj + Resources/Base.lproj/Main.storyboard Resources/Images.xcassets Resources/Migration.xcmappingmodel + Resources/Sample.rcproject Resources/Sample.xcdatamodeld Resources/de.lproj Resources/en.lproj + Resources/en.lproj/Main.strings Resources/logo-sidebar.png Resources/sub_dir libBananaStaticLib.a diff --git a/spec/unit/sources_manager_spec.rb b/spec/unit/sources_manager_spec.rb index 94e5db1ff4..de07e65a7d 100644 --- a/spec/unit/sources_manager_spec.rb +++ b/spec/unit/sources_manager_spec.rb @@ -154,6 +154,10 @@ module Pod @sources_manager.cdn_url?('http://cdn.cocoapods.org').should == true end + it 'spec repo with userinfo' do + @sources_manager.cdn_url?('https://foo:bar@bitbucket.org/foobar/Specs.git').should == false + end + it 'git master spec repo' do stub_as_404('https://github.com/cocoapods/specs.git') stub_as_404('https://github.com/cocoapods/specs') diff --git a/spec/unit/target/aggregate_target_spec.rb b/spec/unit/target/aggregate_target_spec.rb index e4bc927fc8..6c3cb91f8f 100644 --- a/spec/unit/target/aggregate_target_spec.rb +++ b/spec/unit/target/aggregate_target_spec.rb @@ -49,7 +49,7 @@ module Pod it 'returns whether it has xcframeworks to embed' do @target.stubs(:xcframeworks_by_config).returns( - 'DEBUG' => [Xcode::XCFramework.new(fixture('CoconutLib.xcframework'))], + 'DEBUG' => [Xcode::XCFramework.new('CoconutLib', fixture('CoconutLib.xcframework'))], ) @target.includes_xcframeworks?.should.be.true @target.stubs(:xcframeworks_by_config).returns('DEBUG' => [], 'RELEASE' => []) @@ -146,7 +146,7 @@ module Pod end end - describe 'frameworks by config and input output paths' do + describe 'pod target paths' do before do @coconut_spec = fixture_spec('coconut-lib/CoconutLib.podspec') file_accessor = fixture_file_accessor(@coconut_spec, Platform.ios) @@ -187,7 +187,7 @@ module Pod resource_paths_by_config['Release'].should == ['MyResources.bundle'] end - it 'checks resource paths for compilable are converted for static frameworks' do + it 'checks resource paths for compilable files are converted for static frameworks' do @pod_target.stubs(:should_build?).returns(true) @pod_target.stubs(:build_type => BuildType.static_framework) convertible_files = %w[.storyboard .xib .xcdatamodel .xcdatamodeld .xcmappingmodel].map { |ext| "${PODS_ROOT}/Filename#{ext}" } @@ -199,7 +199,7 @@ module Pod resource_paths_by_config['Release'].should == expected_files end - it 'checks resource paths for compilable are converted for static frameworks with multiple file extensions' do + it 'checks resource paths for compilable files are converted for static frameworks with multiple file extensions' do @pod_target.stubs(:should_build?).returns(true) @pod_target.stubs(:build_type => BuildType.static_framework) convertible_files = %w[.storyboard .xib .xcdatamodel .xcdatamodeld .xcmappingmodel].map { |ext| "${PODS_ROOT}/Filename.Suffix#{ext}" } @@ -211,6 +211,18 @@ module Pod resource_paths_by_config['Release'].should == expected_files end + it 'checks resource paths for compilable files are converted for static frameworks when base-localized' do + @pod_target.stubs(:should_build?).returns(true) + @pod_target.stubs(:build_type => BuildType.static_framework) + convertible_files = %w[${PODS_ROOT}/some/folder/Base.lproj/Main.storyboard ${PODS_ROOT}/some/folder/en.lproj/Main.strings] + @pod_target.stubs(:resource_paths).returns('BananaLib' => convertible_files) + @target.stubs(:bridge_support_file).returns(nil) + resource_paths_by_config = @target.resource_paths_by_config + expected_files = %w[${BUILT_PRODUCTS_DIR}/BananaLib/BananaLib.framework/Base.lproj/Main.storyboardc ${PODS_ROOT}/some/folder/en.lproj/Main.strings] + resource_paths_by_config['Debug'].should == expected_files + resource_paths_by_config['Release'].should == expected_files + end + it 'checks xcassets resource paths are not converted for static frameworks' do @pod_target.stubs(:should_build?).returns(true) @pod_target.stubs(:build_type => BuildType.static_framework) @@ -273,6 +285,15 @@ module Pod @pod_target.file_accessors.first.stubs(:vendored_xcframeworks).returns([framework_path]) @target.xcframeworks_by_config['Debug'].map(&:path).should == [framework_path] end + + it 'returns on demand resources paths' do + @target.stubs(:pod_targets).returns([@pod_target, @pod_target_release]) + on_demand_resources = { 'tag1' => { :paths => ['./banana-lib/path/to/resource'], :category => :download_on_demand } } + @pod_target.file_accessors.first.stubs(:on_demand_resources).returns(on_demand_resources) + release_on_demand_resources = { 'othertag1' => { :paths => ['./coconutlib/path/to/other/resource'], :category => :download_on_demand } } + @pod_target_release.file_accessors.first.stubs(:on_demand_resources).returns(release_on_demand_resources) + @target.on_demand_resources.should == ['./banana-lib/path/to/resource', './coconutlib/path/to/other/resource'] + end end it 'returns the specs of the Pods used by this aggregate target' do diff --git a/spec/unit/target/build_settings/aggregate_target_settings_spec.rb b/spec/unit/target/build_settings/aggregate_target_settings_spec.rb index 1686c6d53e..d0f3467de7 100644 --- a/spec/unit/target/build_settings/aggregate_target_settings_spec.rb +++ b/spec/unit/target/build_settings/aggregate_target_settings_spec.rb @@ -205,7 +205,7 @@ def pod_target(spec, target_definition) end end - it 'does not links the pod targets with the aggregate target for non-whitelisted configuration' do + it 'does not link the pod targets with the aggregate target for non-whitelisted configuration' do @generator = AggregateTargetSettings.new(@target, 'Debug', :configuration => :debug) @xcconfig = @generator.dup.generate @xcconfig.to_hash['OTHER_LDFLAGS'].should.be.nil @@ -213,7 +213,7 @@ def pod_target(spec, target_definition) it 'does propagate framework or libraries from a non test specification to an aggregate target' do target_definition = stub('target_definition', :inheritance => 'complete', :abstract? => false, :podfile => Podfile.new, :platform => Platform.ios) - spec = stub('spec', :library_specification? => true, :spec_type => :library) + spec = stub('spec', :library_specification? => true, :spec_type => :library, :name => 'Spec') consumer = stub('consumer', :libraries => ['xml2'], :frameworks => ['XCTest'], @@ -221,6 +221,7 @@ def pod_target(spec, target_definition) :spec => spec, ) xcframework = stub('xcframework', + :target_name => 'PodTarget', :name => 'VendoredXCFramework', :build_type => BuildType.static_library, :slices => [stub('slice', :binary_path => Pathname.new('/tmp/path/to/libVendoredXCFramework.a'))], @@ -255,6 +256,7 @@ def pod_target(spec, target_definition) :uses_swift? => false, :build_product_path => 'BPP', :product_basename => 'PodTarget', + :label => 'PodTarget', :target_definitions => [target_definition], :root_spec => spec, ) diff --git a/spec/unit/validator_spec.rb b/spec/unit/validator_spec.rb index 8811fe1710..7f5d08b448 100644 --- a/spec/unit/validator_spec.rb +++ b/spec/unit/validator_spec.rb @@ -36,8 +36,9 @@ def stub_podspec(pattern = nil, replacement = nil) # @return [Pathname] # - def podspec_path(name = 'JSONKit', version = '1.4') - Config.instance.sources_manager.master.first.specification_path(name, version) + def podspec_path(name = 'JSONKit', version = '1.4', source = nil) + source = Config.instance.sources_manager.master.first if source.nil? + source.specification_path(name, version) end #-------------------------------------------------------------------------# @@ -91,7 +92,8 @@ def podspec_path(name = 'JSONKit', version = '1.4') describe '#only_subspec' do before do - podspec = podspec_path('RestKit', '0.22.0') + test_repo_source = Config.instance.sources_manager.source_with_name_or_url('test_repo') + podspec = podspec_path('RestKit', '0.22.0', test_repo_source) @validator = Validator.new(podspec, config.sources_manager.master.map(&:url)) @validator.quick = true end @@ -108,6 +110,18 @@ def podspec_path(name = 'JSONKit', version = '1.4') @validator.send(:subspec_name).should == 'RestKit/CoreData' end + it 'handles a relative subspec name which starts with the pod name' do + @validator.only_subspec = 'RestKitSubspec' + @validator.validate + @validator.send(:subspec_name).should == 'RestKit/RestKitSubspec' + end + + it 'handles an absolute subspec name which starts with the pod name' do + @validator.only_subspec = 'RestKit/RestKitSubspec' + @validator.validate + @validator.send(:subspec_name).should == 'RestKit/RestKitSubspec' + end + it 'handles a missing subspec name' do @validator.only_subspec = 'RestKit/Missing' should.raise(Informative) { @validator.validate }.message. @@ -983,7 +997,9 @@ def podspec_path(name = 'JSONKit', version = '1.4') target.symbol_type.should == :application target.deployment_target.should.be.nil target.platform_name.should == :ios - + target.build_configurations.each do |c| + c.build_settings['INFOPLIST_FILE'].should == '$(SRCROOT)/App/App-Info.plist' + end Xcodeproj::Project.schemes(project.path).should == %w(App) end @@ -1128,6 +1144,16 @@ def podspec_path(name = 'JSONKit', version = '1.4') validator.result_type.should == :warning end + it 'warns if project_header_files does not match any files' do + file = write_podspec(stub_podspec(/.*source_files.*/, '"source_files": "JSONKit.*", "project_header_files": "MissingHeader.h",')) + validator = Validator.new(file, config.sources_manager.master.map(&:url)) + validator.stubs(:build_pod) + validator.stubs(:validate_url) + validator.validate + validator.results.map(&:to_s).first.should.match /The `project_header_files` pattern did not match any file./ + validator.result_type.should == :warning + end + it 'warns if private_header_files does not match any files' do file = write_podspec(stub_podspec(/.*source_files.*/, '"source_files": "JSONKit.*", "private_header_files": "MissingHeader.h",')) validator = Validator.new(file, config.sources_manager.master.map(&:url)) @@ -1297,9 +1323,26 @@ def setup_validator validator.stubs(:validate_url) validator.validate - validator.results.map(&:to_s).first.should.match /Dynamic frameworks.*iOS 8.0 and onwards/ + validator.results.count.should == 2 + validator.results.map(&:to_s)[0].should.match /`empty\.dylib` does not match the expected static library name format/ + validator.results.map(&:to_s)[1].should.match /Dynamic frameworks.*iOS 8.0 and onwards/ validator.result_type.should == :error end + + it 'uses the expanded paths of the vendored libraries to validate them' do + podspec = stub_podspec(/.*source_files.*/, " \"source_files\": \"JSONKit.*\",\n \"vendored_libraries\": \"**/*.a\",") + file = write_podspec(podspec) + + Pod::Sandbox::FileAccessor.any_instance.stubs(:vendored_libraries).returns([fixture('monkey/monkey.a'), fixture('banana-lib/libBananaStaticLib.a')]) + validator = Validator.new(file, config.sources_manager.master.map(&:url)) + validator.stubs(:build_pod) + validator.stubs(:validate_url) + validator.validate + + validator.results.count.should == 1 + validator.results.map(&:to_s).first.should.match /`monkey\.a` does not match the expected static library name format/ + validator.result_type.should == :warning + end end describe 'additional podspecs' do @@ -1749,7 +1792,7 @@ def create_target_with_validator_consumer(validator, consumer) project.native_targets.find { |t| t.name == 'App' } end - describe 'check appicon key deleted' do + describe 'sets various configuration settings' do before do @validator = Validator.new(podspec_path, config.sources_manager.master.map(&:url)) @validator.stubs(:validate_url) @@ -1759,39 +1802,79 @@ def create_target_with_validator_consumer(validator, consumer) @validator.send(:tear_down_validation_environment) end - it 'ios platform deletes AppIcon key' do - consumer = Specification.from_file(podspec_path).consumer(:ios) - target = create_target_with_validator_consumer(@validator, consumer) + describe 'sets the product bundle identifier' do + it 'ios platform sets product bundle identifier' do + consumer = Specification.from_file(podspec_path).consumer(:ios) + target = create_target_with_validator_consumer(@validator, consumer) - target.build_configurations.each do |config| - config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + target.build_configurations.each do |config| + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' + end end - end - it 'tvos platform deletes AppIcon key' do - consumer = Specification.from_file(podspec_path).consumer(:tvos) - target = create_target_with_validator_consumer(@validator, consumer) + it 'tvos platform deletes AppIcon key' do + consumer = Specification.from_file(podspec_path).consumer(:tvos) + target = create_target_with_validator_consumer(@validator, consumer) - target.build_configurations.each do |config| - config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + target.build_configurations.each do |config| + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' + end + end + + it 'osx platform deletes AppIcon key' do + consumer = Specification.from_file(podspec_path).consumer(:osx) + target = create_target_with_validator_consumer(@validator, consumer) + + target.build_configurations.each do |config| + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' + end end - end - it 'osx platform deletes AppIcon key' do - consumer = Specification.from_file(podspec_path).consumer(:osx) - target = create_target_with_validator_consumer(@validator, consumer) + it 'watchos platform deletes AppIcon key' do + consumer = Specification.from_file(podspec_path).consumer(:watchos) + target = create_target_with_validator_consumer(@validator, consumer) - target.build_configurations.each do |config| - config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + target.build_configurations.each do |config| + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' + end end end - it 'watchos platform deletes AppIcon key' do - consumer = Specification.from_file(podspec_path).consumer(:watchos) - target = create_target_with_validator_consumer(@validator, consumer) + describe 'check appicon key deleted' do + it 'ios platform deletes AppIcon key' do + consumer = Specification.from_file(podspec_path).consumer(:ios) + target = create_target_with_validator_consumer(@validator, consumer) + + target.build_configurations.each do |config| + config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + end + end + + it 'tvos platform deletes AppIcon key' do + consumer = Specification.from_file(podspec_path).consumer(:tvos) + target = create_target_with_validator_consumer(@validator, consumer) + + target.build_configurations.each do |config| + config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + end + end + + it 'osx platform deletes AppIcon key' do + consumer = Specification.from_file(podspec_path).consumer(:osx) + target = create_target_with_validator_consumer(@validator, consumer) + + target.build_configurations.each do |config| + config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + end + end + + it 'watchos platform deletes AppIcon key' do + consumer = Specification.from_file(podspec_path).consumer(:watchos) + target = create_target_with_validator_consumer(@validator, consumer) - target.build_configurations.each do |config| - config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + target.build_configurations.each do |config| + config.build_settings.key?('ASSETCATALOG_COMPILER_APPICON_NAME').should.be.false + end end end end diff --git a/spec/unit/xcode/xcframework_spec.rb b/spec/unit/xcode/xcframework_spec.rb index d3018b8e10..53472c769d 100644 --- a/spec/unit/xcode/xcframework_spec.rb +++ b/spec/unit/xcode/xcframework_spec.rb @@ -7,7 +7,7 @@ module Xcode describe 'when parsing `Info.plist`' do before do @framework_path = fixture('CoconutLib.xcframework') - @framework = XCFramework.new(@framework_path) + @framework = XCFramework.new('CoconutLib', @framework_path) end it 'reads the format version' do @@ -85,7 +85,7 @@ module Xcode describe 'library packaging' do before do @framework_path = fixture('xcframeworks/StaticLibrary/CoconutLib.xcframework') - @framework = XCFramework.new(@framework_path) + @framework = XCFramework.new('CoconutLib', @framework_path) end it 'reads the library slices' do