cocoapods 1.8.4 → 1.9.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -1
  3. data/lib/cocoapods.rb +1 -0
  4. data/lib/cocoapods/command/setup.rb +1 -0
  5. data/lib/cocoapods/executable.rb +1 -1
  6. data/lib/cocoapods/gem_version.rb +1 -1
  7. data/lib/cocoapods/generator/embed_frameworks_script.rb +36 -6
  8. data/lib/cocoapods/generator/prepare_artifacts_script.rb +244 -0
  9. data/lib/cocoapods/installer.rb +6 -5
  10. data/lib/cocoapods/installer/analyzer.rb +137 -59
  11. data/lib/cocoapods/installer/analyzer/pod_variant.rb +27 -12
  12. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +11 -2
  13. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +10 -2
  14. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +15 -2
  15. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +7 -5
  16. data/lib/cocoapods/installer/user_project_integrator.rb +1 -10
  17. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +100 -19
  18. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +3 -0
  19. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +29 -4
  20. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +7 -2
  21. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +106 -45
  22. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +68 -1
  23. data/lib/cocoapods/installer/xcode/pods_project_generator/pods_project_writer.rb +29 -14
  24. data/lib/cocoapods/sandbox/file_accessor.rb +32 -21
  25. data/lib/cocoapods/sources_manager.rb +9 -2
  26. data/lib/cocoapods/target.rb +11 -14
  27. data/lib/cocoapods/target/aggregate_target.rb +78 -18
  28. data/lib/cocoapods/target/build_settings.rb +64 -31
  29. data/lib/cocoapods/target/pod_target.rb +236 -87
  30. data/lib/cocoapods/user_interface/error_report.rb +14 -4
  31. data/lib/cocoapods/validator.rb +2 -0
  32. data/lib/cocoapods/xcode.rb +7 -0
  33. data/lib/cocoapods/{target → xcode}/framework_paths.rb +14 -1
  34. data/lib/cocoapods/xcode/linkage_analyzer.rb +22 -0
  35. data/lib/cocoapods/xcode/xcframework.rb +81 -0
  36. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +51 -0
  37. metadata +12 -8
  38. data/lib/cocoapods/target/build_type.rb +0 -139
@@ -22,6 +22,10 @@ module Pod
22
22
  #
23
23
  attr_reader :project_object_version
24
24
 
25
+ # @return [Hash<String, Hash>] The podfile plugins to be run for the installation.
26
+ #
27
+ attr_reader :podfile_plugins
28
+
25
29
  # @return [Array<PodTarget>] The list of pod targets.
26
30
  #
27
31
  attr_reader :pod_targets
@@ -40,15 +44,17 @@ module Pod
40
44
  # @param [ProjectInstallationCache] cache @see #cache
41
45
  # @param [Hash{String => Symbol}] build_configurations @see #build_configurations
42
46
  # @param [Integer] project_object_version @see #project_object_version
47
+ # @param [Hash<String, Hash>] podfile_plugins @see #podfile_plugins
43
48
  # @param [Array<PodTarget>] pod_targets @see #pod_targets
44
49
  # @param [Array<AggregateTarget>] aggregate_targets @see #aggregate_targets
45
50
  # @param [Bool] clean_install @see #clean_install
46
51
  #
47
- def initialize(sandbox, cache, build_configurations, project_object_version, pod_targets, aggregate_targets,
52
+ def initialize(sandbox, cache, build_configurations, project_object_version, podfile_plugins, pod_targets, aggregate_targets,
48
53
  clean_install: false)
49
54
  @sandbox = sandbox
50
55
  @cache = cache
51
56
  @build_configurations = build_configurations
57
+ @podfile_plugins = podfile_plugins
52
58
  @pod_targets = pod_targets
53
59
  @aggregate_targets = aggregate_targets
54
60
  @project_object_version = project_object_version
@@ -70,7 +76,9 @@ module Pod
70
76
  end
71
77
 
72
78
  # Bail out early since these properties affect all targets and their associate projects.
73
- if cache.build_configurations != build_configurations || cache.project_object_version != project_object_version
79
+ if cache.build_configurations != build_configurations ||
80
+ cache.project_object_version != project_object_version ||
81
+ YAMLHelper.convert(cache.podfile_plugins) != YAMLHelper.convert(podfile_plugins)
74
82
  UI.message 'Ignoring project cache due to project configuration changes.'
75
83
  return full_install_results
76
84
  end
@@ -21,16 +21,23 @@ module Pod
21
21
  #
22
22
  attr_reader :project_object_version
23
23
 
24
+ # @return [Hash<String, Hash>]
25
+ # Podfile plugins used with a particular install.
26
+ #
27
+ attr_reader :podfile_plugins
28
+
24
29
  # Initializes a new instance.
25
30
  #
26
31
  # @param [Hash{String => TargetCacheKey}] cache_key_by_target_label @see #cache_key_by_target_label
27
32
  # @param [Hash{String => Symbol}] build_configurations @see #build_configurations
28
33
  # @param [Integer] project_object_version @see #project_object_version
34
+ # @param [Hash<String, Hash>] podfile_plugins @see #podfile_plugins
29
35
  #
30
- def initialize(cache_key_by_target_label = {}, build_configurations = nil, project_object_version = nil)
36
+ def initialize(cache_key_by_target_label = {}, build_configurations = nil, project_object_version = nil, podfile_plugins = {})
31
37
  @cache_key_by_target_label = cache_key_by_target_label
32
38
  @build_configurations = build_configurations
33
39
  @project_object_version = project_object_version
40
+ @podfile_plugins = podfile_plugins
34
41
  end
35
42
 
36
43
  def update_cache_key_by_target_label!(cache_key_by_target_label)
@@ -45,6 +52,10 @@ module Pod
45
52
  @project_object_version = project_object_version
46
53
  end
47
54
 
55
+ def update_podfile_plugins!(podfile_plugins)
56
+ @podfile_plugins = podfile_plugins
57
+ end
58
+
48
59
  def save_as(path)
49
60
  Pathname(path).dirname.mkpath
50
61
  Sandbox.update_changed_file(path, YAMLHelper.convert(to_hash))
@@ -59,7 +70,8 @@ module Pod
59
70
  end]
