cocoapods 1.10.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +571 -7
  3. data/README.md +10 -11
  4. data/bin/sandbox-pod +1 -1
  5. data/lib/cocoapods/command/lib/lint.rb +4 -1
  6. data/lib/cocoapods/command/outdated.rb +12 -1
  7. data/lib/cocoapods/command/repo/push.rb +20 -0
  8. data/lib/cocoapods/command/setup.rb +2 -2
  9. data/lib/cocoapods/command/spec/cat.rb +3 -1
  10. data/lib/cocoapods/command/spec/create.rb +1 -0
  11. data/lib/cocoapods/command/spec/lint.rb +4 -1
  12. data/lib/cocoapods/command/spec/which.rb +3 -1
  13. data/lib/cocoapods/command/spec.rb +18 -9
  14. data/lib/cocoapods/config.rb +8 -7
  15. data/lib/cocoapods/downloader/cache.rb +98 -6
  16. data/lib/cocoapods/downloader.rb +4 -2
  17. data/lib/cocoapods/executable.rb +1 -1
  18. data/lib/cocoapods/external_sources/abstract_external_source.rb +1 -1
  19. data/lib/cocoapods/external_sources/path_source.rb +1 -1
  20. data/lib/cocoapods/external_sources/podspec_source.rb +1 -1
  21. data/lib/cocoapods/gem_version.rb +1 -1
  22. data/lib/cocoapods/generator/acknowledgements.rb +13 -1
  23. data/lib/cocoapods/generator/app_target_helper.rb +8 -4
  24. data/lib/cocoapods/generator/copy_dsyms_script.rb +4 -4
  25. data/lib/cocoapods/generator/copy_resources_script.rb +2 -1
  26. data/lib/cocoapods/generator/copy_xcframework_script.rb +52 -70
  27. data/lib/cocoapods/generator/embed_frameworks_script.rb +4 -3
  28. data/lib/cocoapods/generator/info_plist_file.rb +1 -1
  29. data/lib/cocoapods/generator/script_phase_constants.rb +1 -0
  30. data/lib/cocoapods/installer/analyzer/analysis_result.rb +3 -3
  31. data/lib/cocoapods/installer/analyzer/pod_variant.rb +1 -1
  32. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +38 -10
  33. data/lib/cocoapods/installer/analyzer.rb +21 -13
  34. data/lib/cocoapods/installer/base_install_hooks_context.rb +19 -4
  35. data/lib/cocoapods/installer/installation_options.rb +11 -0
  36. data/lib/cocoapods/installer/pod_source_downloader.rb +159 -0
  37. data/lib/cocoapods/installer/pod_source_installer.rb +10 -36
  38. data/lib/cocoapods/installer/podfile_validator.rb +2 -2
  39. data/lib/cocoapods/installer/pre_integrate_hooks_context.rb +9 -0
  40. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +14 -7
  41. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +15 -2
  42. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +48 -7
  43. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +150 -9
  44. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +11 -3
  45. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +62 -9
  46. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +6 -19
  47. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +86 -59
  48. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +48 -6
  49. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +3 -1
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +2 -2
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +8 -5
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +9 -3
  53. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +37 -2
  54. data/lib/cocoapods/installer/xcode/target_validator.rb +1 -1
  55. data/lib/cocoapods/installer.rb +150 -34
  56. data/lib/cocoapods/native_target_extension.rb +1 -1
  57. data/lib/cocoapods/open-uri.rb +1 -1
  58. data/lib/cocoapods/project.rb +8 -8
  59. data/lib/cocoapods/resolver/resolver_specification.rb +1 -1
  60. data/lib/cocoapods/resolver.rb +7 -7
  61. data/lib/cocoapods/sandbox/file_accessor.rb +67 -11
  62. data/lib/cocoapods/sandbox/headers_store.rb +3 -1
  63. data/lib/cocoapods/sandbox/path_list.rb +2 -2
  64. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +1 -1
  65. data/lib/cocoapods/sandbox.rb +48 -12
  66. data/lib/cocoapods/sources_manager.rb +18 -9
  67. data/lib/cocoapods/target/aggregate_target.rb +23 -1
  68. data/lib/cocoapods/target/build_settings.rb +67 -22
  69. data/lib/cocoapods/target/pod_target.rb +49 -24
  70. data/lib/cocoapods/target.rb +1 -1
  71. data/lib/cocoapods/user_interface.rb +6 -2
  72. data/lib/cocoapods/validator.rb +58 -22
  73. data/lib/cocoapods/version_metadata.rb +1 -1
  74. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +22 -7
  75. data/lib/cocoapods/xcode/xcframework.rb +9 -4
  76. data/lib/cocoapods.rb +2 -0
  77. metadata +35 -27
