cocoapods 1.9.1 → 1.10.2

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +292 -5
  3. data/README.md +2 -1
  4. data/lib/cocoapods/command/lib/lint.rb +12 -3
  5. data/lib/cocoapods/command/repo/push.rb +1 -1
  6. data/lib/cocoapods/command/repo/update.rb +11 -0
  7. data/lib/cocoapods/command/spec/lint.rb +12 -3
  8. data/lib/cocoapods/command.rb +12 -2
  9. data/lib/cocoapods/config.rb +17 -0
  10. data/lib/cocoapods/downloader/cache.rb +2 -2
  11. data/lib/cocoapods/gem_version.rb +1 -1
  12. data/lib/cocoapods/generator/app_target_helper.rb +10 -2
  13. data/lib/cocoapods/generator/copy_dsyms_script.rb +56 -0
  14. data/lib/cocoapods/generator/copy_resources_script.rb +2 -14
  15. data/lib/cocoapods/generator/copy_xcframework_script.rb +245 -0
  16. data/lib/cocoapods/generator/embed_frameworks_script.rb +125 -212
  17. data/lib/cocoapods/generator/script_phase_constants.rb +99 -0
  18. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +1 -1
  19. data/lib/cocoapods/installer/analyzer.rb +17 -8
  20. data/lib/cocoapods/installer/base_install_hooks_context.rb +135 -0
  21. data/lib/cocoapods/installer/installation_options.rb +5 -0
  22. data/lib/cocoapods/installer/pod_source_installer.rb +2 -1
  23. data/lib/cocoapods/installer/post_install_hooks_context.rb +1 -127
  24. data/lib/cocoapods/installer/post_integrate_hooks_context.rb +9 -0
  25. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +4 -0
  26. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +2 -1
  27. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +132 -111
  28. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +13 -27
  29. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +5 -1
  30. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +2 -1
  31. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +8 -6
  32. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +187 -61
  33. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +61 -30
  34. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +3 -2
  35. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +5 -7
  36. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +45 -6
  37. data/lib/cocoapods/installer/xcode/pods_project_generator_result.rb +19 -0
  38. data/lib/cocoapods/installer/xcode/target_validator.rb +1 -1
  39. data/lib/cocoapods/installer.rb +70 -3
  40. data/lib/cocoapods/sandbox/file_accessor.rb +10 -1
  41. data/lib/cocoapods/sources_manager.rb +2 -1
  42. data/lib/cocoapods/target/aggregate_target.rb +35 -0
  43. data/lib/cocoapods/target/build_settings.rb +94 -18
  44. data/lib/cocoapods/target/pod_target.rb +85 -11
  45. data/lib/cocoapods/target.rb +44 -2
  46. data/lib/cocoapods/user_interface/error_report.rb +1 -1
  47. data/lib/cocoapods/user_interface/inspector_reporter.rb +3 -10
  48. data/lib/cocoapods/validator.rb +38 -12
  49. data/lib/cocoapods/xcode/framework_paths.rb +1 -1
  50. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +91 -4
  51. data/lib/cocoapods/xcode/xcframework.rb +17 -4
  52. data/lib/cocoapods.rb +3 -1
  53. metadata +31 -53
  54. data/lib/cocoapods/generator/prepare_artifacts_script.rb +0 -257
@@ -79,13 +79,14 @@ module Pod
79
79
  #
80
80
  # @param [PBXProject] project The project to configure schemes for.
81
81
  # @param [Array<PodTarget>] pod_targets The pod targets within that project to configure their schemes.
82
+ # @param [PodsProjectGeneratorResult] generator_result the result of the project generation
82
83
  #
83
84
  # @return [void]
84
85
  #
85
- def configure_schemes(project, pod_targets)
86
+ def configure_schemes(project, pod_targets, generator_result)
86
87
  pod_targets.each do |pod_target|
87
88
  share_scheme = pod_target.should_build? && share_scheme_for_development_pod?(pod_target.pod_name) && sandbox.local?(pod_target.pod_name)
88
- configure_schemes_for_pod_target(project, pod_target, share_scheme)
89
+ configure_schemes_for_pod_target(project, pod_target, share_scheme, generator_result)
89
90
  end
90
91
  end
91
92
 
@@ -143,8 +144,10 @@ module Pod
143
144
  pod_installations_to_integrate = pod_target_installation_results.values.select do |pod_target_installation_result|
144
145
  pod_target = pod_target_installation_result.target
145
146
  !pod_target_installation_result.test_native_targets.empty? ||