60
71
  project_object_version = contents['OBJECT_VERSION']
61
72
  build_configurations = contents['BUILD_CONFIGURATIONS']
62
- ProjectInstallationCache.new(cache_key_by_target_label, build_configurations, project_object_version)
73
+ podfile_plugins = contents['PLUGINS']
74
+ ProjectInstallationCache.new(cache_key_by_target_label, build_configurations, project_object_version, podfile_plugins)
63
75
  end
64
76
 
65
77
  def to_hash
@@ -69,6 +81,7 @@ module Pod
69
81
  contents = { 'CACHE_KEYS' => cache_key_contents }
70
82
  contents['BUILD_CONFIGURATIONS'] = build_configurations if build_configurations
71
83
  contents['OBJECT_VERSION'] = project_object_version if project_object_version
84
+ contents['PLUGINS'] = podfile_plugins if podfile_plugins
72
85
  contents
73
86
  end
74
87
  end
@@ -116,12 +116,14 @@ module Pod
116
116
  #
117
117
  def self.from_pod_target(sandbox, pod_target, is_local_pod: false, checkout_options: nil)
118
118
  build_settings = {}
119
- build_settings[pod_target.label.to_s] = Digest::MD5.hexdigest(pod_target.build_settings.xcconfig.to_s)
120
- pod_target.test_spec_build_settings.each do |name, settings|
121
- build_settings[name] = Digest::MD5.hexdigest(settings.xcconfig.to_s)
119
+ build_settings[pod_target.label.to_s] = Hash[pod_target.build_settings.map do |k, v|
120
+ [k, Digest::MD5.hexdigest(v.xcconfig.to_s)]
121
+ end]
122
+ pod_target.test_spec_build_settings_by_config.each do |name, settings_by_config|
123
+ build_settings[name] = Hash[settings_by_config.map { |k, v| [k, Digest::MD5.hexdigest(v.xcconfig.to_s)] }]
122
124
  end
123
- pod_target.app_spec_build_settings.each do |name, settings|
124
- build_settings[name] = Digest::MD5.hexdigest(settings.xcconfig.to_s)
125
+ pod_target.app_spec_build_settings_by_config.each do |name, settings_by_config|
126
+ build_settings[name] = Hash[settings_by_config.map { |k, v| [k, Digest::MD5.hexdigest(v.xcconfig.to_s)] }]
125
127
  end
126
128
 