@@ -36,8 +36,10 @@ module Pod
36
36
  autoload :PreInstallHooksContext, 'cocoapods/installer/pre_install_hooks_context'
37
37
  autoload :BaseInstallHooksContext, 'cocoapods/installer/base_install_hooks_context'
38
38
  autoload :PostIntegrateHooksContext, 'cocoapods/installer/post_integrate_hooks_context'
39
+ autoload :PreIntegrateHooksContext, 'cocoapods/installer/pre_integrate_hooks_context'
39
40
  autoload :SourceProviderHooksContext, 'cocoapods/installer/source_provider_hooks_context'
40
41
  autoload :PodfileValidator, 'cocoapods/installer/podfile_validator'
42
+ autoload :PodSourceDownloader, 'cocoapods/installer/pod_source_downloader'
41
43
  autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
42
44
  autoload :PodSourcePreparer, 'cocoapods/installer/pod_source_preparer'
43
45
  autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
@@ -160,8 +162,10 @@ module Pod
160
162
  resolve_dependencies
161
163
  download_dependencies
162
164
  validate_targets
165
+ clean_sandbox
163
166
  if installation_options.skip_pods_project_generation?
164
167
  show_skip_pods_project_generation_message
168
+ run_podfile_post_install_hooks
165
169
  else
166
170
  integrate
167
171
  end
@@ -175,6 +179,7 @@ module Pod
175
179
  end
176
180
 
177
181
  def integrate
182
+ run_podfile_pre_integrate_hooks
178
183
  generate_pods_project
179
184
  if installation_options.integrate_targets?
180
185
  integrate_user_project
@@ -199,7 +204,7 @@ module Pod
199
204
 
200
205
  force_clean_install = clean_install || project_cache_version.version != Version.create(VersionMetadata.project_cache_version)
201
206
  cache_result = ProjectCache::ProjectCacheAnalyzer.new(sandbox, installation_cache, analysis_result.all_user_build_configurations,
202
- object_version, plugins, pod_targets, aggregate_targets, :clean_install => force_clean_install).analyze
207
+ object_version, plugins, pod_targets, aggregate_targets, installation_options.to_h, :clean_install => force_clean_install).analyze
203
208
  aggregate_targets_to_generate = cache_result.aggregate_targets_to_generate || []
204
209
  pod_targets_to_generate = cache_result.pod_targets_to_generate
205
210
  (aggregate_targets_to_generate + pod_targets_to_generate).each do |target|
@@ -294,7 +299,10 @@ module Pod
294
299
  pod_targets_to_generate = cache_analysis_result.pod_targets_to_generate
295
300
  aggregate_targets_to_generate = cache_analysis_result.aggregate_targets_to_generate
296
301
 
297
- clean_sandbox(pod_targets_to_generate)
302
+ pod_targets_to_generate.each do |pod_target|
303
+ pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
304
+ sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
305
+ end
298
306
 
299
307
  create_and_save_projects(pod_targets_to_generate, aggregate_targets_to_generate,
300
308
  cache_analysis_result.build_configurations, cache_analysis_result.project_object_version)
@@ -441,23 +449,30 @@ module Pod
441
449
  end
442
450
  end
443
451
 
444
- # @return [void] In this step we clean all the header folders for pod targets that will be
445
- # regenerated from scratch and cleanup any pods that have been removed.
452
+ # @return [void] Performs a general clean up of the sandbox related to the sandbox state that was
453
+ # calculated. For example, pods that were marked for deletion are removed.
446
454
  #
447
- def clean_sandbox(pod_targets)
448
- pod_targets.each do |pod_target|
449
- pod_target.build_headers.implode_path!(pod_target.headers_sandbox)
450
- sandbox.public_headers.implode_path!(pod_target.headers_sandbox)
451
- end
452
-
455
+ def clean_sandbox
453
456
  unless sandbox_state.deleted.empty?
454
457
  title_options = { :verbose_prefix => '-> '.red }
455
458
  sandbox_state.deleted.each do |pod_name|
456
459
  UI.titled_section("Removing #{pod_name}".red, title_options) do
457
- sandbox.clean_pod(pod_name)
460
+ root_name = Specification.root_name(pod_name)
461
+ pod_dir = sandbox.local?(root_name) ? nil : sandbox.pod_dir(root_name)
462
+ sandbox.clean_pod(pod_name, pod_dir)
458
463
  end
459
464
  end