146
- !pod_target_installation_result.app_native_targets.empty? ||
147
- pod_target.contains_script_phases?
147
+ !pod_target_installation_result.app_native_targets.empty? ||
148
+ pod_target.contains_script_phases? ||
149
+ pod_target.framework_paths.values.flatten.any? { |paths| !paths.dsym_path.nil? } ||
150
+ pod_target.xcframeworks.values.any? { |xcframeworks| !xcframeworks.empty? }
148
151
  end
149
152
  return if pod_installations_to_integrate.empty?
150
153
 
@@ -218,14 +221,35 @@ module Pod
218
221
  end
219
222
  end
220
223
 
221
- def configure_schemes_for_pod_target(project, pod_target, share_scheme)
224
+ # @param [Project] project
225
+ # the project of the pod target
226
+ #
227
+ # @param [Pod::PodTarget] pod_target
228
+ # the pod target for which to configure schemes
229
+ #
230
+ # @param [Boolean] share_scheme
231
+ # whether the created schemes should be shared
232
+ #
233
+ # @param [PodsProjectGeneratorResult] generator_result
234
+ # the project generation result
235
+ #
236
+ def configure_schemes_for_pod_target(project, pod_target, share_scheme, generator_result)
222
237
  # Ignore subspecs because they do not provide a scheme configuration due to the fact that they are always
223
238
  # merged with the root spec scheme.
224
239
  specs = [pod_target.root_spec] + pod_target.test_specs + pod_target.app_specs
240
+ hosted_test_specs_by_host = Hash.new do |hash, key|
241
+ hash[key] = []
242
+ end
243
+ pod_target.test_app_hosts_by_spec.each do |spec, (host_spec, host_target)|
244
+ if host_target == pod_target
245
+ hosted_test_specs_by_host[host_spec] << spec
246
+ end
247
+ end
248
+ is_custom_host = !hosted_test_specs_by_host.empty?
225
249
  specs.each do |spec|
226
250
  scheme_name = spec.spec_type == :library ? pod_target.label : pod_target.non_library_spec_label(spec)
227
251
  scheme_configuration = pod_target.scheme_for_spec(spec)
228
- unless scheme_configuration.empty?
252
+ if !scheme_configuration.empty? || is_custom_host
229
253
  scheme_path = Xcodeproj::XCScheme.user_data_dir(project.path) + "#{scheme_name}.xcscheme"
230
254
  scheme = Xcodeproj::XCScheme.new(scheme_path)
231
255
  command_line_arguments = scheme.launch_action.command_line_arguments
@@ -241,6 +265,21 @@ module Pod
241
265
  if scheme_configuration.key?(:code_coverage)
242
266
  scheme.test_action.code_coverage_enabled = scheme_configuration[:code_coverage]
243
267
  end
268
+
269
+ hosted_test_specs_by_host[spec].each do |hosted_spec|
270
+ # We are an app spec which hosts this test spec.
271
+ # Include the test specs's test bundle within our scheme's test action
272
+ native_target = generator_result.native_target_for_spec(hosted_spec)
273
+ testable = Xcodeproj::XCScheme::TestAction::TestableReference.new(native_target)
274
+ scheme.test_action.add_testable(testable)
275
+ end
276
+
277
+ if spec.test_specification?
278
+ # Default to using the test bundle to expand variables
279
+ native_target_for_expansion = generator_result.native_target_for_spec(spec)
280
+ macro_expansion = Xcodeproj::XCScheme::MacroExpansion.new(native_target_for_expansion)
281
+ scheme.launch_action.add_macro_expansion(macro_expansion)
282
+ end
244
283
  scheme.save!
245
284
  end
246
285
  Xcodeproj::XCScheme.share_scheme(project.path, scheme_name) if share_scheme
@@ -28,6 +28,25 @@ module Pod
28
28
  @projects_by_pod_targets = projects_by_pod_targets
29
29
  @target_installation_results = target_installation_results
30
30
  end
31
+
32
+ # @param [Pod::Specification] spec
33
+ # A spec which was included in the generated project
34
+ #
35
+ # @return [Xcodeproj::PBXNativeTarget] the native target for the spec
36
+ #
37
+ def native_target_for_spec(spec)
38
+ installation_results_by_spec[spec.root].native_target_for_spec(spec)
39
+ end
40
+
41
+ private
42
+
43
+ def installation_results_by_spec
44
+ @target_installation_results_by_spec ||= begin
45
+ target_installation_results.pod_target_installation_results.values.each_with_object({}) do |installation_results, hash|
46
+ hash[installation_results.target.root_spec] = installation_results
47
+ end
48
+ end
49
+ end
31
50
  end