127
129
  contents = {
@@ -92,7 +92,7 @@ module Pod
92
92
  # @return [void]
93
93
  #
94
94
  def create_workspace
95
- all_projects = user_project_paths_to_integrate.sort.push(sandbox.project_path).uniq
95
+ all_projects = user_project_paths.sort.push(sandbox.project_path).uniq
96
96
  file_references = all_projects.map do |path|
97
97
  relative_path = path.relative_path_from(workspace_path.dirname).to_s
98
98
  Xcodeproj::Workspace::FileReference.new(relative_path, 'group')
@@ -221,15 +221,6 @@ module Pod
221
221
  end
222
222
  end
223
223
 
224
- # @return [Array<Pathname>] the paths of all the user projects referenced
225
- # by the targets that require integration.
226
- #
227
- # @note Empty target definitions are ignored.
228
- #
229
- def user_project_paths_to_integrate
230
- targets_to_integrate.map(&:user_project_path).compact.uniq
231
- end
232
-
233
224
  # @return [Array<Xcodeproj::Project>] the projects of all the targets that require integration.
234
225
  #
235
226
  # @note Empty target definitions are ignored.
@@ -1,5 +1,5 @@
1
1
  require 'active_support/core_ext/string/inflections'
2
- require 'cocoapods/target/framework_paths'
2
+ require 'cocoapods/xcode/framework_paths'
3
3
 
4
4
  module Pod
5
5
  class Installer
@@ -37,6 +37,10 @@ module Pod
37
37
  #
38
38
  EMBED_FRAMEWORK_PHASE_NAME = 'Embed Pods Frameworks'.freeze
39
39
 
40
+ # @return [String] the name of the embed frameworks phase
41
+ #
42
+ PREPARE_ARTIFACTS_PHASE_NAME = 'Prepare Artifacts'.freeze
43
+
40
44
  # @return [String] the name of the copy resources phase
41
45
  #
42
46
  COPY_PODS_RESOURCES_PHASE_NAME = 'Copy Pods Resources'.freeze
@@ -45,6 +49,10 @@ module Pod
45
49
  #
46
50
  MAX_INPUT_OUTPUT_PATHS = 1000
47
51
 
52
+ # @return [String] the path to the artifact lists file used in the prepare & embed scripts
53
+ #
54
+ ARTIFACT_LIST_FILE = '${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt'.freeze
55
+
48
56
  # @return [AggregateTarget] the target that should be integrated.
49
57
  #
50
58
  attr_reader :target
@@ -135,15 +143,52 @@ module Pod
135
143
  TargetIntegrator.set_input_output_paths(phase, input_paths_by_config, output_paths_by_config)
136
144
  end
137
145
 
146
+ # Adds a shell script build phase responsible to copy xcframeworks slices
147
+ # generated by the TargetDefinition to the build directory.
148
+ #
149
+ # @param [PBXNativeTarget] native_target
150
+ # The native target to add the script phase into.
151
+ #
152
+ # @param [String] script_path
153
+ # The script path to execute as part of this script phase.
154
+ #
155
+ # @param [Hash<Array, String>] input_paths_by_config
156
+ # The input paths (if any) to include for this script phase.
157
+ #
158
+ # @param [Hash<Array, String>] output_paths_by_config
159
+ # The output paths (if any) to include for this script phase.
160
+ #
161
+ # @return [void]
162
+ #
163
+ def create_or_update_prepare_artifacts_script_phase_to_target(native_target, script_path, input_paths_by_config = {}, output_paths_by_config = {})
164
+ phase = TargetIntegrator.create_or_update_shell_script_build_phase(native_target, BUILD_PHASE_PREFIX + PREPARE_ARTIFACTS_PHASE_NAME)
165
+ phase.shell_script = %("#{script_path}"\n)
166
+ reorder_script_phase(native_target, phase, :before_compile)
167
+ TargetIntegrator.set_input_output_paths(phase, input_paths_by_config, output_paths_by_config)
168
+ end
169
+
138
170
  # Delete a 'Embed Pods Frameworks' Copy Files Build Phase if present
139
171
  #
140
172
  # @param [PBXNativeTarget] native_target
141
173
  # The native target to remove the script phase from.
142
174
  #
143
175
  def remove_embed_frameworks_script_phase_from_target(native_target)
144
- embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name && bp.name.end_with?(EMBED_FRAMEWORK_PHASE_NAME) }
145
- return unless embed_build_phase.present?
146
- native_target.build_phases.delete(embed_build_phase)
176
+ remove_script_phase_from_target(native_target, EMBED_FRAMEWORK_PHASE_NAME)
177
+ end
178
+
179
+ # Delete a 'Embed Pods Frameworks' Copy Files Build Phase if present
180
+ #
181
+ # @param [PBXNativeTarget] native_target
182
+ # The native target to remove the script phase from.
183
+ #
184
+ def remove_prepare_artifacts_script_phase_from_target(native_target)
185
+ remove_script_phase_from_target(native_target, PREPARE_ARTIFACTS_PHASE_NAME)
186
+ end
187
+
188
+ def remove_script_phase_from_target(native_target, phase_name)
189
+ build_phase = native_target.shell_script_build_phases.find { |bp| bp.name && bp.name.end_with?(phase_name) }
190
+ return unless build_phase.present?
191
+ native_target.build_phases.delete(build_phase)
147
192
  end
148
193
 
149
194
  # Adds a shell script build phase responsible to copy the resources
@@ -235,6 +280,7 @@ module Pod
235
280
  phase.output_paths = script_phase[:output_files]
236
281
  phase.input_file_list_paths = script_phase[:input_file_lists]
237
282
  phase.output_file_list_paths = script_phase[:output_file_lists]
283
+ phase.dependency_file = script_phase[:dependency_file]
238
284
  # At least with Xcode 10 `showEnvVarsInLog` is *NOT* set to any value even if it's checked and it only
239
285
  # gets set to '0' if the user has explicitly disabled this.
240
286
  if (show_env_vars_in_log = script_phase.fetch(:show_env_vars_in_log, '1')) == '0'
@@ -242,19 +288,22 @@ module Pod
242
288
  end
243
289
 
244
290
  execution_position = script_phase[:execution_position]
245
- unless execution_position == :any
246
- compile_build_phase_index = native_target.build_phases.index do |bp|
247
- bp.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase)
248
- end
249
- unless compile_build_phase_index.nil?
250
- script_phase_index = native_target.build_phases.index do |bp|
251
- bp.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && !bp.name.nil? && bp.name == name_with_prefix
252
- end
253
- if (execution_position == :before_compile && script_phase_index > compile_build_phase_index) ||
254
- (execution_position == :after_compile && script_phase_index < compile_build_phase_index)
255
- native_target.build_phases.move_from(script_phase_index, compile_build_phase_index)
256
- end
257
- end
291
+ reorder_script_phase(native_target, phase, execution_position)
292
+ end
293
+ end
294
+
295
+ def reorder_script_phase(native_target, script_phase, execution_position)
296
+ return if execution_position == :any
297
+ compile_build_phase_index = native_target.build_phases.index do |bp|
298
+ bp.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase)
299
+ end
300
+ unless compile_build_phase_index.nil?
301
+ script_phase_index = native_target.build_phases.index do |bp|
302
+ bp.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && !bp.name.nil? && bp.name == script_phase.name
303
+ end
304
+ if (execution_position == :before_compile && script_phase_index > compile_build_phase_index) ||
305
+ (execution_position == :after_compile && script_phase_index < compile_build_phase_index)
306
+ native_target.build_phases.move_from(script_phase_index, compile_build_phase_index)
258
307
  end