460
465
  end
466
+
467
+ # Check any changed pods that became local pods and used to be remote pods and
468
+ # ensure the sandbox is cleaned up.
469
+ unless sandbox_state.changed.empty?
470
+ sandbox_state.changed.each do |pod_name|
471
+ previous_spec_repo = sandbox.manifest.spec_repo(pod_name)
472
+ should_clean = !previous_spec_repo.nil? && sandbox.local?(pod_name)
473
+ sandbox.clean_pod(pod_name, sandbox.sources_root + Specification.root_name(pod_name)) if should_clean
474
+ end
475
+ end
461
476
  end
462
477
 
463
478
  # @raise [Informative] If there are any Podfile changes
@@ -488,26 +503,38 @@ module Pod
488
503
  # @return [void]
489
504
  #
490
505
  def install_pod_sources
506
+ @downloaded_specs = []
491
507
  @installed_specs = []
492
508
  pods_to_install = sandbox_state.added | sandbox_state.changed
493
509
  title_options = { :verbose_prefix => '-> '.green }
494
- root_specs.sort_by(&:name).each do |spec|
495
- if pods_to_install.include?(spec.name)
496
- if sandbox_state.changed.include?(spec.name) && sandbox.manifest
497
- current_version = spec.version
498
- previous_version = sandbox.manifest.version(spec.name)
499
- has_changed_version = current_version != previous_version
500
- current_repo = analysis_result.specs_by_source.detect { |key, values| break key if values.map(&:name).include?(spec.name) }
501
- current_repo &&= (Pod::TrunkSource::TRUNK_REPO_NAME if current_repo.name == Pod::TrunkSource::TRUNK_REPO_NAME) || current_repo.url || current_repo.name
502
- previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
503
- has_changed_repo = !previous_spec_repo.nil? && current_repo && !current_repo.casecmp(previous_spec_repo).zero?
504
- title = "Installing #{spec.name} #{spec.version}"
505
- title << " (was #{previous_version} and source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if has_changed_version && has_changed_repo
506
- title << " (was #{previous_version})" if has_changed_version && !has_changed_repo
507
- title << " (source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if !has_changed_version && has_changed_repo
508
- else
509
- title = "Installing #{spec}"
510
+
511
+ sorted_root_specs = root_specs.sort_by(&:name)
512
+
513
+ # Download pods in parallel before installing if the option is set
514
+ if installation_options.parallel_pod_downloads
515
+ require 'concurrent/executor/fixed_thread_pool'
516
+ thread_pool_size = installation_options.parallel_pod_download_thread_pool_size
517
+ thread_pool = Concurrent::FixedThreadPool.new(thread_pool_size, :idletime => 300)
518
+
519
+ sorted_root_specs.each do |spec|
520
+ if pods_to_install.include?(spec.name)
521
+ title = section_title(spec, 'Downloading')
522
+ UI.titled_section(title.green, title_options) do
523
+ thread_pool.post do
524
+ download_source_of_pod(spec.name)
525
+ end
526
+ end
510
527
  end
528
+ end
529
+
530
+ thread_pool.shutdown
531
+ thread_pool.wait_for_termination
532
+ end
533
+
534
+ # Install pods, which includes downloading only if parallel_pod_downloads is set to false
535
+ sorted_root_specs.each do |spec|
536
+ if pods_to_install.include?(spec.name)
537
+ title = section_title(spec, 'Installing')
511
538
  UI.titled_section(title.green, title_options) do
512
539
  install_source_of_pod(spec.name)
513
540
  end
@@ -519,13 +546,32 @@ module Pod
519
546
  end
520
547
  end
521
548
 
549
+ def section_title(spec, current_action)
550
+ if sandbox_state.changed.include?(spec.name) && sandbox.manifest
551
+ current_version = spec.version
552
+ previous_version = sandbox.manifest.version(spec.name)
553
+ has_changed_version = current_version != previous_version
554
+ current_repo = analysis_result.specs_by_source.detect { |key, values| break key if values.map(&:name).include?(spec.name) }
555
+ current_repo &&= (Pod::TrunkSource::TRUNK_REPO_NAME if current_repo.name == Pod::TrunkSource::TRUNK_REPO_NAME) || current_repo.url || current_repo.name
556
+ previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
557
+ has_changed_repo = !previous_spec_repo.nil? && current_repo && !current_repo.casecmp(previous_spec_repo).zero?
558
+ title = "#{current_action} #{spec.name} #{spec.version}"
559
+ title << " (was #{previous_version} and source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if has_changed_version && has_changed_repo
560
+ title << " (was #{previous_version})" if has_changed_version && !has_changed_repo
561
+ title << " (source changed to `#{current_repo}` from `#{previous_spec_repo}`)" if !has_changed_version && has_changed_repo
562
+ else
563
+ title = "#{current_action} #{spec}"
564
+ end
565
+ title
566
+ end
567
+
522
568
  def create_pod_installer(pod_name)