32
51
  end
33
52
  end
@@ -115,7 +115,7 @@ module Pod
115
115
  target_errors = swift_target_definitions.map(&error_message_for_target_definition).to_sentence
116
116
  "- `#{swift_pod_target.name}` is integrated by multiple targets that use a different Swift version: #{target_errors}."
117
117
  end
118
- elsif swift_pod_target.swift_version.empty?
118
+ elsif !swift_pod_target.swift_version.nil? && swift_pod_target.swift_version.empty?
119
119
  "- `#{swift_pod_target.name}` does not specify a Swift version (#{swift_pod_target.spec_swift_versions.map { |v| "`#{v}`" }.to_sentence}) " \
120
120
  "that is satisfied by any of targets (#{swift_pod_target.target_definitions.map { |td| "`#{td.name}`" }.to_sentence}) integrating it."
121
121
  end
@@ -34,6 +34,8 @@ module Pod
34
34
  autoload :InstallationOptions, 'cocoapods/installer/installation_options'
35
35
  autoload :PostInstallHooksContext, 'cocoapods/installer/post_install_hooks_context'
36
36
  autoload :PreInstallHooksContext, 'cocoapods/installer/pre_install_hooks_context'
37
+ autoload :BaseInstallHooksContext, 'cocoapods/installer/base_install_hooks_context'
38
+ autoload :PostIntegrateHooksContext, 'cocoapods/installer/post_integrate_hooks_context'
37
39
  autoload :SourceProviderHooksContext, 'cocoapods/installer/source_provider_hooks_context'
38
40
  autoload :PodfileValidator, 'cocoapods/installer/podfile_validator'
39
41
  autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
@@ -47,6 +49,8 @@ module Pod
47
49
 
48
50
  include Config::Mixin
49
51
 
52
+ MASTER_SPECS_REPO_GIT_URL = 'https://github.com/CocoaPods/Specs.git'.freeze
53
+
50
54
  # @return [Sandbox] The sandbox where the Pods should be installed.
51
55
  #
52
56
  attr_reader :sandbox
@@ -331,7 +335,7 @@ module Pod
331
335
  all_projects_by_pod_targets.merge!(pods_project_by_targets) if pods_project_by_targets
332
336
  all_projects_by_pod_targets.merge!(projects_by_pod_targets) if projects_by_pod_targets
333
337
  all_projects_by_pod_targets.each do |project, pod_targets|
334
- generator.configure_schemes(project, pod_targets)
338
+ generator.configure_schemes(project, pod_targets, pod_project_generation_result)
335
339
  end
336
340
  end
337
341
  end
@@ -494,7 +498,7 @@ module Pod
494
498
  previous_version = sandbox.manifest.version(spec.name)
495
499
  has_changed_version = current_version != previous_version
496
500
  current_repo = analysis_result.specs_by_source.detect { |key, values| break key if values.map(&:name).include?(spec.name) }
497
- current_repo &&= current_repo.url || current_repo.name
501
+ current_repo &&= (Pod::TrunkSource::TRUNK_REPO_NAME if current_repo.name == Pod::TrunkSource::TRUNK_REPO_NAME) || current_repo.url || current_repo.name
498
502
  previous_spec_repo = sandbox.manifest.spec_repo(spec.name)
499
503
  has_changed_repo = !previous_spec_repo.nil? && current_repo && !current_repo.casecmp(previous_spec_repo).zero?
500
504
  title = "Installing #{spec.name} #{spec.version}"
@@ -563,6 +567,7 @@ module Pod
563
567
  #
564
568
  def clean_pod_sources
565
569
  return unless installation_options.clean?
570
+ return if installed_specs.empty?
566
571
  pod_installers.each(&:clean!)
567
572
  end
568
573
 
@@ -607,6 +612,7 @@ module Pod
607
612
  run_plugins_post_install_hooks
608
613
  warn_for_deprecations
609
614
  warn_for_installed_script_phases
615
+ warn_for_removing_git_master_specs_repo
610
616
  print_post_install_message
611
617
  end
612
618
 
@@ -635,12 +641,27 @@ module Pod
635
641
  lock_pod_sources
636
642
  end
637
643
 
644
+ # Runs the registered callbacks for the plugins post integrate hooks.
645
+ #
646
+ def run_plugins_post_integrate_hooks
647
+ if any_plugin_post_integrate_hooks?
648
+ context = PostIntegrateHooksContext.generate(sandbox, pods_project, aggregate_targets)
649
+ HooksManager.run(:post_integrate, context, plugins)
650
+ end
651
+ end
652
+
638
653
  # @return [Boolean] whether there are any plugin post-install hooks to run