259
308
  end
260
309
  end
@@ -318,7 +367,7 @@ module Pod
318
367
 
319
368
  # Returns the framework output paths for the given input paths
320
369
  #
321
- # @param [Array<Target::FrameworkPaths>] framework_input_paths
370
+ # @param [Array<Xcode::FrameworkPaths>] framework_input_paths
322
371
  # The framework input paths to map to output paths.
323
372
  #
324
373
  # @return [Array<String>] The framework output paths
@@ -351,6 +400,7 @@ module Pod
351
400
 
352
401
  add_pods_library
353
402
  add_embed_frameworks_script_phase
403
+ add_prepare_artifacts_script_phase
354
404
  remove_embed_frameworks_script_phase_from_embedded_targets
355
405
  add_copy_resources_script_phase
356
406
  add_check_manifest_lock_script_phase
@@ -454,7 +504,7 @@ module Pod
454
504
  # @return [void]
455
505
  #
456
506
  def add_embed_frameworks_script_phase
457
- unless target.includes_frameworks?
507
+ unless target.includes_frameworks? || target.includes_xcframeworks?
458
508
  native_targets_to_embed_in.each do |native_target|
459
509
  TargetIntegrator.remove_embed_frameworks_script_phase_from_target(native_target)
460
510
  end
@@ -468,6 +518,7 @@ module Pod
468
518
  target.framework_paths_by_config.each do |config, framework_paths|
469
519
  input_paths_key = XCFileListConfigKey.new(target.embed_frameworks_script_input_files_path(config), target.embed_frameworks_script_input_files_relative_path)
470
520
  input_paths = input_paths_by_config[input_paths_key] = [script_path]
521
+ input_paths << ARTIFACT_LIST_FILE if target.includes_xcframeworks?
471
522
  framework_paths.each do |path|
472
523
  input_paths.concat(path.all_paths)
473
524
  end
@@ -482,6 +533,36 @@ module Pod
482
533
  end
483
534
  end
484
535
 
536
+ # Find or create a 'Prepare Artifacts' Copy Files Build Phase
537
+ #
538
+ # @return [void]
539
+ #
540
+ def add_prepare_artifacts_script_phase
541
+ unless target.includes_xcframeworks?
542
+ native_targets_to_embed_in.each do |native_target|
543
+ TargetIntegrator.remove_prepare_artifacts_script_phase_from_target(native_target)
544
+ end
545
+ return
546
+ end
547
+
548
+ script_path = target.prepare_artifacts_script_relative_path
549
+ input_paths_by_config = {}
550
+ output_paths_by_config = {}
551
+ if use_input_output_paths?
552
+ target.xcframeworks_by_config.each do |config, xcframeworks|
553
+ input_paths_key = XCFileListConfigKey.new(target.prepare_artifacts_script_input_files_path(config), target.prepare_artifacts_script_input_files_relative_path)
554
+ input_paths = input_paths_by_config[input_paths_key] = [script_path]
555
+ input_paths.concat(xcframeworks.map { |xcf| "${PODS_ROOT}/#{xcf.path.relative_path_from(target.sandbox.root)}" })
556
+
557
+ output_paths_key = XCFileListConfigKey.new(target.prepare_artifacts_script_output_files_path(config), target.prepare_artifacts_script_output_files_relative_path)
558
+ output_paths_by_config[output_paths_key] = [ARTIFACT_LIST_FILE]
559
+ end
560
+ end
561
+ native_targets_to_embed_in.each do |native_target|
562
+ TargetIntegrator.create_or_update_prepare_artifacts_script_phase_to_target(native_target, script_path, input_paths_by_config, output_paths_by_config)
563
+ end
564
+ end
565
+
485
566
  # Updates all target script phases for the current target, including creating or updating, deleting
486
567
  # and re-ordering.
487
568
  #
@@ -238,6 +238,9 @@ module Pod
238
238
  environment_variables.assign_variable(:key => k, :value => v)
239
239
  end
240
240
  scheme.launch_action.environment_variables = environment_variables
241
+ if scheme_configuration.key?(:code_coverage)
242
+ scheme.test_action.code_coverage_enabled = scheme_configuration[:code_coverage]
243
+ end
241
244
  scheme.save!
242
245
  end
243
246
  Xcodeproj::XCScheme.share_scheme(project.path, scheme_name) if share_scheme
@@ -16,7 +16,7 @@ module Pod
16
16
  create_support_files_dir
17
17
  create_support_files_group
18
18
  create_xcconfig_file(native_target)
19
- if target.host_requires_frameworks?
19
+ if target.build_as_framework?
20
20
  create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform)
21
21
  create_module_map(native_target)
22
22
  create_umbrella_header(native_target)
@@ -30,7 +30,8 @@ module Pod
30
30
  # cause an App Store rejection because frameworks cannot be
31
31
  # embedded in embedded targets.
32
32
  #
33
- create_embed_frameworks_script if target.includes_frameworks? && !target.requires_host_target?
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?
34
35
  create_bridge_support_file(native_target)
