cocoapods 1.9.0.beta.3 → 1.10.0.beta.1

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +222 -0
  3. data/README.md +2 -1
  4. data/lib/cocoapods.rb +3 -1
  5. data/lib/cocoapods/command.rb +12 -2
  6. data/lib/cocoapods/command/lib/lint.rb +12 -3
  7. data/lib/cocoapods/command/repo/push.rb +1 -1
  8. data/lib/cocoapods/command/repo/update.rb +11 -0
  9. data/lib/cocoapods/command/spec/lint.rb +12 -3
  10. data/lib/cocoapods/config.rb +17 -0
  11. data/lib/cocoapods/downloader/cache.rb +2 -2
  12. data/lib/cocoapods/gem_version.rb +1 -1
  13. data/lib/cocoapods/generator/app_target_helper.rb +10 -2
  14. data/lib/cocoapods/generator/copy_dsyms_script.rb +56 -0
  15. data/lib/cocoapods/generator/copy_resources_script.rb +2 -14
  16. data/lib/cocoapods/generator/copy_xcframework_script.rb +245 -0
  17. data/lib/cocoapods/generator/embed_frameworks_script.rb +137 -206
  18. data/lib/cocoapods/generator/script_phase_constants.rb +99 -0
  19. data/lib/cocoapods/installer.rb +70 -3
  20. data/lib/cocoapods/installer/analyzer.rb +17 -8
  21. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +1 -1
  22. data/lib/cocoapods/installer/base_install_hooks_context.rb +135 -0
  23. data/lib/cocoapods/installer/installation_options.rb +5 -0
  24. data/lib/cocoapods/installer/pod_source_installer.rb +2 -1
  25. data/lib/cocoapods/installer/post_install_hooks_context.rb +1 -127
  26. data/lib/cocoapods/installer/post_integrate_hooks_context.rb +9 -0
  27. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +2 -1
  28. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +132 -111
  29. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +45 -6
  30. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +13 -27
  31. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +2 -1
  32. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +4 -4
  33. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +175 -58
  34. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +61 -30
  35. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +3 -2
  36. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +5 -7
  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/sources_manager.rb +2 -1
  40. data/lib/cocoapods/target.rb +44 -2
  41. data/lib/cocoapods/target/aggregate_target.rb +35 -0
  42. data/lib/cocoapods/target/build_settings.rb +86 -19
  43. data/lib/cocoapods/target/pod_target.rb +85 -11
  44. data/lib/cocoapods/user_interface/error_report.rb +1 -1
  45. data/lib/cocoapods/user_interface/inspector_reporter.rb +3 -10
  46. data/lib/cocoapods/validator.rb +32 -8
  47. data/lib/cocoapods/xcode/framework_paths.rb +1 -1
  48. data/lib/cocoapods/xcode/xcframework.rb +17 -4
  49. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +81 -3
  50. metadata +30 -38
  51. data/lib/cocoapods/generator/prepare_artifacts_script.rb +0 -244
@@ -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
@@ -6,6 +6,10 @@ module Pod
6
6
  # project and the relative support files.
7
7
  #
8
8
  class AggregateTargetInstaller < TargetInstaller
9
+ # @return [AggregateTarget] @see TargetInstaller#target
10
+ #
11
+ attr_reader :target
12
+
9
13
  # Creates the target in the Pods project and the relative support files.
10
14
  #
11
15
  # @return [TargetInstallationResult] the result of the installation of this target.
@@ -30,8 +34,7 @@ module Pod
30
34
  # cause an App Store rejection because frameworks cannot be
31
35
  # embedded in embedded targets.
32
36
  #
33
- create_embed_frameworks_script if (target.includes_frameworks? || target.includes_xcframeworks?) && !target.requires_host_target?
34
- create_prepare_artifacts_script if target.includes_xcframeworks? && !target.requires_host_target?
37
+ create_embed_frameworks_script if embed_frameworks_script_required?
35
38
  create_bridge_support_file(native_target)
36
39
  create_copy_resources_script if target.includes_resources?
37
40
  create_acknowledgements