639
654
  #
640
655
  def any_plugin_post_install_hooks?
641
656
  HooksManager.hooks_to_run(:post_install, plugins).any?
642
657
  end
643
658
 
659
+ # @return [Boolean] whether there are any plugin post-integrate hooks to run
660
+ #
661
+ def any_plugin_post_integrate_hooks?
662
+ HooksManager.hooks_to_run(:post_integrate, plugins).any?
663
+ end
664
+
644
665
  # Runs the registered callbacks for the source provider plugin hooks.
645
666
  #
646
667
  # @return [Array<Pod::Source>] the plugin sources
@@ -686,7 +707,7 @@ module Pod
686
707
  end
687
708
  end
688
709
 
689
- DEFAULT_PLUGINS = { 'cocoapods-stats' => {} }
710
+ DEFAULT_PLUGINS = {}
690
711
 
691
712
  # Returns the plugins that should be run, as indicated by the default
692
713
  # plugins and the podfile's plugins
@@ -736,6 +757,24 @@ module Pod
736
757
  end
737
758
  end
738
759
 
760
+ # Prints a warning if the project is not explicitly using the git based master specs repo.
761
+ #
762
+ # Helps users to delete the git based master specs repo from the repos directory which reduces `--repo-update`
763
+ # speed and hopefully reduces Github workload.
764
+ #
765
+ # @return [void]
766
+ #
767
+ def warn_for_removing_git_master_specs_repo
768
+ return unless installation_options.warn_for_unused_master_specs_repo?
769
+ podfile_master_source = podfile.sources.find { |source| source == MASTER_SPECS_REPO_GIT_URL }
770
+ master_repo = config.sources_manager.all.find { |s| s.url == MASTER_SPECS_REPO_GIT_URL }
771
+ if podfile_master_source.nil? && !master_repo.nil?
772
+ UI.warn 'Your project does not explicitly specify the CocoaPods master specs repo. Since CDN is now used as the' \
773
+ ' default, you may safely remove it from your repos directory via `pod repo remove master`. To suppress this warning' \
774
+ ' please add `warn_for_unused_master_specs_repo => false` to your Podfile.'
775
+ end
776
+ end
777
+
739
778
  # @return [Lockfile] The lockfile to write to disk.
740
779
  #
741
780
  def generate_lockfile
@@ -799,6 +838,7 @@ module Pod
799
838
  integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, aggregate_targets, generated_aggregate_targets,
800
839
  :use_input_output_paths => !installation_options.disable_input_output_paths?)
801
840
  integrator.integrate!
841
+ run_podfile_post_integrate_hooks
802
842
  end
803
843
  end
804
844
 
@@ -861,6 +901,33 @@ module Pod
861
901
  "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
862
902
  end
863
903
 
904
+ # Runs the post integrate hooks of the installed specs and of the Podfile.
905
+ #
906
+ # @note Post integrate hooks run _after_ saving of project, so that they
907
+ # can alter it after it is written to the disk.
908
+ #
909
+ # @return [void]
910
+ #
911
+ def run_podfile_post_integrate_hooks
912
+ UI.message '- Running post integrate hooks' do
913
+ executed = run_podfile_post_integrate_hook
914
+ UI.message '- Podfile' if executed
915
+ end
916
+ end
917
+
918
+ # Runs the post integrate hook of the Podfile.
919
+ #
920
+ # @raise Raises an informative if the hooks raises.
921
+ #
922
+ # @return [Boolean] Whether the hook was run.
923
+ #
924
+ def run_podfile_post_integrate_hook
925
+ podfile.post_integrate!(self)
926
+ rescue => e
927
+ raise Informative, 'An error occurred while processing the post-integrate ' \
928
+ 'hook of the Podfile.' \
929
+ "\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
930
+ end
864
931
  #-------------------------------------------------------------------------#
865
932
 
866
933
  public
@@ -172,6 +172,15 @@ module Pod
172
172
  end
173
173
  end
174
174
 
175
+ # @return [Array<Pathname>] The paths of the dynamic xcframework bundles
176
+ # that come shipped with the Pod.
177
+ #
178
+ def vendored_static_xcframeworks
179
+ vendored_xcframeworks.select do |path|
180
+ Xcode::XCFramework.new(path).build_type == BuildType.static_framework
181
+ end
182
+ end
183
+
175
184
  # @return [Array<Pathname>] The paths of the static (fake) framework
176
185
  # bundles that come shipped with the Pod.
