cocoapods 1.9.2 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +235 -6
  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 +125 -212
  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/project_cache/project_metadata_cache.rb +4 -0
  28. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +2 -1
  29. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +132 -111
  30. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +45 -6
  31. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +13 -27
  32. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +5 -1
  33. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +2 -1
  34. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +8 -6
  35. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +180 -59
  36. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +61 -30
  37. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +3 -2
  38. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +5 -7
  39. data/lib/cocoapods/installer/xcode/pods_project_generator_result.rb +19 -0
  40. data/lib/cocoapods/installer/xcode/target_validator.rb +1 -1
  41. data/lib/cocoapods/sources_manager.rb +2 -1
  42. data/lib/cocoapods/target.rb +44 -2
  43. data/lib/cocoapods/target/aggregate_target.rb +35 -0
  44. data/lib/cocoapods/target/build_settings.rb +94 -18
  45. data/lib/cocoapods/target/pod_target.rb +85 -11
  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 +37 -11
  49. data/lib/cocoapods/xcode/framework_paths.rb +1 -1
  50. data/lib/cocoapods/xcode/xcframework.rb +17 -4
  51. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +81 -3
  52. metadata +31 -53
  53. 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
@@ -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.
@@ -79,7 +79,11 @@ module Pod
79
79
  app_host_target.build_configurations.each do |configuration|
80
80
  configuration.build_settings['PRODUCT_NAME'] = app_target_label
81
81
  configuration.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}'
82
- configuration.build_settings['CODE_SIGN_IDENTITY'] = '' if platform == :osx
82
+ if platform == :osx
83
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = ''
84
+ elsif platform == :ios
85
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = 'iPhone Developer'
86
+ end
83
87
  configuration.build_settings['CURRENT_PROJECT_VERSION'] = '1'
84
88
  end
85
89
 
@@ -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
@@ -152,15 +152,17 @@ module Pod
152
152
  target_attributes[test_native_target.uuid.to_s] = { 'TestTargetID' => app_native_target.uuid.to_s }
153
153
  project.root_object.attributes['TargetAttributes'] = target_attributes
154
154
  test_native_target.add_dependency(app_native_target)
155
- else
155
+ elsif cached_dependency = metadata_cache.target_label_by_metadata[app_host_target_label]
156
156
  # Hit the cache
157
- cached_dependency = metadata_cache.target_label_by_metadata[app_host_target_label]
158
157
  project.add_cached_subproject_reference(sandbox, cached_dependency, project.dependencies_group)
159
158
  Project.add_cached_dependency(sandbox, test_native_target, cached_dependency)
159
+ else
160
+ raise "Expected to either have an installation or cache result for #{app_host_target_label} (from pod #{app_host_pod_target_label}) " \
161
+ "for target #{test_native_target.name} in project #{project.project_name}"
160
162
  end
161
163
  end
162
164
 
163
- def wire_app_native_targets(pod_target, native_target, installation_result, pod_target_installation_results, project, frameworks_group, metadata_cache)
165
+ def wire_app_native_targets(pod_target, installation_result, pod_target_installation_results, project, frameworks_group, metadata_cache)
164
166
  installation_result.app_specs_by_native_target.each do |app_native_target, app_spec|
165
167
  resource_bundle_native_targets = installation_result.app_resource_bundle_targets[app_spec.name] || []
166
168
  resource_bundle_native_targets.each do |app_resource_bundle_target|
@@ -187,7 +189,7 @@ module Pod
187
189
  # Hit the cache
188
190
  cached_dependency = metadata_cache.target_label_by_metadata[app_dependent_target.label]
189
191
  project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
190
- Project.add_cached_dependency(sandbox, native_target, cached_dependency)
192
+ Project.add_cached_dependency(sandbox, app_native_target, cached_dependency)
191
193
  end
192
194
  end
193
195
  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? && consumer.spec.library_specification?
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
@@ -371,13 +408,16 @@ module Pod
371
408
  configuration.build_settings['CODE_SIGNING_ALLOWED'] = 'YES'
372
409
  end