@@ -76,6 +79,13 @@ module Pod
76
79
  super.merge(settings)
77
80
  end
78
81
 
82
+ # @return [Boolean] whether this target requires an `Embed Frameworks` script phase
83
+ #
84
+ def embed_frameworks_script_required?
85
+ includes_dynamic_xcframeworks = target.xcframeworks_by_config.values.flatten.map(&:build_type).any?(&:dynamic_framework?)
86
+ (target.includes_frameworks? || includes_dynamic_xcframeworks) && !target.requires_host_target?
87
+ end
88
+
79
89
  # Creates the group that holds the references to the support files
80
90
  # generated by this installer.
81
91
  #
@@ -154,33 +164,9 @@ module Pod
154
164
  #
155
165
  def create_embed_frameworks_script
156
166
  path = target.embed_frameworks_script_path
157
- generator = Generator::EmbedFrameworksScript.new(target.framework_paths_by_config)
158
- update_changed_file(generator, path)
159
- add_file_to_support_group(path)
160
- end
161
-
162
- # Creates a script that prepares artifacts for embedding into a host target.
163
- #
164
- # @note We can't use Xcode default link libraries phase, because
165
- # we need to ensure that we only copy the frameworks which are
166
- # relevant for the current build configuration.
167
- #
168
- # @return [void]
169
- #
170
- def create_prepare_artifacts_script
171
- path = target.prepare_artifacts_script_path
172
- generator = Generator::PrepareArtifactsScript.new(target.xcframeworks_by_config, sandbox.root, target.platform)
167
+ generator = Generator::EmbedFrameworksScript.new(target.framework_paths_by_config, target.xcframeworks_by_config)
173
168
  update_changed_file(generator, path)
174
169
  add_file_to_support_group(path)
175
-
176
- target.user_build_configurations.each_key do |config|
177
- if (input_file_list = target.prepare_artifacts_script_input_files_path(config))
178
- add_file_to_support_group(input_file_list)
179
- end
180
- if (output_file_list = target.prepare_artifacts_script_output_files_path(config))
181
- add_file_to_support_group(output_file_list)
182
- end
183
- end
184
170
  end
185
171
 
186
172
  # Generates the acknowledgement files (markdown and plist) for the target.
@@ -218,7 +218,8 @@ module Pod
218
218
  pod_name = file_accessor.spec.name
219
219
  preserve_pod_file_structure_flag = (sandbox.local?(pod_name) || preserve_pod_file_structure) && reflect_file_system_structure
220
220
  base_path = preserve_pod_file_structure_flag ? common_path(paths) : nil
221
- group = pods_project.group_for_spec(pod_name, group_key)
221
+ actual_group_key = preserve_pod_file_structure_flag ? nil : group_key
222
+ group = pods_project.group_for_spec(pod_name, actual_group_key)
222
223
  paths.each do |path|
223
224
  pods_project.add_file_reference(path, group, preserve_pod_file_structure_flag, base_path)
224
225
  end
@@ -53,8 +53,8 @@ module Pod
53
53
 
54
54
  # Wire up app native targets.
55
55
  unless pod_target_installation_result.app_native_targets.empty?
56
- wire_app_native_targets(pod_target, native_target, pod_target_installation_result,
57
- pod_target_installation_results, project, frameworks_group, metadata_cache)
56
+ wire_app_native_targets(pod_target, pod_target_installation_result, pod_target_installation_results,
57
+ project, frameworks_group, metadata_cache)
58
58
  end
59
59
  end
60
60
  end
@@ -160,7 +160,7 @@ module Pod
160
160
  end
161
161
  end
162
162
 
163
- def wire_app_native_targets(pod_target, native_target, installation_result, pod_target_installation_results, project, frameworks_group, metadata_cache)
163
+ def wire_app_native_targets(pod_target, installation_result, pod_target_installation_results, project, frameworks_group, metadata_cache)
164
164
  installation_result.app_specs_by_native_target.each do |app_native_target, app_spec|
165
165
  resource_bundle_native_targets = installation_result.app_resource_bundle_targets[app_spec.name] || []