177
186
  #
@@ -289,7 +298,7 @@ module Pod
289
298
  # that come shipped with the Pod.
290
299
  #
291
300
  def vendored_static_artifacts
292
- vendored_static_libraries + vendored_static_frameworks
301
+ vendored_static_libraries + vendored_static_frameworks + vendored_static_xcframeworks
293
302
  end
294
303
 
295
304
  # @return [Hash{String => Array<Pathname>}] A hash that describes the
@@ -2,7 +2,6 @@ require 'cocoapods-core/source'
2
2
  require 'netrc'
3
3
  require 'set'
4
4
  require 'rest'
5
- require 'typhoeus'
6
5
  require 'yaml'
7
6
 
8
7
  module Pod
@@ -72,6 +71,8 @@ module Pod
72
71
  #
73
72
  def cdn_url?(url)
74
73
  if url =~ %r{^https?:\/\/}
74
+ require 'typhoeus'
75
+
75
76
  response = Typhoeus.get(url + '/CocoaPods-version.yml', :netrc_file => Netrc.default_path, :netrc => :optional)
76
77
  response.code == 200 && begin
77
78
  response_hash = YAML.load(response.body) # rubocop:disable Security/YAMLLoad
@@ -98,6 +98,7 @@ module Pod
98
98
  target_definition, client_root, user_project, user_target_uuids, merged).tap do |aggregate_target|
99
99
  aggregate_target.search_paths_aggregate_targets.concat(search_paths_aggregate_targets).freeze
100
100
  aggregate_target.mark_application_extension_api_only if application_extension_api_only
101
+ aggregate_target.mark_build_library_for_distribution if build_library_for_distribution
101
102
  end
102
103
  end
103
104
 
@@ -284,6 +285,20 @@ module Pod
284
285
  resources_by_config[config] = targets.flat_map do |pod_target|
285
286
  library_specs = pod_target.library_specs.map(&:name)
286
287
  resource_paths = pod_target.resource_paths.values_at(*library_specs).flatten
288
+
289
+ if pod_target.build_as_static_framework?
290
+ built_product_dir = Pathname.new(pod_target.build_product_path('${BUILT_PRODUCTS_DIR}'))
291
+ resource_paths = resource_paths.map do |resource_path|
292
+ extname = File.extname(resource_path)
293
+ if self.class.resource_extension_compilable?(extname)
294
+ output_extname = self.class.output_extension_for_resource(extname)
295
+ built_product_dir.join(File.basename(resource_path)).sub_ext(output_extname).to_s
296
+ else
297
+ resource_path
298
+ end
299
+ end
300
+ end
301
+
287
302
  resource_paths << bridge_support_file
288
303
  resource_paths.compact.uniq
289
304
  end
@@ -359,6 +374,10 @@ module Pod
359
374
  #
360
375
  # @return [Pathname] The absolute path of the prepare artifacts script input file list.
361
376
  #
377
+ # @deprecated
378
+ #
379
+ # @todo Remove in 2.0
380
+ #
362
381
  def prepare_artifacts_script_input_files_path(configuration)
363
382
  support_files_dir + "#{label}-artifacts-#{configuration}-input-files.xcfilelist"
364
383
  end
@@ -367,6 +386,10 @@ module Pod
367
386
  #
368
387
  # @return [Pathname] The absolute path of the prepare artifacts script output file list.
369
388
  #
389
+ # @deprecated
390
+ #
391
+ # @todo Remove in 2.0
392
+ #
370
393
  def prepare_artifacts_script_output_files_path(configuration)
371
394
  support_files_dir + "#{label}-artifacts-#{configuration}-output-files.xcfilelist"
372
395
  end
@@ -453,6 +476,10 @@ module Pod
453
476
  # @return [String] The path of the prepare artifacts script relative to the
454
477
  # root of the Pods project.
455
478
  #
479
+ # @deprecated
480
+ #
481
+ # @todo Remove in 2.0
482
+ #
456
483
  def prepare_artifacts_script_relative_path
457
484
  "${PODS_ROOT}/#{relative_to_pods_root(prepare_artifacts_script_path)}"
458
485
  end
@@ -460,6 +487,10 @@ module Pod
460
487
  # @return [String] The path of the prepare artifacts script input file list
461
488
  # relative to the root of the Pods project.
462
489
  #
490
+ # @deprecated
491
+ #
492
+ # @todo Remove in 2.0
493
+ #
463
494
  def prepare_artifacts_script_input_files_relative_path