523
569
  specs_by_platform = specs_for_pod(pod_name)
524
570
 
525
571
  if specs_by_platform.empty?
526
572
  requiring_targets = pod_targets.select { |pt| pt.recursive_dependent_targets.any? { |dt| dt.pod_name == pod_name } }
527
573
  message = "Could not install '#{pod_name}' pod"
528
- message += ", dependended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
574
+ message += ", depended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
529
575
  message += '. There is either no platform to build for, or no target to build.'
530
576
  raise StandardError, message
531
577
  end
@@ -535,6 +581,20 @@ module Pod
535
581
  pod_installer
536
582
  end
537
583
 
584
+ def create_pod_downloader(pod_name)
585
+ specs_by_platform = specs_for_pod(pod_name)
586
+
587
+ if specs_by_platform.empty?
588
+ requiring_targets = pod_targets.select { |pt| pt.recursive_dependent_targets.any? { |dt| dt.pod_name == pod_name } }
589
+ message = "Could not download '#{pod_name}' pod"
590
+ message += ", depended upon by #{requiring_targets.to_sentence}" unless requiring_targets.empty?
591
+ message += '. There is either no platform to build for, or no target to build.'
592
+ raise StandardError, message
593
+ end
594
+
595
+ PodSourceDownloader.new(sandbox, podfile, specs_by_platform, :can_cache => installation_options.clean?)
596
+ end
597
+
538
598
  # The specifications matching the specified pod name
539
599
  #
540
600
  # @param [String] pod_name the name of the pod
@@ -562,8 +622,19 @@ module Pod
562
622
  @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
563
623
  end
564
624
 
565
- # Cleans the sources of the Pods if the config instructs to do so.
625
+ # Download the pod unless it is local or has been predownloaded from an
626
+ # external source.
566
627
  #
628
+ # @return [void]
629
+ #
630
+ def download_source_of_pod(pod_name)
631
+ return if sandbox.local?(pod_name) || sandbox.predownloaded?(pod_name)
632
+
633
+ pod_downloader = create_pod_downloader(pod_name)
634
+ pod_downloader.download!
635
+ end
636
+
637
+ # Cleans the sources of the Pods if the config instructs to do so.
567
638
  #
568
639
  def clean_pod_sources
569
640
  return unless installation_options.clean?
@@ -627,6 +698,15 @@ module Pod
627
698
  title_options)
628
699
  end
629
700
 
701
+ # Runs the registered callbacks for the plugins pre integrate hooks.
702
+ #
703
+ def run_plugins_pre_integrate_hooks
704
+ if any_plugin_pre_integrate_hooks?
705
+ context = PreIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
706
+ HooksManager.run(:pre_integrate, context, plugins)
707
+ end
708
+ end
709
+
630
710
  # Runs the registered callbacks for the plugins post install hooks.
631
711
  #
632
712
  def run_plugins_post_install_hooks
@@ -634,7 +714,7 @@ module Pod
634
714
  if any_plugin_post_install_hooks?
635
715
  unlock_pod_sources
636
716
 
637
- context = PostInstallHooksContext.generate(sandbox, pods_project, aggregate_targets)
717
+ context = PostInstallHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
638
718
  HooksManager.run(:post_install, context, plugins)
639
719
  end
640
720
 
@@ -645,11 +725,17 @@ module Pod
645
725
  #
646
726
  def run_plugins_post_integrate_hooks
647
727
  if any_plugin_post_integrate_hooks?
648
- context = PostIntegrateHooksContext.generate(sandbox, pods_project, aggregate_targets)
728
+ context = PostIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
649
729
  HooksManager.run(:post_integrate, context, plugins)
650
730
  end
651
731
  end
652
732
 
733
+ # @return [Boolean] whether there are any plugin pre-integrate hooks to run
734
+ #
735
+ def any_plugin_pre_integrate_hooks?
736
+ HooksManager.hooks_to_run(:pre_integrate, plugins).any?
737
+ end
738
+
653
739
  # @return [Boolean] whether there are any plugin post-install hooks to run
654
740
  #
655
741
  def any_plugin_post_install_hooks?
@@ -747,7 +833,7 @@ module Pod
747
833
  def warn_for_installed_script_phases