166
166
  resource_bundle_native_targets.each do |app_resource_bundle_target|
@@ -187,7 +187,7 @@ module Pod
187
187
  # Hit the cache
188
188
  cached_dependency = metadata_cache.target_label_by_metadata[app_dependent_target.label]
189
189
  project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
190
- Project.add_cached_dependency(sandbox, native_target, cached_dependency)
190
+ Project.add_cached_dependency(sandbox, app_native_target, cached_dependency)
191
191
  end
192
192
  end
193
193
  end
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/array'
2
+ require 'active_support/core_ext/string/inflections'
1
3
  require 'cocoapods/xcode'
2
4
 
3
5
  module Pod
@@ -14,11 +16,15 @@ module Pod
14
16
  #
15
17
  attr_reader :umbrella_header_paths
16
18
 
19
+ # @return [PodTarget] @see TargetInstaller#target
20
+ #
21
+ attr_reader :target
22
+
17
23
  # Initialize a new instance
18
24
  #
19
25
  # @param [Sandbox] sandbox @see TargetInstaller#sandbox
20
26
  # @param [Pod::Project] project @see TargetInstaller#project
21
- # @param [Target] target @see TargetInstaller#target
27
+ # @param [PodTarget] target @see TargetInstaller#target
22
28
  # @param [Array<Pathname>] umbrella_header_paths @see #umbrella_header_paths
23
29
  #
24
30
  def initialize(sandbox, project, target, umbrella_header_paths = nil)
@@ -42,6 +48,8 @@ module Pod
42
48
  # PBXAggregateTarget that will be used to wire up dependencies later.
43
49
  native_target = add_placeholder_target
44
50
  resource_bundle_targets = add_resources_bundle_targets(library_file_accessors).values.flatten
51
+ create_copy_dsyms_script
52
+ create_copy_xcframeworks_script unless target.xcframeworks.values.all?(&:empty?)
45
53
  create_xcconfig_file(native_target, resource_bundle_targets)
46
54
  return TargetInstallationResult.new(target, native_target, resource_bundle_targets)
47
55
  end
@@ -57,8 +65,10 @@ module Pod
57
65
  app_resource_bundle_targets = add_resources_bundle_targets(app_file_accessors)
58
66
 
59
67
  add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
60
- validate_targets_contain_sources(test_native_targets + app_native_targets + [native_target])
61
- validate_xcframeworks_no_mixed_linkage
68
+ validate_targets_contain_sources(test_native_targets + app_native_targets.values + [native_target])
69
+ validate_xcframeworks
70
+
71
+ create_copy_xcframeworks_script unless target.xcframeworks.values.all?(&:empty?)
62
72
 
63
73
  create_xcconfig_file(native_target, resource_bundle_targets)
64
74
  create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets)
@@ -120,12 +130,13 @@ module Pod
120
130
  target.app_specs.each do |app_spec|
121
131
  path = target.prefix_header_path_for_spec(app_spec)
122
132
  app_spec_consumer = app_spec.consumer(target.platform)
123
- app_native_target = app_native_target_from_spec(app_spec_consumer.spec, app_native_targets)
133
+ app_native_target = app_native_targets[app_spec_consumer.spec]
124
134
  create_prefix_header(path, app_file_accessors, target.platform, app_native_target, project_directory)
125
135
  add_file_to_support_group(path)
126
136
  end
127
137
  end
128
138
  create_dummy_source(native_target)
139
+ create_copy_dsyms_script
129
140
  clean_support_files_temp_dir