35
36
  create_copy_resources_script if target.includes_resources?
36
37
  create_acknowledgements
@@ -145,8 +146,8 @@ module Pod
145
146
  # Creates a script that embeds the frameworks to the bundle of the client
146
147
  # target.
147
148
  #
148
- # @note We can't use Xcode default copy bundle resource phase, because
149
- # we need to ensure that we only copy the resources, which are
149
+ # @note We can't use Xcode default link libraries phase, because
150
+ # we need to ensure that we only copy the frameworks which are
150
151
  # relevant for the current build configuration.
151
152
  #
152
153
  # @return [void]
@@ -158,6 +159,30 @@ module Pod
158
159
  add_file_to_support_group(path)
159
160
  end
160
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)
173
+ update_changed_file(generator, path)
174
+ 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
+ end
185
+
161
186
  # Generates the acknowledgement files (markdown and plist) for the target.
162
187
  #
163
188
  # @return [void]
@@ -37,6 +37,10 @@ module Pod
37
37
  #
38
38
  attr_reader :add_main
39
39
 
40
+ # @return [Boolean] whether the app host installer should add a launch screen storyboard
41
+ #
42
+ attr_reader :add_launchscreen_storyboard
43
+
40
44
  # @return [Hash] Info.plist entries for the app host
41
45
  #
42
46
  attr_reader :info_plist_entries
@@ -52,7 +56,7 @@ module Pod
52
56
  # @param [Boolean] add_main see #add_main
53
57
  # @param [Hash] info_plist_entries see #info_plist_entries
54
58
  #
55
- def initialize(sandbox, project, platform, subgroup_name, group_name, app_target_label, add_main: true, info_plist_entries: {})
59
+ def initialize(sandbox, project, platform, subgroup_name, group_name, app_target_label, add_main: true, add_launchscreen_storyboard: platform == :ios, info_plist_entries: {})
56
60
  @sandbox = sandbox
57
61
  @project = project
58
62
  @platform = platform
@@ -60,6 +64,7 @@ module Pod
60
64
  @group_name = group_name
61
65
  @app_target_label = app_target_label
62
66
  @add_main = add_main
67
+ @add_launchscreen_storyboard = add_launchscreen_storyboard
63
68
  @info_plist_entries = info_plist_entries
64
69
  target_group = project.pod_group(group_name)
65
70
  @group = target_group[subgroup_name] || target_group.new_group(subgroup_name)
@@ -79,7 +84,7 @@ module Pod
79
84
  end
80
85
 
81
86
  Pod::Generator::AppTargetHelper.add_app_host_main_file(project, app_host_target, platform_name, @group, app_target_label) if add_main
82
- Pod::Generator::AppTargetHelper.add_launchscreen_storyboard(project, app_host_target, @group, deployment_target, app_target_label) if platform == :ios
87
+ Pod::Generator::AppTargetHelper.add_launchscreen_storyboard(project, app_host_target, @group, deployment_target, app_target_label) if add_launchscreen_storyboard
83
88
  create_info_plist_file_with_sandbox(sandbox, app_host_info_plist_path, app_host_target, '1.0.0', platform,
84
89
  :appl, :additional_entries => additional_info_plist_entries)
85
90
  @group.new_file(app_host_info_plist_path)
@@ -1,3 +1,5 @@
1
+ require 'cocoapods/xcode'
2
+
1
3
  module Pod
2
4
  class Installer
3
5
  class Xcode
@@ -56,6 +58,7 @@ module Pod
56
58
 
57
59
  add_files_to_build_phases(native_target, test_native_targets, app_native_targets)
58
60
  validate_targets_contain_sources(test_native_targets + app_native_targets + [native_target])
61
+ validate_xcframeworks_no_mixed_linkage
59
62
 
60
63
  create_xcconfig_file(native_target, resource_bundle_targets)
61
64
  create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets)
@@ -69,7 +72,7 @@ module Pod
69
72
  generator.imports += library_file_accessors.flat_map do |file_accessor|
70
73
  header_dir = if !target.build_as_framework? && dir = file_accessor.spec_consumer.header_dir
71
74
  Pathname.new(dir)
72
- end
75
+ end
73
76
 
74
77
  file_accessor.public_headers.map do |public_header|
75
78
  public_header = if header_mappings_dir(file_accessor)
@@ -148,14 +151,18 @@ module Pod
148
151
  # Removes overrides of the `pod_target_xcconfig` settings from the target's
149
152
  # build configurations.
150
153
  #
151
- # @return [Void]
152
- #
153
- # @param [Target::BuildSettings] build_settings
154
+ # @param [Hash{Symbol => Pod::Target::BuildSettings}] build_settings_by_config the build settings by config
155
+ # of the target.
154
156
  #
155
157
  # @param [PBXNativeTarget] native_target
158
+ # the native target to remove pod target xcconfig overrides from.
159
+ #
160
+ # @return [Void]
156
161
  #
157
- def remove_pod_target_xcconfig_overrides_from_target(build_settings, native_target)
162
+ #
163
+ def remove_pod_target_xcconfig_overrides_from_target(build_settings_by_config, native_target)
158
164
  native_target.build_configurations.each do |configuration|
165
+ build_settings = build_settings_by_config[target.user_build_configurations[configuration.name]]
159
166
  build_settings.merged_pod_target_xcconfigs.each_key do |setting|