373
410
  # For macOS we do not code sign the XCTest bundle because we do not code sign the frameworks either.
374
- configuration.build_settings['CODE_SIGN_IDENTITY'] = '' if target.platform == :osx
411
+ if target.platform == :osx
412
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = ''
413
+ elsif target.platform == :ios
414
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = 'iPhone Developer'
415
+ end
375
416
  end
376
417
 
377
418
  remove_pod_target_xcconfig_overrides_from_target(target.test_spec_build_settings_by_config[test_spec.name], test_native_target)
378
419
 
379
420
  # 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
421
  create_test_target_embed_frameworks_script(test_spec)
382
422
  create_test_target_copy_resources_script(test_spec)
383
423
 
@@ -411,10 +451,10 @@ module Pod
411
451
  # Adds the app targets for the library to the Pods project with the
412
452
  # appropriate build configurations.
413
453
  #
414
- # @return [Array<PBXNativeTarget>] the app native targets created.
454
+ # @return [Hash{Specification => PBXNativeTarget}] the app native targets created, keyed by their app spec
415
455
  #
416
456
  def add_app_targets
417
- target.app_specs.map do |app_spec|
457
+ target.app_specs.each_with_object({}) do |app_spec, hash|
418
458
  spec_consumer = app_spec.consumer(target.platform)
419
459
  spec_name = app_spec.parent.name
420
460
  subspec_name = target.subspec_label(app_spec)
@@ -473,7 +513,7 @@ module Pod
473
513
  create_app_target_copy_resources_script(app_spec)
474
514
  add_resources_to_target(resources, app_native_target)
475
515
 
476
- app_native_target
516
+ hash[app_spec] = app_native_target
477
517
  end
478
518
  end
479
519
 
@@ -649,33 +689,6 @@ module Pod
649
689
  end
650
690
  end
651
691
 
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
692
  # Creates a script that embeds the frameworks to the bundle of the test target.
680
693
  #
681
694
  # @param [Specification] test_spec
@@ -696,8 +709,16 @@ module Pod
696
709
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
697
710
  end
698
711
  end
699
- unless framework_paths_by_config.each_value.all?(&:empty?)
700
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
712
+ xcframeworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
713
+ paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
714
+ spec_paths_to_include = pod_target.library_specs.map(&:name)
715
+ spec_paths_to_include -= host_target_spec_names
716
+ spec_paths_to_include << test_spec.name if pod_target == target
717
+ pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
718
+ end
719
+ end
720
+ unless framework_paths_by_config.each_value.all?(&:empty?) && xcframeworks_by_config.each_value.all?(&:empty?)
721
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config, xcframeworks_by_config)
701
722
  update_changed_file(generator, path)
702
723
  add_file_to_support_group(path)
703
724
  end
@@ -705,8 +726,8 @@ module Pod
705
726
 
706
727
  # Generates the contents of the xcconfig file used for each app target type and saves it to disk.
707
728
  #
708
- # @param [Array<PBXNativeTarget>] app_native_targets
709
- # the app native target to link the xcconfig file into.
729
+ # @param [Hash{Specification => PBXNativeTarget}] app_native_targets
730
+ # the app native targets to link the xcconfig file into.
710
731
  #
711
732
  # @param [Hash{String=>Array<PBXNativeTarget>}] app_resource_bundle_targets
712
733
  # the additional app resource bundle targets to link the xcconfig file into.
@@ -716,7 +737,7 @@ module Pod
716
737
  def create_app_xcconfig_files(app_native_targets, app_resource_bundle_targets)
717
738
  target.app_specs.each do |app_spec|
718
739
  spec_consumer = app_spec.consumer(target.platform)
719
- app_native_target = app_native_target_from_spec(spec_consumer.spec, app_native_targets)
740
+ app_native_target = app_native_targets[spec_consumer.spec]
720
741
 
721
742
  target.user_config_names_by_config_type.each do |config, names|
722
743
  path = target.xcconfig_path("#{target.subspec_label(app_spec)}.#{config}")
@@ -765,20 +786,57 @@ module Pod
765
786
  def create_app_target_embed_frameworks_script(app_spec)