464
495
  "${PODS_ROOT}/#{relative_to_pods_root(prepare_artifacts_script_input_files_path('${CONFIGURATION}'))}"
465
496
  end
@@ -467,6 +498,10 @@ module Pod
467
498
  # @return [String] The path of the prepare artifacts script output file list
468
499
  # relative to the root of the Pods project.
469
500
  #
501
+ # @deprecated
502
+ #
503
+ # @todo Remove in 2.0
504
+ #
470
505
  def prepare_artifacts_script_output_files_relative_path
471
506
  "${PODS_ROOT}/#{relative_to_pods_root(prepare_artifacts_script_output_files_path('${CONFIGURATION}'))}"
472
507
  end
@@ -43,7 +43,13 @@ module Pod
43
43
  # @return [String]
44
44
  # The variable for the configuration build directory used when building pod targets.
45
45
  #
46
- CONFIGURATION_BUILD_DIR_VARIABLE = '${PODS_CONFIGURATION_BUILD_DIR}'.freeze
46
+ CONFIGURATION_BUILD_DIR_VARIABLE = '${PODS_CONFIGURATION_BUILD_DIR}'
47
+
48
+ # @return [String]
49
+ # The variable for the configuration intermediate frameworks directory used for building pod targets
50
+ # that contain vendored xcframeworks.
51
+ #
52
+ XCFRAMEWORKS_BUILD_DIR_VARIABLE = '${PODS_XCFRAMEWORKS_BUILD_DIR}'
47
53
 
48
54
  #-------------------------------------------------------------------------#
49
55
 
@@ -95,7 +101,7 @@ module Pod
95
101
  from_search_paths_aggregate_targets: false, from_pod_targets_to_link: false,
96
102
  &implementation)
97
103
 
98
- memoized_key = "#{self}##{method_name}".freeze
104
+ memoized_key = "#{self}##{method_name}"
99
105
 
100
106
  (@build_settings_names ||= Set.new) << method_name.to_s.upcase if build_setting
101
107
 
@@ -134,6 +140,14 @@ module Pod
134
140
  end
135
141
  private_class_method :define_build_settings_method
136
142
 
143
+ # @param [XCFramework] xcframework the xcframework thats slice will be copied to the intermediates dir
144
+ #
145
+ # @return [String] the path to the directory containing the xcframework slice
146
+ #
147
+ def self.xcframework_intermediate_dir(xcframework)
148
+ "#{XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{xcframework.name}"
149
+ end
150
+
137
151
  class << self
138
152
  #-------------------------------------------------------------------------#
139
153
 
@@ -204,6 +218,10 @@ module Pod
204
218
  '${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)'
205
219
  end
206
220
 
221
+ define_build_settings_method :pods_xcframeworks_build_dir, :build_setting => true do
222
+ '$(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates'
223
+ end
224
+
207
225
  # @return [String]
208
226
  define_build_settings_method :use_recursive_script_inputs_in_script_phases, :build_setting => true do
209
227
  'YES'
@@ -314,6 +332,13 @@ module Pod
314
332
  false
315
333
  end
316
334
 
335
+ # Xcode 12 turns on this warning by default which is problematic for CocoaPods-generated
336
+ # imports which use double-quoted paths.
337
+ # @return [Boolean]
338
+ define_build_settings_method :clang_warn_quoted_include_in_framework_header, :build_setting => true do
339
+ 'NO'
340
+ end
341
+
317
342
  # @return [Array<String>]
318
343
  # the `LD_RUNPATH_SEARCH_PATHS` needed for dynamically linking the {#target}
319
344
  #
@@ -475,6 +500,14 @@ module Pod
475
500
  pod_targets - subset_targets
476
501
  end
477
502
 
503
+ # @param [Pathname,String] path the path to the xcframework bundle
504
+ #
505
+ # @return [Xcode::XCFramework] the xcframework at the given path
506
+ #
507
+ def load_xcframework(path)
508
+ Xcode::XCFramework.new(path)
509
+ end
510
+
478
511
  # A subclass that generates build settings for a {PodTarget}
479
512
  class PodTargetSettings < BuildSettings
480
513
  #-------------------------------------------------------------------------#
@@ -576,10 +609,13 @@ module Pod
576
609
  frameworks.concat consumer_frameworks
577
610
  if library_xcconfig?
578
611
  # We know that this library target is being built dynamically based
579
- # on the guard above, so include any vendored static frameworks.
612
+ # on the guard above, so include any vendored static frameworks and vendored xcframeworks.
580
613
  if target.should_build?
581
614
  frameworks.concat vendored_static_frameworks.map { |l| File.basename(l, '.framework') }