130
141
  TargetInstallationResult.new(target, native_target, resource_bundle_targets,
131
142
  test_native_targets, test_resource_bundle_targets, test_app_host_targets,
@@ -177,7 +188,7 @@ module Pod
177
188
  # @return [Boolean] Whether the target should build a pch file.
178
189
  #
179
190
  def skip_pch?(specs)
180
- specs.any? { |spec| spec.prefix_header_file.is_a?(FalseClass) }
191
+ specs.any? { |spec| spec.root.prefix_header_file.is_a?(FalseClass) }
181
192
  end
182
193
 
183
194
  # True if info.plist generation should be skipped
@@ -216,9 +227,30 @@ module Pod
216
227
  settings['SWIFT_VERSION'] = target.swift_version
217
228
  end
218
229
 
230
+ if info_plist_bundle_id
231
+ settings['PRODUCT_BUNDLE_IDENTIFIER'] = info_plist_bundle_id
232
+ end
233
+
219
234
  settings
220
235
  end
221
236
 
237
+ # @return [String] Bundle Identifier found in the custom Info.plist entries
238
+ #
239
+ def info_plist_bundle_id
240
+ return @plist_bundle_id if defined?(@plist_bundle_id)
241
+ unless target.info_plist_entries.nil?
242
+ @plist_bundle_id = target.info_plist_entries['CFBundleIdentifier']
243
+ unless @plist_bundle_id.nil?
244
+ message = "The `#{target.name}` target " \
245
+ "sets a Bundle Identifier of `#{@plist_bundle_id}` in it's info.plist file. " \
246
+ 'The Bundle Identifier should be set using pod_target_xcconfig: ' \
247
+ "s.pod_target_xcconfig = { 'PRODUCT_BUNDLE_IDENTIFIER': '#{@plist_bundle_id}' }`."
248
+ UI.warn message
249
+ end
250
+ @plist_bundle_id
251
+ end
252
+ end
253
+
222
254
  # Filters the given resource file references discarding empty paths which are
223
255
  # added by their parent directory. This will also include references to the parent [PBXVariantGroup]
224
256
  # for all resources underneath it.
@@ -285,7 +317,7 @@ module Pod
285
317
  when :test
286
318
  test_native_target_from_spec(consumer.spec, test_native_targets)
287
319
  when :app
288
- app_native_target_from_spec(consumer.spec, app_native_targets)
320
+ app_native_targets[consumer.spec]
289
321
  end
290
322
 
291
323
  headers = file_accessor.headers
@@ -322,6 +354,11 @@ module Pod
322
354
 
323
355
  filter_resource_file_references(file_accessor.resources.flatten) do |compile_phase_refs, resource_phase_refs|
324
356
  native_target.add_file_references(compile_phase_refs, nil)
357
+
358
+ if target.build_as_static_framework?
359
+ resource_phase_refs = resource_phase_refs.select { |ref| Target.resource_extension_compilable?(File.extname(ref.path)) }
360
+ end
361
+
325
362
  native_target.add_resources(resource_phase_refs)
326
363
  end
327
364
  end
@@ -377,7 +414,6 @@ module Pod
377
414
  remove_pod_target_xcconfig_overrides_from_target(target.test_spec_build_settings_by_config[test_spec.name], test_native_target)
378
415
 
379
416
  # Test native targets also need frameworks and resources to be copied over to their xctest bundle.
380
- create_test_target_prepare_artifacts_script(test_spec)
381
417
  create_test_target_embed_frameworks_script(test_spec)
382
418
  create_test_target_copy_resources_script(test_spec)
383
419
 
@@ -411,10 +447,10 @@ module Pod
411
447
  # Adds the app targets for the library to the Pods project with the
412
448
  # appropriate build configurations.
413
449
  #
414
- # @return [Array<PBXNativeTarget>] the app native targets created.
450
+ # @return [Hash{Specification => PBXNativeTarget}] the app native targets created, keyed by their app spec
415
451
  #
416
452
  def add_app_targets
417
- target.app_specs.map do |app_spec|
453
+ target.app_specs.each_with_object({}) do |app_spec, hash|
418
454
  spec_consumer = app_spec.consumer(target.platform)
419
455
  spec_name = app_spec.parent.name
420
456
  subspec_name = target.subspec_label(app_spec)
@@ -473,7 +509,7 @@ module Pod
473
509
  create_app_target_copy_resources_script(app_spec)
474
510
  add_resources_to_target(resources, app_native_target)
475
511
 
476
- app_native_target
512
+ hash[app_spec] = app_native_target
477
513
  end
478
514
  end
479
515
 
@@ -649,33 +685,6 @@ module Pod
649
685
  end
650
686
  end
651
687
 
652
- # Creates a script that prepares artifacts for the test target.
653
- #
654
- # @param [Specification] test_spec
655
- # The test spec to create the script for.
656
- #
657
- # @return [void]
658
- #
659
- def create_test_target_prepare_artifacts_script(test_spec)
660
- path = target.prepare_artifacts_script_path_for_spec(test_spec)
661
- host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt|
662
- pt.specs.map(&:name)
663
- end.uniq
664
- frameworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
665
- paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
666
- spec_paths_to_include = pod_target.library_specs.map(&:name)
667
- spec_paths_to_include -= host_target_spec_names
668
- spec_paths_to_include << test_spec.name if pod_target == target
669
- pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
670
- end
671
- end
672
- unless frameworks_by_config.each_value.all?(&:empty?)
673
- generator = Generator::PrepareArtifactsScript.new(frameworks_by_config, target.sandbox.root, target.platform)
674
- update_changed_file(generator, path)
675
- add_file_to_support_group(path)
676
- end
677
- end
678
-
679
688
  # Creates a script that embeds the frameworks to the bundle of the test target.
680
689
  #
681
690
  # @param [Specification] test_spec
@@ -696,8 +705,16 @@ module Pod
696
705
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
697
706
  end
698
707
  end
699
- unless framework_paths_by_config.each_value.all?(&:empty?)
700
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
708
+ xcframeworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
709
+ paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
710
+ spec_paths_to_include = pod_target.library_specs.map(&:name)
711
+ spec_paths_to_include -= host_target_spec_names
712
+ spec_paths_to_include << test_spec.name if pod_target == target
713
+ pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
714
+ end
715
+ end
716
+ unless framework_paths_by_config.each_value.all?(&:empty?) && xcframeworks_by_config.each_value.all?(&:empty?)
717
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config, xcframeworks_by_config)
701
718
  update_changed_file(generator, path)