766
787
  path = target.embed_frameworks_script_path_for_spec(app_spec)
767
788
  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|
789
+ paths_by_config[config_name] = target.dependent_targets_for_app_spec(app_spec, :configuration => config).flat_map do |pod_target|
770
790
  spec_paths_to_include = pod_target.library_specs.map(&:name)
771
791
  spec_paths_to_include << app_spec.name if pod_target == target
772
792
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
773
793
  end
774
794
  end
775
- unless framework_paths_by_config.each_value.all?(&:empty?)
776
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
795
+ xcframeworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
796
+ paths_by_config[config_name] = target.dependent_targets_for_app_spec(app_spec, :configuration => config).flat_map do |pod_target|
797
+ spec_paths_to_include = pod_target.library_specs.map(&:name)
798
+ spec_paths_to_include << app_spec.name if pod_target == target
799
+ pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
800
+ end
801
+ end
802
+
803
+ unless framework_paths_by_config.each_value.all?(&:empty?) && xcframeworks_by_config.each_value.all?(&:empty?)
804
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config, xcframeworks_by_config)
805
+ update_changed_file(generator, path)
806
+ add_file_to_support_group(path)
807
+ end
808
+ end
809
+
810
+ # Creates a script that copies and strips vendored dSYMs and bcsymbolmaps.
811
+ #
812
+ # @return [void]
813
+ #
814
+ def create_copy_dsyms_script
815
+ dsym_paths = PodTargetInstaller.dsym_paths(target)
816
+ bcsymbolmap_paths = PodTargetInstaller.bcsymbolmap_paths(target)
817
+ path = target.copy_dsyms_script_path
818
+ unless dsym_paths.empty? && bcsymbolmap_paths.empty?
819
+ generator = Generator::CopydSYMsScript.new(dsym_paths, bcsymbolmap_paths)
777
820
  update_changed_file(generator, path)
778
821
  add_file_to_support_group(path)
779
822
  end
780
823
  end
781
824
 
825
+ # Creates a script that copies the appropriate xcframework slice to the build dir.
826
+ #
827
+ # @note We can't use Xcode default link libraries phase, because
828
+ # we need to ensure that we only copy the frameworks which are
829
+ # relevant for the current build configuration.
830
+ #
831
+ # @return [void]
832
+ #
833
+ def create_copy_xcframeworks_script
834
+ path = target.copy_xcframeworks_script_path
835
+ generator = Generator::CopyXCFrameworksScript.new(target.xcframeworks.values.flatten, sandbox.root, target.platform)
836
+ update_changed_file(generator, path)
837
+ add_file_to_support_group(path)
838
+ end
839
+
782
840
  # Manually add `libswiftSwiftOnoneSupport.dylib` as it seems there is an issue with tests that do not include it for Debug configurations.
783
841
  # Possibly related to Swift module optimization.
784
842
  #
@@ -943,9 +1001,18 @@ module Pod
943
1001
  end
944
1002
 
945
1003
  def project_file_references_array(files, file_type)
1004
+ error_message_for_missing_reference = lambda do |sf, target|
1005
+ "Unable to find #{file_type} ref for `#{sf.basename}` for target `#{target.name}`."
1006
+ end
946
1007
  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
1008
+ begin
1009
+ project.reference_for_path(sf).tap do |ref|
1010
+ raise Informative, error_message_for_missing_reference.call(sf, target) unless ref
1011
+ end
1012
+ rescue Errno::ENOENT
1013
+ # Normalize the error for Ruby < 2.7. Ruby 2.7 can crash on a different call of real path compared
1014
+ # to older versions. This ensures that the error message is consistent.
1015
+ raise Informative, error_message_for_missing_reference.call(sf, target)
949
1016
  end
950
1017
  end
951
1018
  end
@@ -1011,13 +1078,6 @@ module Pod
1011
1078
  end
1012
1079
  end
1013
1080
 
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
1081
  # Adds a placeholder native target for the library to the Pods project with the
1022
1082
  # appropriate build configurations.