748
834
  pods_to_install = sandbox_state.added | sandbox_state.changed
749
835
  pod_targets.group_by(&:pod_name).each do |name, pod_targets|
750
- if pods_to_install.include?(name)
836
+ if pods_to_install.include?(name) && !sandbox.local?(name)
751
837
  script_phase_count = pod_targets.inject(0) { |sum, target| sum + target.script_phases.count }
752
838
  unless script_phase_count.zero?
753
839
  UI.warn "#{name} has added #{script_phase_count} #{'script phase'.pluralize(script_phase_count)}. " \
@@ -766,9 +852,11 @@ module Pod
766
852
  #
767
853
  def warn_for_removing_git_master_specs_repo
768
854
  return unless installation_options.warn_for_unused_master_specs_repo?
769
- podfile_master_source = podfile.sources.find { |source| source == MASTER_SPECS_REPO_GIT_URL }
855
+ plugin_sources = run_source_provider_hooks
856
+ all_sources = podfile.sources + plugin_sources.map(&:url)
857
+ master_source = all_sources.find { |source| source == MASTER_SPECS_REPO_GIT_URL }
770
858
  master_repo = config.sources_manager.all.find { |s| s.url == MASTER_SPECS_REPO_GIT_URL }
771
- if podfile_master_source.nil? && !master_repo.nil?
859
+ if master_source.nil? && !master_repo.nil?
772
860
  UI.warn 'Your project does not explicitly specify the CocoaPods master specs repo. Since CDN is now used as the' \
773
861
  ' default, you may safely remove it from your repos directory via `pod repo remove master`. To suppress this warning' \
774
862
  ' please add `warn_for_unused_master_specs_repo => false` to your Podfile.'
@@ -815,6 +903,7 @@ module Pod
815
903
  installation_cache.update_project_object_version!(cache_analysis_result.project_object_version)
816
904
  installation_cache.update_build_configurations!(cache_analysis_result.build_configurations)
817
905
  installation_cache.update_podfile_plugins!(plugins)
906
+ installation_cache.update_installation_options!(installation_options.to_h)
818
907
  installation_cache.save_as(sandbox.project_installation_cache_path)
819
908
 