702
719
  add_file_to_support_group(path)
703
720
  end
@@ -705,8 +722,8 @@ module Pod
705
722
 
706
723
  # Generates the contents of the xcconfig file used for each app target type and saves it to disk.
707
724
  #
708
- # @param [Array<PBXNativeTarget>] app_native_targets
709
- # the app native target to link the xcconfig file into.
725
+ # @param [Hash{Specification => PBXNativeTarget}] app_native_targets
726
+ # the app native targets to link the xcconfig file into.
710
727
  #
711
728
  # @param [Hash{String=>Array<PBXNativeTarget>}] app_resource_bundle_targets
712
729
  # the additional app resource bundle targets to link the xcconfig file into.
@@ -716,7 +733,7 @@ module Pod
716
733
  def create_app_xcconfig_files(app_native_targets, app_resource_bundle_targets)
717
734
  target.app_specs.each do |app_spec|
718
735
  spec_consumer = app_spec.consumer(target.platform)
719
- app_native_target = app_native_target_from_spec(spec_consumer.spec, app_native_targets)
736
+ app_native_target = app_native_targets[spec_consumer.spec]
720
737
 
721
738
  target.user_config_names_by_config_type.each do |config, names|
722
739
  path = target.xcconfig_path("#{target.subspec_label(app_spec)}.#{config}")
@@ -765,20 +782,57 @@ module Pod
765
782
  def create_app_target_embed_frameworks_script(app_spec)
766
783
  path = target.embed_frameworks_script_path_for_spec(app_spec)
767
784
  framework_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
768
- pod_targets = target.dependent_targets_for_app_spec(app_spec, :configuration => config)
769
- paths_by_config[config_name] = pod_targets.flat_map do |pod_target|
785
+ paths_by_config[config_name] = target.dependent_targets_for_app_spec(app_spec, :configuration => config).flat_map do |pod_target|
770
786
  spec_paths_to_include = pod_target.library_specs.map(&:name)
771
787
  spec_paths_to_include << app_spec.name if pod_target == target