160
167
  configuration.build_settings.delete(setting)
161
168
  end
@@ -365,9 +372,10 @@ module Pod
365
372
  configuration.build_settings['CODE_SIGN_IDENTITY'] = '' if target.platform == :osx
366
373
  end
367
374
 
368
- remove_pod_target_xcconfig_overrides_from_target(target.build_settings_for_spec(test_spec), test_native_target)
375
+ remove_pod_target_xcconfig_overrides_from_target(target.test_spec_build_settings_by_config[test_spec.name], test_native_target)
369
376
 
370
377
  # Test native targets also need frameworks and resources to be copied over to their xctest bundle.
378
+ create_test_target_prepare_artifacts_script(test_spec)
371
379
  create_test_target_embed_frameworks_script(test_spec)
372
380
  create_test_target_copy_resources_script(test_spec)
373
381
 
@@ -411,8 +419,11 @@ module Pod
411
419
  app_target_label = target.app_target_label(app_spec)
412
420
  platform = Platform.new(target.platform.symbolic_name, target.deployment_target_for_non_library_spec(app_spec))
413
421
  info_plist_entries = spec_consumer.info_plist
422
+ resources = target.file_accessors.find { |fa| fa.spec == app_spec }.resources
423
+ add_launchscreen_storyboard = resources.none? { |resource| resource.basename.to_s == 'LaunchScreen.storyboard' } && platform.name == :ios
414
424
  app_native_target = AppHostInstaller.new(sandbox, project, platform, subspec_name, spec_name,
415
425
  app_target_label, :add_main => false,
426
+ :add_launchscreen_storyboard => add_launchscreen_storyboard,
416
427
  :info_plist_entries => info_plist_entries).install!
417
428
 
418
429
  app_native_target.product_reference.name = app_target_label
@@ -454,11 +465,11 @@ module Pod
454
465
  end
455
466
  end
456
467
 
457
- remove_pod_target_xcconfig_overrides_from_target(target.build_settings_for_spec(app_spec), app_native_target)
468
+ remove_pod_target_xcconfig_overrides_from_target(target.app_spec_build_settings_by_config[app_spec.name], app_native_target)
458
469
 
459
470
  create_app_target_embed_frameworks_script(app_spec)
460
471
  create_app_target_copy_resources_script(app_spec)
461
- add_resources_to_target(target.file_accessors.find { |fa| fa.spec == app_spec }.resources, app_native_target)
472
+ add_resources_to_target(resources, app_native_target)
462
473
 
463
474
  app_native_target
464
475
  end
@@ -489,7 +500,7 @@ module Pod
489
500
  # @param [Array<Sandbox::FileAccessor>] file_accessors
490
501
  # the file accessors list to generate resource bundles for.
491
502
  #
492
- # @return [Array<PBXNativeTarget>] the resource bundle native targets created.
503
+ # @return [Hash{String=>Array<PBXNativeTarget>}] the resource bundle native targets created.
493
504
  #
494
505
  def add_resources_bundle_targets(file_accessors)
495
506
  file_accessors.each_with_object({}) do |file_accessor, hash|
@@ -548,7 +559,7 @@ module Pod
548
559
  end
549
560
  end
550
561
 
551
- remove_pod_target_xcconfig_overrides_from_target(target.build_settings_for_spec(file_accessor.spec), resource_bundle_target)
562
+ remove_pod_target_xcconfig_overrides_from_target(target.build_settings_by_config_for_spec(file_accessor.spec), resource_bundle_target)
552
563
 
553
564
  resource_bundle_target
554
565
  end
@@ -566,12 +577,14 @@ module Pod
566
577
  # @return [void]
567
578
  #
568
579
  def create_xcconfig_file(native_target, resource_bundle_targets)
569
- path = target.xcconfig_path
570
- update_changed_file(target.build_settings, path)
571
- xcconfig_file_ref = add_file_to_support_group(path)
580
+ target.user_config_names_by_config_type.each do |config, names|
581
+ path = target.xcconfig_path(config)
582
+ update_changed_file(target.build_settings[config], path)
583
+ xcconfig_file_ref = add_file_to_support_group(path)
572
584
 
573
- # also apply the private config to resource bundle targets.
574
- apply_xcconfig_file_ref_to_targets([native_target] + resource_bundle_targets, xcconfig_file_ref)
585
+ # also apply the private config to resource bundle targets.
586
+ apply_xcconfig_file_ref_to_targets([native_target] + resource_bundle_targets, xcconfig_file_ref, names)
587
+ end
575
588
  end
576
589
 
577
590
  # Generates the contents of the xcconfig file used for each test target type and saves it to disk.
@@ -588,19 +601,22 @@ module Pod
588
601
  target.test_specs.each do |test_spec|
589
602
  spec_consumer = test_spec.consumer(target.platform)
590
603
  test_type = spec_consumer.test_type
591
- path = target.xcconfig_path("#{test_type.capitalize}-#{target.subspec_label(test_spec)}")
592
- test_spec_build_settings = target.build_settings_for_spec(test_spec)
593
- update_changed_file(test_spec_build_settings, path)
594
- test_xcconfig_file_ref = add_file_to_support_group(path)
595
-
596
604
  test_native_target = test_native_target_from_spec(spec_consumer.spec, test_native_targets)