582
- frameworks.concat vendored_xcframeworks.map(&:name)
615
+ frameworks.concat vendored_xcframeworks.
616
+ select { |xcf| xcf.build_type.static_framework? }.
617
+ map(&:name).
618
+ uniq
583
619
  end
584
620
  # Also include any vendored dynamic frameworks of dependencies.
585
621
  frameworks.concat dependent_targets.reject(&:should_build?).flat_map { |pt| pt.build_settings[@configuration].dynamic_frameworks_to_import }
@@ -596,7 +632,7 @@ module Pod
596
632
  static_frameworks_to_import.concat vendored_static_frameworks.map { |f| File.basename(f, '.framework') } unless target.should_build? && target.build_as_dynamic?
597
633
  unless target.should_build? && target.build_as_dynamic?
598
634
  static_frameworks_to_import.concat vendored_xcframeworks.
599
- select(&:includes_static_slices?).
635
+ select { |xcf| xcf.build_type.static_framework? }.
600
636
  map(&:name).
601
637
  uniq
602
638
  end
@@ -608,7 +644,7 @@ module Pod
608
644
  define_build_settings_method :dynamic_frameworks_to_import, :memoized => true do
609
645
  dynamic_frameworks_to_import = vendored_dynamic_frameworks.map { |f| File.basename(f, '.framework') }
610
646
  dynamic_frameworks_to_import.concat vendored_xcframeworks.
611
- select(&:includes_dynamic_slices?).
647
+ select { |xcf| xcf.build_type.dynamic_framework? }.
612
648
  map(&:name).
613
649
  uniq
614
650
  dynamic_frameworks_to_import << target.product_basename if target.should_build? && target.build_as_dynamic_framework?
@@ -656,12 +692,11 @@ module Pod
656
692
  search_paths.concat file_accessors.
657
693
  flat_map(&:vendored_frameworks).
658
694
  map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
659
- # Include each slice in the framework search paths.
660
- # Xcode will not search inside an .xcframework for headers within each slice
661
- search_paths.concat vendored_xcframeworks.
662
- flat_map(&:slices).
663
- select { |slice| slice.platform.symbolic_name == target.platform.symbolic_name }.
664
- flat_map { |slice| File.join '${PODS_ROOT}', slice.path.dirname.relative_path_from(target.sandbox.root) }
695
+ xcframework_intermediates = vendored_xcframeworks.
696
+ select { |xcf| xcf.build_type.framework? }.
697
+ map { |xcf| BuildSettings.xcframework_intermediate_dir(xcf) }.
698
+ uniq
699
+ search_paths.concat xcframework_intermediates
665
700
  search_paths
666
701
  end
667
702
 
@@ -686,7 +721,7 @@ module Pod
686
721
 
687
722
  # @return [Array<Xcode::XCFramework>]
688
723
  define_build_settings_method :vendored_xcframeworks, :memoized => true do
689
- file_accessors.flat_map(&:vendored_xcframeworks).map { |path| Xcode::XCFramework.new(path) }
724
+ file_accessors.flat_map(&:vendored_xcframeworks).map { |path| load_xcframework(path) }
690
725
  end
691
726
 
692
727
  # @return [Array<String>]
@@ -707,7 +742,7 @@ module Pod
707
742
  # @return [Array<String>]
708
743
  #
709
744
  def linker_names_from_libraries(libraries)
710
- libraries.map { |l| File.basename(l, l.extname).sub(/\Alib/, '') }
745
+ libraries.map { |l| File.basename(l, File.extname(l)).sub(/\Alib/, '') }
711
746
  end
712
747
 
713
748
  # @return [Array<String>]
@@ -718,6 +753,11 @@ module Pod
718
753
  if non_library_xcconfig? || target.build_as_dynamic?
719
754
  libraries.concat linker_names_from_libraries(vendored_static_libraries)
720
755
  libraries.concat libraries_to_import
756
+ xcframework_libraries = vendored_xcframeworks.
757
+ select { |xcf| xcf.build_type.static_library? }.
758
+ flat_map { |xcf| linker_names_from_libraries([xcf.slices.first.binary_path]) }.
759
+ uniq
760
+ libraries.concat xcframework_libraries
721
761
  end
722
762
  if non_library_xcconfig?
723
763
  libraries.concat dependent_targets.flat_map { |pt| pt.build_settings[@configuration].dynamic_libraries_to_import }
@@ -729,7 +769,14 @@ module Pod
729
769
  # @return [Array<String>]
730
770
  define_build_settings_method :static_libraries_to_import, :memoized => true do