772
788
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
773
789
  end
774
790
  end
775
- unless framework_paths_by_config.each_value.all?(&:empty?)
776
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
791
+ xcframeworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
792
+ paths_by_config[config_name] = target.dependent_targets_for_app_spec(app_spec, :configuration => config).flat_map do |pod_target|
793
+ spec_paths_to_include = pod_target.library_specs.map(&:name)
794
+ spec_paths_to_include << app_spec.name if pod_target == target
795
+ pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
796
+ end
797
+ end
798
+
799
+ unless framework_paths_by_config.each_value.all?(&:empty?) && xcframeworks_by_config.each_value.all?(&:empty?)
800
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config, xcframeworks_by_config)
801
+ update_changed_file(generator, path)
802
+ add_file_to_support_group(path)
803
+ end
804
+ end
805
+
806
+ # Creates a script that copies and strips vendored dSYMs and bcsymbolmaps.
807
+ #
808
+ # @return [void]
809
+ #
810
+ def create_copy_dsyms_script
811
+ dsym_paths = PodTargetInstaller.dsym_paths(target)
812
+ bcsymbolmap_paths = PodTargetInstaller.bcsymbolmap_paths(target)
813
+ path = target.copy_dsyms_script_path
814
+ unless dsym_paths.empty? && bcsymbolmap_paths.empty?
815
+ generator = Generator::CopydSYMsScript.new(dsym_paths, bcsymbolmap_paths)
777
816
  update_changed_file(generator, path)
778
817
  add_file_to_support_group(path)
779
818
  end
780
819
  end
781
820
 
821
+ # Creates a script that copies the appropriate xcframework slice to the build dir.
822
+ #
823
+ # @note We can't use Xcode default link libraries phase, because
824
+ # we need to ensure that we only copy the frameworks which are
825
+ # relevant for the current build configuration.
826
+ #
827
+ # @return [void]
828
+ #
829
+ def create_copy_xcframeworks_script
830
+ path = target.copy_xcframeworks_script_path
831
+ generator = Generator::CopyXCFrameworksScript.new(target.xcframeworks.values.flatten, sandbox.root, target.platform)
832
+ update_changed_file(generator, path)
833
+ add_file_to_support_group(path)
834
+ end
835
+
782
836
  # Manually add `libswiftSwiftOnoneSupport.dylib` as it seems there is an issue with tests that do not include it for Debug configurations.
783
837
  # Possibly related to Swift module optimization.
784
838
  #
@@ -943,9 +997,18 @@ module Pod
943
997
  end
944
998
 
945
999
  def project_file_references_array(files, file_type)
1000
+ error_message_for_missing_reference = lambda do |sf, target|
1001
+ "Unable to find #{file_type} ref for `#{sf.basename}` for target `#{target.name}`."
1002
+ end
946
1003
  files.map do |sf|
947
- project.reference_for_path(sf).tap do |ref|
948
- raise Informative, "Unable to find #{file_type} ref for `#{sf.basename}` for target `#{target.name}`." unless ref
1004
+ begin
1005
+ project.reference_for_path(sf).tap do |ref|
1006
+ raise Informative, error_message_for_missing_reference.call(sf, target) unless ref
1007
+ end
1008
+ rescue Errno::ENOENT
1009
+ # Normalize the error for Ruby < 2.7. Ruby 2.7 can crash on a different call of real path compared
1010
+ # to older versions. This ensures that the error message is consistent.
1011
+ raise Informative, error_message_for_missing_reference.call(sf, target)
949
1012
  end
950
1013
  end
951
1014
  end
@@ -1011,13 +1074,6 @@ module Pod
1011
1074
  end
1012
1075
  end
1013
1076
 
1014
- def app_native_target_from_spec(spec, app_native_targets)
1015
- app_target_label = target.app_target_label(spec)
1016
- app_native_targets.find do |app_native_target|
1017
- app_native_target.name == app_target_label
1018
- end
1019
- end
1020
-
1021
1077
  # Adds a placeholder native target for the library to the Pods project with the
1022
1078
  # appropriate build configurations.