1023
1083
  #
@@ -1086,19 +1146,80 @@ module Pod
1086
1146
  end
1087
1147
  end
1088
1148
 
1089
- # Raises if a vendored xcframework contains frameworks of mixed linkage
1149
+ # Raises if a vendored xcframework contains frameworks of mixed linkage or mixed packaging
1090
1150
  #
1091
- def validate_xcframeworks_no_mixed_linkage
1151
+ def validate_xcframeworks
1092
1152
  target.xcframeworks.each_value do |xcframeworks|
1093
1153
  xcframeworks.each do |xcframework|
1094
- dynamic_slices, static_slices = xcframework.slices.partition { |slice| Pod::Xcode::LinkageAnalyzer.dynamic_binary?(slice.path) }
1154
+ if xcframework.slices.empty?
1155
+ raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it does not contain any binaries."
1156
+ end
1157
+ if xcframework.build_type.dynamic_library?
1158
+ raise Informative, <<-MSG.strip_heredoc
1159
+ Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it contains dynamic libraries which are not supported.
1160
+ Use dynamic frameworks for dynamic linking instead.
1161
+ MSG
1162
+ end
1163
+ if xcframework.build_type.static_library?
1164
+ binary_names = xcframework.slices.map { |slice| File.basename(slice.binary_path, File.extname(slice.binary_path)) }.uniq
1165
+ if binary_names.size > 1
1166
+ raise Informative, <<-MSG.strip_heredoc
1167
+ Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}` because it contains static libraries
1168
+ with differing binary names: #{binary_names.to_sentence}.
1169
+ MSG
1170
+ end
1171
+ end
1172
+ dynamic_slices, static_slices = xcframework.slices.partition(&:dynamic?)
1095
1173
  if !dynamic_slices.empty? && !static_slices.empty?
1096
1174
  raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}`, because it contains both static and dynamic frameworks."
1097
1175
  end
1176
+ library_slices, framework_slices = xcframework.slices.partition(&:library?)
1177
+ if !library_slices.empty? && !framework_slices.empty?
1178
+ raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}`, because it contains both libraries and frameworks."
1179
+ end
1098
1180
  end
1099
1181
  end
1100
1182
  end
1183
+
1101
1184
  #-----------------------------------------------------------------------#
1185
+
1186
+ class << self
1187
+ # @param [PodTarget] target the target to be installed
1188
+ #
1189
+ # @return [Array<String>] the dSYM paths for the given target
1190
+ #
1191
+ def dsym_paths(target)
1192
+ dsym_paths = target.framework_paths.values.flatten.reject { |fmwk_path| fmwk_path.dsym_path.nil? }.map(&:dsym_path)
1193
+ dsym_paths.concat(target.xcframeworks.values.flatten.flat_map { |xcframework| xcframework_dsyms(xcframework.path) })
1194
+ dsym_paths
1195
+ end
1196
+
1197
+ # @param [PodTarget] target the target to be installed
1198
+ #
1199
+ # @return [Array<String>] the bcsymbolmap paths for the given target
1200
+ #
1201
+ def bcsymbolmap_paths(target)
1202
+ target.framework_paths.values.flatten.reject do |fmwk_path|
1203
+ fmwk_path.bcsymbolmap_paths.nil?
1204
+ end.flat_map(&:bcsymbolmap_paths)
1205
+ end
1206
+
1207
+ # @param [Pathname] xcframework_path
1208
+ # the base path of the .xcframework bundle
1209
+ #
1210
+ # @return [Array<Pathname>] all found .dSYM paths
1211
+ #
1212
+ def xcframework_dsyms(xcframework_path)
1213
+ basename = File.basename(xcframework_path, '.xcframework')
1214
+ dsym_basename = basename + '.dSYMs'
1215
+ path = xcframework_path.dirname + dsym_basename
1216
+ if File.directory?(path)
1217
+ Dir.glob(path + '*.dSYM')
1218
+ else
1219
+ []
1220
+ end
1221
+ end
1222
+ end
1102
1223
  end
1103
1224
  end
1104
1225
  end