731
771
  static_libraries_to_import = []
732
- static_libraries_to_import.concat linker_names_from_libraries(vendored_static_libraries) unless target.should_build? && target.build_as_dynamic?
772
+ unless target.should_build? && target.build_as_dynamic?
773
+ static_libraries_to_import.concat linker_names_from_libraries(vendored_static_libraries)
774
+ xcframework_libraries = vendored_xcframeworks.
775
+ select { |xcf| xcf.build_type.static_library? }.
776
+ flat_map { |xcf| linker_names_from_libraries([xcf.slices.first.binary_path]) }.
777
+ uniq
778
+ static_libraries_to_import.concat linker_names_from_libraries(xcframework_libraries)
779
+ end
733
780
  static_libraries_to_import << target.product_basename if target.should_build? && target.build_as_static_library?
734
781
  static_libraries_to_import
735
782
  end
@@ -775,12 +822,20 @@ module Pod
775
822
 
776
823
  # @return [Array<String>]
777
824
  define_build_settings_method :vendored_static_library_search_paths, :memoized => true do
778
- vendored_static_libraries.map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
825
+ paths = vendored_static_libraries.map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
826
+ paths.concat vendored_xcframeworks.
827
+ select { |xcf| xcf.build_type.static_library? }.
828
+ map { |xcf| BuildSettings.xcframework_intermediate_dir(xcf) }
829
+ paths
779
830
  end
780
831
 
781
832
  # @return [Array<String>]
782
833
  define_build_settings_method :vendored_dynamic_library_search_paths, :memoized => true do
783
- vendored_dynamic_libraries.map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
834
+ paths = vendored_dynamic_libraries.map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
835
+ paths.concat vendored_xcframeworks.
836
+ select { |xcf| xcf.build_type.dynamic_library? }.
837
+ map { |xcf| BuildSettings.xcframework_intermediate_dir(xcf) }
838
+ paths
784
839
  end
785
840
 
786
841
  # @return [Array<String>]
@@ -816,7 +871,16 @@ module Pod
816
871
 
817
872
  # @return [Array<String>]
818
873
  define_build_settings_method :header_search_paths, :build_setting => true, :memoized => true, :sorted => true do
819
- target.header_search_paths(:include_dependent_targets_for_test_spec => test_xcconfig? && non_library_spec, :include_dependent_targets_for_app_spec => app_xcconfig? && non_library_spec, :configuration => @configuration)
874
+ paths = target.header_search_paths(:include_dependent_targets_for_test_spec => test_xcconfig? && non_library_spec, :include_dependent_targets_for_app_spec => app_xcconfig? && non_library_spec, :configuration => @configuration)
875
+
876
+ dependent_vendored_xcframeworks = []
877
+ dependent_vendored_xcframeworks.concat vendored_xcframeworks
878
+ dependent_vendored_xcframeworks.concat dependent_targets.flat_map { |pt| pt.build_settings[@configuration].vendored_xcframeworks }
879
+ paths.concat dependent_vendored_xcframeworks.
880
+ select { |xcf| xcf.build_type.static_library? }.
881
+ map { |xcf| "#{BuildSettings.xcframework_intermediate_dir(xcf)}/Headers" }.
882
+ compact
883
+ paths
820
884
  end
821
885
 
822
886
  # @return [Array<String>]
@@ -912,6 +976,11 @@ module Pod
912
976
  target.application_extension_api_only ? 'YES' : nil
913
977
  end
914
978
 
979
+ # @return [String]
980
+ define_build_settings_method :build_library_for_distribution, :build_setting => true, :memoized => true do
981
+ target.build_library_for_distribution ? 'YES' : nil
982
+ end
983
+
915
984
  #-------------------------------------------------------------------------#
916
985
 
917
986
  # @!group Target Properties
@@ -1098,6 +1167,13 @@ module Pod
1098
1167
  select { |pt| pt.build_as_framework? && pt.should_build? }.
1099
1168
  map { |pt| pt.build_settings[@configuration].framework_header_search_path }
1100
1169
 
1170
+ xcframework_library_headers = pod_targets.flat_map { |pt| pt.build_settings[@configuration].vendored_xcframeworks }.
1171
+ select { |xcf| xcf.build_type.static_library? }.
1172
+ map { |xcf| "#{BuildSettings.xcframework_intermediate_dir(xcf)}/Headers" }.
1173
+ compact
1174
+
1175
+ paths.concat xcframework_library_headers
1176
+
1101
1177
  paths.concat target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).header_search_paths }
1102
1178
 
1103
1179
  paths