605
+
606
+ target.user_config_names_by_config_type.each do |config, names|
607
+ path = target.xcconfig_path("#{test_type.capitalize}-#{target.subspec_label(test_spec)}.#{config}")
608
+ test_spec_build_settings = target.build_settings_for_spec(test_spec, :configuration => config)
609
+ update_changed_file(test_spec_build_settings, path)
610
+ test_xcconfig_file_ref = add_file_to_support_group(path)
611
+
612
+ # also apply the private config to resource bundle test targets related to this test spec.
613
+ scoped_test_resource_bundle_targets = test_resource_bundle_targets[test_spec.name]
614
+ apply_xcconfig_file_ref_to_targets([test_native_target] + scoped_test_resource_bundle_targets, test_xcconfig_file_ref, names)
615
+ end
616
+
597
617
  test_native_target.build_configurations.each do |test_native_target_bc|
598
618
  test_target_swift_debug_hack(test_spec, test_native_target_bc)
599
619
  end
600
-
601
- # also apply the private config to resource bundle test targets related to this test spec.
602
- scoped_test_resource_bundle_targets = test_resource_bundle_targets[test_spec.name]
603
- apply_xcconfig_file_ref_to_targets([test_native_target] + scoped_test_resource_bundle_targets, test_xcconfig_file_ref)
604
620
  end
605
621
  end
606
622
 
@@ -613,12 +629,11 @@ module Pod
613
629
  #
614
630
  def create_test_target_copy_resources_script(test_spec)
615
631
  path = target.copy_resources_script_path_for_spec(test_spec)
616
- pod_targets = target.dependent_targets_for_test_spec(test_spec)
617
632
  host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt|
618
633
  pt.specs.map(&:name)
619
634
  end.uniq
620
- resource_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config|
621
- resources_by_config[config] = pod_targets.flat_map do |pod_target|
635
+ resource_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), resources_by_config|
636
+ resources_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
622
637
  spec_paths_to_include = pod_target.library_specs.map(&:name)
623
638
  spec_paths_to_include -= host_target_spec_names
624
639
  spec_paths_to_include << test_spec.name if pod_target == target
@@ -632,6 +647,33 @@ module Pod
632
647
  end
633
648
  end
634
649
 
650
+ # Creates a script that prepares artifacts for the test target.
651
+ #
652
+ # @param [Specification] test_spec
653
+ # The test spec to create the script for.
654
+ #
655
+ # @return [void]
656
+ #
657
+ def create_test_target_prepare_artifacts_script(test_spec)
658
+ path = target.prepare_artifacts_script_path_for_spec(test_spec)
659
+ host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt|
660
+ pt.specs.map(&:name)
661
+ end.uniq
662
+ frameworks_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
663
+ paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
664
+ spec_paths_to_include = pod_target.library_specs.map(&:name)
665
+ spec_paths_to_include -= host_target_spec_names
666
+ spec_paths_to_include << test_spec.name if pod_target == target
667
+ pod_target.xcframeworks.values_at(*spec_paths_to_include).flatten.compact.uniq
668
+ end
669
+ end
670
+ unless frameworks_by_config.each_value.all?(&:empty?)
671
+ generator = Generator::PrepareArtifactsScript.new(frameworks_by_config, target.sandbox.root, target.platform)
672
+ update_changed_file(generator, path)
673
+ add_file_to_support_group(path)
674
+ end
675
+ end
676
+
635
677
  # Creates a script that embeds the frameworks to the bundle of the test target.
636
678
  #
637
679
  # @param [Specification] test_spec
@@ -641,12 +683,11 @@ module Pod
641
683
  #
642
684
  def create_test_target_embed_frameworks_script(test_spec)
643
685
  path = target.embed_frameworks_script_path_for_spec(test_spec)
644
- pod_targets = target.dependent_targets_for_test_spec(test_spec)
645
686
  host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt|
646
687
  pt.specs.map(&:name)
647
688
  end.uniq
648
- framework_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, paths_by_config|
649
- paths_by_config[config] = pod_targets.flat_map do |pod_target|
689
+ framework_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
690
+ paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target|
650
691
  spec_paths_to_include = pod_target.library_specs.map(&:name)
651
692
  spec_paths_to_include -= host_target_spec_names
652
693
  spec_paths_to_include << test_spec.name if pod_target == target
@@ -673,15 +714,18 @@ module Pod
673
714
  def create_app_xcconfig_files(app_native_targets, app_resource_bundle_targets)
674
715
  target.app_specs.each do |app_spec|
675
716
  spec_consumer = app_spec.consumer(target.platform)
676
- path = target.xcconfig_path(target.subspec_label(app_spec))
677
- update_changed_file(target.build_settings_for_spec(app_spec), path)
678
- app_xcconfig_file_ref = add_file_to_support_group(path)
679
-
680
717
  app_native_target = app_native_target_from_spec(spec_consumer.spec, app_native_targets)
681
718
 