820
909
  metadata_cache.update_metadata!(target_installation_results.pod_target_installation_results || {},
@@ -873,6 +962,33 @@ module Pod
873
962
  "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
874
963
  end
875
964
 
965
+ # Runs the pre integrate hooks of the installed specs and of the Podfile.
966
+ #
967
+ # @note Pre integrate hooks run _before_ generation of the Pods project.
968
+ #
969
+ # @return [void]
970
+ #
971
+ def run_podfile_pre_integrate_hooks
972
+ UI.message '- Running pre integrate hooks' do
973
+ executed = run_podfile_pre_integrate_hook
974
+ UI.message '- Podfile' if executed
975
+ end
976
+ end
977
+
978
+ # Runs the pre integrate hook of the Podfile.
979
+ #
980
+ # @raise Raises an informative if the hooks raises.
981
+ #
982
+ # @return [Boolean] Whether the hook was run.
983
+ #
984
+ def run_podfile_pre_integrate_hook
985
+ podfile.pre_integrate!(self)
986
+ rescue => e
987
+ raise Informative, 'An error occurred while processing the pre-integrate ' \
988
+ 'hook of the Podfile.' \
989
+ "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
990
+ end
991
+
876
992
  # Runs the post install hooks of the installed specs and of the Podfile.
877
993
  #
878
994
  # @note Post install hooks run _before_ saving of project, so that they
@@ -43,7 +43,7 @@ module Pod
43
43
  # @param [TargetMetadata] cached_target
44
44
  # the target to search for.
45
45
  #
46
- # @return [Bool]
46
+ # @return [Boolean]
47
47
  #
48
48
  def self.dependency_for_cached_target?(sandbox, target, cached_target)
49
49
  target.dependencies.find do |dep|
@@ -24,7 +24,7 @@ module OpenURI
24
24
  # @param [URI::Generic] uri2
25
25
  # the target uri where to where the redirect points to
26
26
  #
27
- # @return [Bool]
27
+ # @return [Boolean]
28
28
  #
29
29
  def self.redirectable?(uri1, uri2)
30
30
  uri1.scheme.downcase == uri2.scheme.downcase ||
@@ -26,7 +26,7 @@ module Pod
26
26
  #
27
27
  attr_reader :dependencies_group
28
28
 
29
- # @return [Bool] Bool indicating if this project is a pod target subproject.
29
+ # @return [Boolean] Bool indicating if this project is a pod target subproject.
30
30
  # Used by `generate_multiple_pod_projects` installation option.
31
31
  #
32
32
  attr_reader :pod_target_subproject
@@ -39,7 +39,7 @@ module Pod
39
39
  # Initialize a new instance
40
40
  #
41
41
  # @param [Pathname, String] path @see Xcodeproj::Project#path
42
- # @param [Bool] skip_initialization Whether the project should be initialized from scratch.
42
+ # @param [Boolean] skip_initialization Whether the project should be initialized from scratch.
43
43
  # @param [Int] object_version Object version to use for serialization, defaults to Xcode 3.2 compatible.
44
44
  #
45
45
  def initialize(path, skip_initialization = false,
@@ -107,10 +107,10 @@ module Pod
107
107
  # @param [#to_s] path
108
108
  # The path to the root of the Pod.
109
109
  #
110
- # @param [Bool] development
110
+ # @param [Boolean] development
111
111
  # Whether the group should be added to the Development Pods group.
112
112
  #
113
- # @param [Bool] absolute
113
+ # @param [Boolean] absolute
114
114
  # Whether the path of the group should be set as absolute.
115
115
  #
116
116
  # @return [PBXGroup] The new group.
@@ -136,7 +136,7 @@ module Pod
136
136
  # @param [Project] project
137
137
  # The subproject to be added.
138
138
  #
139
- # @param [Bool] development
139
+ # @param [Boolean] development
140
140
  # Whether the project should be added to the Development Pods group.
141
141
  # For projects where `pod_target_subproject` is enabled, all subprojects are added into the Dependencies group.
142
142
  #
@@ -156,7 +156,7 @@ module Pod
156
156
  # @param [TargetMetadata] metadata
157
157
  # The project metadata to be added.
158
158
  #
159
- # @param [Bool] development
159
+ # @param [Boolean] development
160
160
  # Whether the project should be added to the Development Pods group.
161
161
  # For projects where `pod_target_subproject` is enabled, all subprojects are added into the Dependencies group.
162
162
  #
@@ -253,7 +253,7 @@ module Pod
253
253
  # @param [PBXGroup] group
254
254
  # The group for the new file reference.
255
255
  #
256
- # @param [Bool] reflect_file_system_structure
256
+ # @param [Boolean] reflect_file_system_structure
257
257
  # Whether group structure should reflect the file system structure.
258
258
  # If yes, where needed, intermediate groups are created, similar to
259
259
  # how mkdir -p operates.
@@ -430,7 +430,7 @@ module Pod
430
430
  # @param [PBXGroup] group
431
431
  # The parent group used as the base of the relative path.
432
432
  #
433
- # @param [Bool] reflect_file_system_structure
433
+ # @param [Boolean] reflect_file_system_structure
434
434
  # Whether group structure should reflect the file system structure.
435
435
  # If yes, where needed, intermediate groups are created, similar to
436
436
  # how mkdir -p operates.
@@ -12,7 +12,7 @@ module Pod
12
12
  #
13
13
  attr_reader :source
14
14
 
15
- # @return [Bool] whether this resolved specification is used by non-library targets.
15
+ # @return [Boolean] whether this resolved specification is used by non-library targets.
16
16
  #
17
17
  attr_reader :used_by_non_library_targets_only
18
18
  alias used_by_non_library_targets_only? used_by_non_library_targets_only
@@ -34,7 +34,7 @@ module Pod
34
34
  #
35
35
  attr_reader :sources
36
36
 
37
- # @return [Bool] Whether the resolver has sources repositories up-to-date.
37
+ # @return [Boolean] Whether the resolver has sources repositories up-to-date.
38
38
  #
39
39
  attr_reader :specs_updated
40
40
  alias specs_updated? specs_updated
@@ -162,9 +162,8 @@ module Pod
162
162
  Array(@podfile_requirements_by_root_name[dependency.root_name])
163
163
  end
164
164
 
165
- specifications_for_dependency(dependency, additional_requirements)
165
+ specifications_for_dependency(dependency, additional_requirements).freeze
166
166
  end
167
- @search[dependency].dup
168
167
  end
169
168
 
170
169
  # Returns the dependencies of `specification`.
@@ -175,8 +174,9 @@ module Pod
175
174
  # dependencies are being asked for.
176
175
  #
177
176
  def dependencies_for(specification)
177
+ root_name = Specification.root_name(specification.name)
178
178
  specification.all_dependencies.map do |dependency|
179
- if dependency.root_name == Specification.root_name(specification.name)
179
+ if dependency.root_name == root_name
180
180
  dependency.dup.tap { |d| d.specific_version = specification.version }
181
181
  else
182
182
  dependency
@@ -264,7 +264,7 @@ module Pod
264
264
  # @param [{String => Array<Conflict>}] conflicts the current conflicts.
265
265
  #
266
266
  def sort_dependencies(dependencies, activated, conflicts)
267
- dependencies.sort_by do |dependency|
267
+ dependencies.sort_by! do |dependency|
268
268
  name = name_for(dependency)
269
269
  [
270
270
  activated.vertex_named(name).payload ? 0 : 1,
@@ -531,7 +531,7 @@ You have either:#{specs_update_message}
531
531
  #
532
532
  # @param [Specification] spec
533
533
  #
534
- # @return [Bool]
534
+ # @return [Boolean]
535
535
  #
536
536
  def spec_is_platform_compatible?(dependency_graph, dependency, spec)
537
537
  # This is safe since a pod will only be in locked dependencies if we're
@@ -575,7 +575,7 @@ You have either:#{specs_update_message}
575
575
  # Whether the given `edge` should be followed to find dependencies for the
576
576
  # given `target_platform`.
577
577
  #
578
- # @return [Bool]
578
+ # @return [Boolean]
579
579
  #
580
580
  def edge_is_valid_for_target_platform?(edge, target_platform)
581
581
  @edge_validity ||= Hash.new do |hash, edge_and_platform|
@@ -128,6 +128,7 @@ module Pod
128
128
  #
129
129
  def public_headers(include_frameworks = false)
130
130
  public_headers = public_header_files
131
+ project_headers = project_header_files
131
132
  private_headers = private_header_files
132
133
  if public_headers.nil? || public_headers.empty?
133
134
  header_files = headers
@@ -135,7 +136,13 @@ module Pod
135
136
  header_files = public_headers
136
137
  end
137
138
  header_files += vendored_frameworks_headers if include_frameworks
138
- header_files - private_headers
139
+ header_files - project_headers - private_headers
140
+ end
141
+
142
+ # @return [Array<Pathname>] The project headers of the specification.
143
+ #
144
+ def project_headers
145
+ project_header_files
139
146
  end
140
147
 
141
148
  # @return [Array<Pathname>] The private headers of the specification.
@@ -172,6 +179,24 @@ module Pod
172
179
  end
173
180
  end
174
181
 
182
+ # @return [Array<Pathname>] The paths of the static xcframework bundles
183
+ # that come shipped with the Pod.
184
+ #
185
+ def vendored_static_xcframeworks
186
+ vendored_xcframeworks.select do |path|
187
+ Xcode::XCFramework.new(spec.name, path).build_type == BuildType.static_framework
188
+ end
189
+ end
190
+
191
+ # @return [Array<Pathname>] The paths of the dynamic xcframework bundles
192
+ # that come shipped with the Pod.
193
+ #
194
+ def vendored_dynamic_xcframeworks
195
+ vendored_xcframeworks.select do |path|
196
+ Xcode::XCFramework.new(spec.name, path).build_type == BuildType.dynamic_framework
197
+ end
198
+ end
199
+
175
200
  # @return [Array<Pathname>] The paths of the static (fake) framework
176
201
  # bundles that come shipped with the Pod.
177
202
  #
@@ -191,7 +216,7 @@ module Pod
191
216
  # @param [Array<FileAccessor>] file_accessors
192
217
  # The list of all file accessors to compute.
193
218
  #
194
- # @return [Array<String>] The list of all file accessors that a target will integrate into the project.
219
+ # @return [Array<Pathname>] The list of all file accessors that a target will integrate into the project.
195
220
  #
196
221
  def self.all_files(file_accessors)
197
222
  files = [
@@ -203,10 +228,11 @@ module Pod
203
228
  file_accessors.map(&:preserve_paths),
204
229
  file_accessors.map(&:readme),
205
230
  file_accessors.map(&:resources),
231
+ file_accessors.map(&:on_demand_resources_files),
206
232
  file_accessors.map(&:source_files),
207
233
  file_accessors.map(&:module_map),
208
234
  ]
209
- files.flatten.compact.map(&:to_s).uniq
235
+ files.flatten.compact.uniq
210
236
  end
211
237
 
212
238
  # @param [Pathname] framework
@@ -229,14 +255,17 @@ module Pod
229
255
  Pathname.glob(headers_dir + '**/' + GLOB_PATTERNS[:public_header_files])
230
256
  end
231
257
 
232
- # @param [Pathname] framework
258
+ # @param [String] target_name
259
+ # The target name this .xcframework belongs to
260
+ #
261
+ # @param [Pathname] framework_path
233
262
  # The path to the .xcframework
234
263
  #
235
264
  # @return [Array<Pathname>] The paths to all the headers included in the
236
265
  # vendored xcframework
237
266
  #
238
- def self.vendored_xcframework_headers(framework)
239
- xcframework = Xcode::XCFramework.new(framework)
267
+ def self.vendored_xcframework_headers(target_name, framework_path)
268
+ xcframework = Xcode::XCFramework.new(target_name, framework_path)
240
269
  xcframework.slices.flat_map do |slice|
241
270
  vendored_frameworks_headers(slice.path)
242
271
  end
@@ -250,7 +279,7 @@ module Pod
250
279
  self.class.vendored_frameworks_headers(framework)
251
280
  end.uniq
252
281
  paths.concat Array.new(vendored_xcframeworks.flat_map do |framework|
253
- self.class.vendored_xcframework_headers(framework)
282
+ self.class.vendored_xcframework_headers(spec.name, framework)
254
283
  end)
255
284
  paths
256
285
  end
@@ -289,7 +318,7 @@ module Pod
289
318
  # that come shipped with the Pod.
290
319
  #
291
320
  def vendored_static_artifacts
292
- vendored_static_libraries + vendored_static_frameworks
321
+ vendored_static_libraries + vendored_static_frameworks + vendored_static_xcframeworks
293
322
  end
294
323
 
295
324
  # @return [Hash{String => Array<Pathname>}] A hash that describes the
@@ -314,6 +343,26 @@ module Pod
314
343
  resource_bundles.values.flatten
315
344
  end
316
345
 
346
+ # @return [Hash{String => Hash] The expanded paths of the on demand resources specified
347
+ # keyed by their tag including their category.
348
+ #
349
+ def on_demand_resources
350
+ result = {}
351
+ spec_consumer.on_demand_resources.each do |tag_name, file_patterns|
352
+ paths = expanded_paths(file_patterns[:paths],
353
+ :exclude_patterns => spec_consumer.exclude_files,
354
+ :include_dirs => true)
355
+ result[tag_name] = { :paths => paths, :category => file_patterns[:category] }
356
+ end
357
+ result
358
+ end
359
+
360
+ # @return [Array<Pathname>] The expanded paths of the on demand resources.
361
+ #
362
+ def on_demand_resources_files
363
+ on_demand_resources.values.flat_map { |v| v[:paths] }
364
+ end
365
+
317
366
  # @return [Pathname] The of the prefix header file of the specification.
318
367
  #
319
368
  def prefix_header
@@ -322,7 +371,7 @@ module Pod
322
371
  end
323
372
  end
324
373
 
325
- # @return [Pathname] The path of the auto-detected README file.
374
+ # @return [Pathname, nil] The path of the auto-detected README file.
326
375
  #
327
376
  def readme
328
377
  path_list.glob([GLOB_PATTERNS[:readme]]).first
@@ -404,7 +453,14 @@ module Pod
404
453
  paths_for_attribute(:public_header_files)
405
454
  end
406
455
 
407
- # @return [Array<Pathname>] The paths of the user-specified public header
456
+ # @return [Array<Pathname>] The paths of the user-specified project header
457
+ # files.
458
+ #
459
+ def project_header_files
460
+ paths_for_attribute(:project_header_files)
461
+ end
462
+
463
+ # @return [Array<Pathname>] The paths of the user-specified private header
408
464
  # files.
409
465
  #
410
466
  def private_header_files
@@ -457,7 +513,7 @@ module Pod
457
513
  # @option options [Array<String>] :exclude_patterns
458
514
  # The exclude patterns to pass to the PathList.
459
515
  #
460
- # @option options [Bool] :include_dirs
516
+ # @option options [Boolean] :include_dirs
461
517
  # Whether directories should be also included or just plain
462
518
  # files.
463
519
  #
@@ -51,7 +51,9 @@ module Pod
51
51
  #
52
52
  def search_paths(platform, target_name = nil, use_modular_headers = false)
53
53
  key = SEARCH_PATHS_KEY.new(platform.name, target_name, use_modular_headers)
54
- return @search_paths_cache[key] if @search_paths_cache.key?(key)
54
+ if (cached = @search_paths_cache[key])
55
+ return cached
56
+ end
55
57
  search_paths = @search_paths.select do |entry|
56
58
  matches_platform = entry[:platform] == platform.name
57
59
  matches_target = target_name.nil? || (File.basename(entry[:path]) == target_name)