1023
1079
  #
@@ -1086,19 +1142,80 @@ module Pod
1086
1142
  end
1087
1143
  end
1088
1144
 
1089
- # Raises if a vendored xcframework contains frameworks of mixed linkage
1145
+ # Raises if a vendored xcframework contains frameworks of mixed linkage or mixed packaging
1090
1146
  #
1091
- def validate_xcframeworks_no_mixed_linkage
1147
+ def validate_xcframeworks
1092
1148
  target.xcframeworks.each_value do |xcframeworks|
1093
1149
  xcframeworks.each do |xcframework|
1094
- dynamic_slices, static_slices = xcframework.slices.partition { |slice| Pod::Xcode::LinkageAnalyzer.dynamic_binary?(slice.path) }
1150
+ if xcframework.slices.empty?
1151
+ raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it does not contain any binaries."
1152
+ end
1153
+ if xcframework.build_type.dynamic_library?
1154
+ raise Informative, <<-MSG.strip_heredoc
1155
+ Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it contains dynamic libraries which are not supported.
1156
+ Use dynamic frameworks for dynamic linking instead.
1157
+ MSG
1158
+ end
1159
+ if xcframework.build_type.static_library?
1160
+ binary_names = xcframework.slices.map { |slice| File.basename(slice.binary_path, File.extname(slice.binary_path)) }.uniq
1161
+ if binary_names.size > 1
1162
+ raise Informative, <<-MSG.strip_heredoc
1163
+ Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it contains static libraries
1164
+ with differing binary names: #{binary_names.to_sentence}.
1165
+ MSG
1166
+ end
1167
+ end
1168
+ dynamic_slices, static_slices = xcframework.slices.partition(&:dynamic?)
1095
1169
  if !dynamic_slices.empty? && !static_slices.empty?
1096
1170
  raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}`, because it contains both static and dynamic frameworks."
1097
1171
  end
1172
+ library_slices, framework_slices = xcframework.slices.partition(&:library?)
1173
+ if !library_slices.empty? && !framework_slices.empty?
1174
+ raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}`, because it contains both libraries and frameworks."
1175
+ end
1098
1176
  end
1099
1177
  end
1100
1178
  end
1179
+
1101
1180
  #-----------------------------------------------------------------------#
1181
+
1182
+ class << self
1183
+ # @param [PodTarget] target the target to be installed
1184
+ #
1185
+ # @return [Array<String>] the dSYM paths for the given target
1186
+ #
1187
+ def dsym_paths(target)
1188
+ dsym_paths = target.framework_paths.values.flatten.reject { |fmwk_path| fmwk_path.dsym_path.nil? }.map(&:dsym_path)
1189
+ dsym_paths.concat(target.xcframeworks.values.flatten.flat_map { |xcframework| xcframework_dsyms(xcframework.path) })
1190
+ dsym_paths
1191
+ end
1192
+
1193
+ # @param [PodTarget] target the target to be installed
1194
+ #
1195
+ # @return [Array<String>] the bcsymbolmap paths for the given target
1196
+ #
1197
+ def bcsymbolmap_paths(target)
1198
+ target.framework_paths.values.flatten.reject do |fmwk_path|
1199
+ fmwk_path.bcsymbolmap_paths.nil?
1200
+ end.flat_map(&:bcsymbolmap_paths)
1201
+ end
1202
+
1203
+ # @param [Pathname] xcframework_path
1204
+ # the base path of the .xcframework bundle
1205
+ #
1206
+ # @return [Array<Pathname>] all found .dSYM paths
1207
+ #
1208
+ def xcframework_dsyms(xcframework_path)
1209
+ basename = File.basename(xcframework_path, '.xcframework')
1210
+ dsym_basename = basename + '.dSYMs'
1211
+ path = xcframework_path.dirname + dsym_basename
1212
+ if File.directory?(path)
1213
+ Dir.glob(path + '*.dSYM')
1214
+ else
1215
+ []
1216
+ end
1217
+ end
1218
+ end
1102
1219
  end
1103
1220
  end
1104
1221
  end