682
- # also apply the private config to resource bundle app targets related to this app spec.
683
- scoped_app_resource_bundle_targets = app_resource_bundle_targets[app_spec.name]
684
- apply_xcconfig_file_ref_to_targets([app_native_target] + scoped_app_resource_bundle_targets, app_xcconfig_file_ref)
719
+ target.user_config_names_by_config_type.each do |config, names|
720
+ path = target.xcconfig_path("#{target.subspec_label(app_spec)}.#{config}")
721
+ app_spec_build_settings = target.build_settings_for_spec(app_spec, :configuration => config)
722
+ update_changed_file(app_spec_build_settings, path)
723
+ app_xcconfig_file_ref = add_file_to_support_group(path)
724
+
725
+ # also apply the private config to resource bundle app targets related to this app spec.
726
+ scoped_app_resource_bundle_targets = app_resource_bundle_targets[app_spec.name]
727
+ apply_xcconfig_file_ref_to_targets([app_native_target] + scoped_app_resource_bundle_targets, app_xcconfig_file_ref, names)
728
+ end
685
729
  end
686
730
  end
687
731
 
@@ -694,9 +738,9 @@ module Pod
694
738
  #
695
739
  def create_app_target_copy_resources_script(app_spec)
696
740
  path = target.copy_resources_script_path_for_spec(app_spec)
697
- pod_targets = target.dependent_targets_for_app_spec(app_spec)
698
- resource_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config|
699
- resources_by_config[config] = pod_targets.flat_map do |pod_target|
741
+ resource_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), resources_by_config|
742
+ pod_targets = target.dependent_targets_for_app_spec(app_spec, :configuration => config)
743
+ resources_by_config[config_name] = pod_targets.flat_map do |pod_target|
700
744
  spec_paths_to_include = pod_target.library_specs.map(&:name)
701
745
  spec_paths_to_include << app_spec.name if pod_target == target
702
746
  pod_target.resource_paths.values_at(*spec_paths_to_include).flatten.compact
@@ -718,9 +762,9 @@ module Pod
718
762
  #
719
763
  def create_app_target_embed_frameworks_script(app_spec)
720
764
  path = target.embed_frameworks_script_path_for_spec(app_spec)
721
- pod_targets = target.dependent_targets_for_app_spec(app_spec)
722
- framework_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, paths_by_config|
723
- paths_by_config[config] = pod_targets.flat_map do |pod_target|
765
+ framework_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config|
766
+ pod_targets = target.dependent_targets_for_app_spec(app_spec, :configuration => config)
767
+ paths_by_config[config_name] = pod_targets.flat_map do |pod_target|
724
768
  spec_paths_to_include = pod_target.library_specs.map(&:name)
725
769
  spec_paths_to_include << app_spec.name if pod_target == target
726
770
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
@@ -841,9 +885,10 @@ module Pod
841
885
  flags * ' '
842
886
  end
843
887
 
844
- def apply_xcconfig_file_ref_to_targets(targets, xcconfig_file_ref)
888
+ def apply_xcconfig_file_ref_to_targets(targets, xcconfig_file_ref, configurations)
845
889
  targets.each do |config_target|
846
890
  config_target.build_configurations.each do |configuration|
891
+ next unless configurations.include?(configuration.name)
847
892
  configuration.base_configuration_reference = xcconfig_file_ref
848
893
  end
849
894
  end
@@ -928,16 +973,20 @@ module Pod
928
973
  'Project'
929
974
  end
930
975
 
931
- if target.build_as_framework? && any_header_mapping_dirs? && acl != 'Project'
976
+ if target.build_as_framework? && !header_mappings_dir(file_accessor).nil? && acl != 'Project'
932
977
  relative_path = if mapping_dir = header_mappings_dir(file_accessor)
933
978
  file_ref.real_path.relative_path_from(mapping_dir)
934
979
  else
935
980
  file_ref.real_path.relative_path_from(file_accessor.path_list.root)
936
981
  end
982
+ compile_build_phase_index = native_target.build_phases.index do |bp|
983
+ bp.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase)
984
+ end
937
985
  sub_dir = relative_path.dirname
938
986
  copy_phase_name = "Copy #{sub_dir} #{acl} Headers"
939
987
  copy_phase = native_target.copy_files_build_phases.find { |bp| bp.name == copy_phase_name } ||
940
988
  native_target.new_copy_files_build_phase(copy_phase_name)
989
+ native_target.build_phases.move(copy_phase, compile_build_phase_index - 1) unless compile_build_phase_index.nil?
941
990
  copy_phase.symbol_dst_subfolder_spec = :products_directory
942
991
  copy_phase.dst_path = "$(#{acl.upcase}_HEADERS_FOLDER_PATH)/#{sub_dir}"
943
992
  copy_phase.add_file_reference(file_ref, true)
@@ -1035,6 +1084,18 @@ module Pod
1035
1084
  end
1036
1085
  end
1037
1086
 
1087
+ # Raises if a vendored xcframework contains frameworks of mixed linkage
1088
+ #
1089
+ def validate_xcframeworks_no_mixed_linkage
1090
+ target.xcframeworks.each_value do |xcframeworks|
1091
+ xcframeworks.each do |xcframework|
1092
+ dynamic_slices, static_slices = xcframework.slices.partition { |slice| Pod::Xcode::LinkageAnalyzer.dynamic_binary?(slice.path) }
1093
+ if !dynamic_slices.empty? && !static_slices.empty?
1094
+ raise Informative, "Unable to install vendored xcframework `#{xcframework.name}` for Pod `#{target.label}`, because it contains both static and dynamic frameworks."
1095
+ end
1096
+ end
1097
+ end
1098
+ end
1038
1099
  #-----------------------------------------------------------------------#
1039
1100
  end
1040
1101
  end