cocoapods 1.2.1 → 1.3.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.
@@ -71,6 +71,7 @@ module Pod
71
71
  @lockfile = lockfile
72
72
 
73
73
  @use_default_plugins = true
74
+ @has_dependencies = true
74
75
  end
75
76
 
76
77
  # @return [Hash, Boolean, nil] Pods that have been requested to be
@@ -80,6 +81,11 @@ module Pod
80
81
  #
81
82
  attr_accessor :update
82
83
 
84
+ # @return [Boolean] Whether it has dependencies. Defaults to true.
85
+ #
86
+ attr_accessor :has_dependencies
87
+ alias_method :has_dependencies?, :has_dependencies
88
+
83
89
  # @return [Boolean] Whether the spec repos should be updated.
84
90
  #
85
91
  attr_accessor :repo_update
@@ -109,9 +115,7 @@ module Pod
109
115
  prepare
110
116
  resolve_dependencies
111
117
  download_dependencies
112
- verify_no_duplicate_framework_and_library_names
113
- verify_no_static_framework_transitive_dependencies
114
- verify_framework_usage
118
+ validate_targets
115
119
  generate_pods_project
116
120
  if installation_options.integrate_targets?
117
121
  integrate_user_project
@@ -214,7 +218,9 @@ module Pod
214
218
  # generated as result of the analyzer.
215
219
  #
216
220
  def pod_targets
217
- aggregate_targets.map(&:pod_targets).flatten.uniq
221
+ aggregate_target_pod_targets = aggregate_targets.map(&:pod_targets).flatten
222
+ test_dependent_targets = aggregate_target_pod_targets.map(&:test_dependent_targets).flatten
223
+ (aggregate_target_pod_targets + test_dependent_targets).uniq
218
224
  end
219
225
 
220
226
  # @return [Array<Specification>] The specifications that where installed.
@@ -240,6 +246,7 @@ module Pod
240
246
  def create_analyzer
241
247
  Analyzer.new(sandbox, podfile, lockfile).tap do |analyzer|
242
248
  analyzer.installation_options = installation_options
249
+ analyzer.has_dependencies = has_dependencies?
243
250
  end
244
251
  end
245
252
 
@@ -286,19 +293,11 @@ module Pod
286
293
  end
287
294
  end
288
295
 
289
- # TODO: the file accessor should be initialized by the sandbox as they
290
- # created by the Pod source installer as well.
296
+ # @return [void] In this step we create the file accessors for the pod
297
+ # targets.
291
298
  #
292
299
  def create_file_accessors
293
- pod_targets.each do |pod_target|
294
- pod_root = sandbox.pod_dir(pod_target.root_spec.name)
295
- path_list = Sandbox::PathList.new(pod_root)
296
- file_accessors = pod_target.specs.map do |spec|
297
- Sandbox::FileAccessor.new(path_list, spec.consumer(pod_target.platform))
298
- end
299
- pod_target.file_accessors ||= []
300
- pod_target.file_accessors.concat(file_accessors)
301
- end
300
+ sandbox.create_file_accessors(pod_targets)
302
301
  end
303
302
 
304
303
  # Downloads, installs the documentation and cleans the sources of the Pods
@@ -393,67 +392,9 @@ module Pod
393
392
  end
394
393
  end
395
394
 
396
- def verify_no_duplicate_framework_and_library_names
397
- aggregate_targets.each do |aggregate_target|
398
- aggregate_target.user_build_configurations.keys.each do |config|
399
- pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
400
- file_accessors = pod_targets.flat_map(&:file_accessors)
401
-
402
- frameworks = file_accessors.flat_map(&:vendored_frameworks).uniq.map(&:basename)
403
- frameworks += pod_targets.select { |pt| pt.should_build? && pt.requires_frameworks? }.map(&:product_module_name)
404
- verify_no_duplicate_names(frameworks, aggregate_target.label, 'frameworks')
405
-
406
- libraries = file_accessors.flat_map(&:vendored_libraries).uniq.map(&:basename)
407
- libraries += pod_targets.select { |pt| pt.should_build? && !pt.requires_frameworks? }.map(&:product_name)
408
- verify_no_duplicate_names(libraries, aggregate_target.label, 'libraries')
409
- end
410
- end
411
- end
412
-
413
- def verify_no_duplicate_names(names, label, type)
414
- duplicates = names.map { |n| n.to_s.downcase }.group_by { |f| f }.select { |_, v| v.size > 1 }.keys
415
-
416
- unless duplicates.empty?
417
- raise Informative, "The '#{label}' target has " \
418
- "#{type} with conflicting names: #{duplicates.to_sentence}."
419
- end
420
- end
421
-
422
- def verify_no_static_framework_transitive_dependencies
423
- aggregate_targets.each do |aggregate_target|
424
- next unless aggregate_target.requires_frameworks?
425
-
426
- aggregate_target.user_build_configurations.keys.each do |config|
427
- pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
428
-
429
- dependencies = pod_targets.select(&:should_build?).flat_map(&:dependencies)
430
- dependended_upon_targets = pod_targets.select { |t| dependencies.include?(t.pod_name) && !t.should_build? }
431
-
432
- static_libs = dependended_upon_targets.flat_map(&:file_accessors).flat_map(&:vendored_static_artifacts)
433
- unless static_libs.empty?
434
- raise Informative, "The '#{aggregate_target.label}' target has " \
435
- "transitive dependencies that include static binaries: (#{static_libs.to_sentence})"
436
- end
437
- end
438
- end
439
- end
440
-
441
- def verify_framework_usage
442
- aggregate_targets.each do |aggregate_target|
443
- next if aggregate_target.requires_frameworks?
444
-
445
- aggregate_target.user_build_configurations.keys.each do |config|
446
- pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
447
-
448
- swift_pods = pod_targets.select(&:uses_swift?)
449
- unless swift_pods.empty?
450
- raise Informative, 'Pods written in Swift can only be integrated as frameworks; ' \
451
- 'add `use_frameworks!` to your Podfile or target to opt into using it. ' \
452
- "The Swift #{swift_pods.size == 1 ? 'Pod being used is' : 'Pods being used are'}: " +
453
- swift_pods.map(&:name).to_sentence
454
- end
455
- end
456
- end
395
+ def validate_targets
396
+ validator = Xcode::TargetValidator.new(aggregate_targets, pod_targets)
397
+ validator.validate!
457
398
  end
458
399
 
459
400
  # Runs the registered callbacks for the plugins pre install hooks.
@@ -45,6 +45,7 @@ module Pod
45
45
 
46
46
  @update = false
47
47
  @allow_pre_downloads = true
48
+ @has_dependencies = true
48
49
  end
49
50
 
50
51
  # Performs the analysis.
@@ -152,6 +153,15 @@ module Pod
152
153
  attr_accessor :allow_pre_downloads
153
154
  alias_method :allow_pre_downloads?, :allow_pre_downloads
154
155
 
156
+ # @return [Bool] Whether the analysis has dependencies and thus
157
+ # sources must be configured.
158
+ #
159
+ # @note This is used by the `pod lib lint` command to prevent
160
+ # update of specs when not needed.
161
+ #
162
+ attr_accessor :has_dependencies
163
+ alias_method :has_dependencies?, :has_dependencies
164
+
155
165
  #-----------------------------------------------------------------------#
156
166
 
157
167
  private
@@ -313,12 +323,12 @@ module Pod
313
323
  end
314
324
 
315
325
  unless embedded_targets_missing_hosts.empty?
316
- embedded_targets_missing_hosts_product_types = embedded_targets_missing_hosts.map(&:user_targets).flatten.map(&:symbol_type).uniq
326
+ embedded_targets_missing_hosts_product_types = Set.new embedded_targets_missing_hosts.map(&:user_targets).flatten.map(&:symbol_type)
317
327
  # If the targets missing hosts are only frameworks, then this is likely
318
328
  # a project for doing framework development. In that case, just warn that
319
329
  # the frameworks that these targets depend on won't be integrated anywhere
320
- if embedded_targets_missing_hosts_product_types == [:framework]
321
- UI.warn 'The Podfile contains framework targets, for which the Podfile does not contain host targets (targets which embed the framework).' \
330
+ if embedded_targets_missing_hosts_product_types.subset?(Set.new([:framework, :static_library]))
331
+ UI.warn 'The Podfile contains framework or static library targets, for which the Podfile does not contain host targets (targets which embed the framework).' \
322
332
  "\n" \
323
333
  'If this project is for doing framework development, you can ignore this message. Otherwise, add a target to the Podfile that embeds these frameworks to make this message go away (e.g. a test target).'
324
334
  else
@@ -357,7 +367,6 @@ module Pod
357
367
  #
358
368
  def generate_targets
359
369
  specs_by_target = result.specs_by_target.reject { |td, _| td.abstract? }
360
- check_pod_target_swift_versions(specs_by_target)
361
370
  pod_targets = generate_pod_targets(specs_by_target)
362
371
  aggregate_targets = specs_by_target.keys.map do |target_definition|
363
372
  generate_target(target_definition, pod_targets)
@@ -419,43 +428,30 @@ module Pod
419
428
  end
420
429
 
421
430
  target.pod_targets = pod_targets.select do |pod_target|
422
- pod_target.target_definitions.include?(target_definition)
431
+ target_definition_included = pod_target.target_definitions.include?(target_definition)
432
+ explicitly_defined_in_target_definition = target_definition.non_inherited_dependencies.map(&:name).include?(pod_target.name)
433
+ test_pod_target_only = pod_target_test_only?(pod_target, pod_targets)
434
+ target_definition_included && (explicitly_defined_in_target_definition || !test_pod_target_only)
423
435
  end
424
436
 
425
437
  target
426
438
  end
427
439
 
428
- # Verify that targets using a pod have the same swift version
440
+ # Returns true if a pod target is only used by other pod targets as a test dependency and therefore should
441
+ # not be included as part of the aggregate target.
429
442
  #
430
- # @param [Hash{Podfile::TargetDefinition => Array<Specification>}] specs_by_target
431
- # the resolved specifications grouped by target.
443
+ # @param [PodTarget] pod_target
444
+ # the pod target being queried
432
445
  #
433
- # @note raises Informative if targets using a pod do not have
434
- # the same swift version
446
+ # @param [Array<PodTarget>] pod_targets
447
+ # the array of pod targets to check against
435
448
  #
436
- def check_pod_target_swift_versions(specs_by_target)
437
- targets_by_spec = {}
438
- specs_by_target.each do |target, specs|
439
- specs.each do |spec|
440
- (targets_by_spec[spec] ||= []) << target
441
- end
442
- end
443
-
444
- error_message_for_target = lambda do |target|
445
- "#{target.name} (Swift #{target.swift_version})"
446
- end
447
-
448
- error_messages = targets_by_spec.map do |spec, targets|
449
- swift_targets = targets.reject { |target| target.swift_version.blank? }
450
- next if swift_targets.empty? || swift_targets.uniq(&:swift_version).count == 1
451
- target_errors = swift_targets.map(&error_message_for_target).join(', ')
452
- "- #{spec.name} required by #{target_errors}"
453
- end.compact
454
-
455
- unless error_messages.empty?
456
- raise Informative, 'The following pods are integrated into targets ' \
457
- "that do not have the same Swift version:\n\n#{error_messages.join("\n")}"
458
- end
449
+ # @return [Boolean] if the pod target is only referenced from test dependencies.
450
+ #
451
+ def pod_target_test_only?(pod_target, pod_targets)
452
+ source = pod_targets.any? { |pt| pt.dependent_targets.map(&:name).include?(pod_target.name) }
453
+ test = pod_targets.any? { |pt| pt.test_dependent_targets.map(&:name).include?(pod_target.name) }
454
+ !source && test
459
455
  end
460
456
 
461
457
  # Setup the pod targets for an aggregate target. Deduplicates resulting
@@ -492,15 +488,10 @@ module Pod
492
488
  hash[name] = values.sort_by { |pt| pt.specs.count }
493
489
  end
494
490
  pod_targets.each do |target|
495
- dependencies = transitive_dependencies_for_specs(target.specs, target.platform, all_specs).group_by(&:root)
496
- target.dependent_targets = dependencies.map do |root_spec, deps|
497
- pod_targets_by_name[root_spec.name].find do |t|
498
- next false if t.platform.symbolic_name != target.platform.symbolic_name ||
499
- t.requires_frameworks? != target.requires_frameworks?
500
- spec_names = t.specs.map(&:name)
501
- deps.all? { |dep| spec_names.include?(dep.name) }
502
- end
503
- end
491
+ dependencies = transitive_dependencies_for_specs(target.specs.reject(&:test_specification?), target.platform, all_specs).group_by(&:root)
492
+ test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, all_specs).group_by(&:root)
493
+ target.dependent_targets = filter_dependencies(dependencies, pod_targets_by_name, target)
494
+ target.test_dependent_targets = filter_dependencies(test_dependencies, pod_targets_by_name, target)
504
495
  end
505
496
  else
506
497
  dedupe_cache = {}
@@ -512,12 +503,25 @@ module Pod
512
503
 
513
504
  pod_targets.each do |target|
514
505
  dependencies = transitive_dependencies_for_specs(target.specs, target.platform, specs).group_by(&:root)
506
+ test_dependencies = transitive_dependencies_for_specs(target.specs.select(&:test_specification?), target.platform, all_specs).group_by(&:root)
515
507
  target.dependent_targets = pod_targets.reject { |t| dependencies[t.root_spec].nil? }
508
+ target.test_dependent_targets = pod_targets.reject { |t| test_dependencies[t.root_spec].nil? }
516
509
  end
517
510
  end
518
511
  end
519
512
  end
520
513
 
514
+ def filter_dependencies(dependencies, pod_targets_by_name, target)
515
+ dependencies.map do |root_spec, deps|
516
+ pod_targets_by_name[root_spec.name].find do |t|
517
+ next false if t.platform.symbolic_name != target.platform.symbolic_name ||
518
+ t.requires_frameworks? != target.requires_frameworks?
519
+ spec_names = t.specs.map(&:name)
520
+ deps.all? { |dep| spec_names.include?(dep.name) }
521
+ end
522
+ end
523
+ end
524
+
521
525
  # Returns the specs upon which the given specs _transitively_ depend.
522
526
  #
523
527
  # @note: This is implemented in the analyzer, because we don't have to
@@ -819,11 +823,11 @@ module Pod
819
823
 
820
824
  # Add any sources specified using the :source flag on individual dependencies.
821
825
  dependency_sources = podfile.dependencies.map(&:podspec_repo).compact
822
-
823
826
  all_dependencies_have_sources = dependency_sources.count == podfile.dependencies.count
827
+
824
828
  if all_dependencies_have_sources
825
829
  sources = dependency_sources
826
- elsif sources.empty?
830
+ elsif has_dependencies? && sources.empty?
827
831
  sources = ['https://github.com/CocoaPods/Specs.git']
828
832
  else
829
833
  sources += dependency_sources
@@ -2,6 +2,7 @@ module Pod
2
2
  class Installer
3
3
  class Xcode
4
4
  autoload :PodsProjectGenerator, 'cocoapods/installer/xcode/pods_project_generator'
5
+ autoload :TargetValidator, 'cocoapods/installer/xcode/target_validator'
5
6
  end
6
7
  end
7
8
  end
@@ -86,6 +86,11 @@ module Pod
86
86
  development_pod_targets.select(&:should_build?).each do |pod_target|
87
87
  next unless share_scheme_for_development_pod?(pod_target.pod_name)
88
88
  Xcodeproj::XCScheme.share_scheme(project.path, pod_target.label)
89
+ if pod_target.contains_test_specifications?
90
+ pod_target.supported_test_types.each do |test_type|
91
+ Xcodeproj::XCScheme.share_scheme(project.path, pod_target.test_target_label(test_type))
92
+ end
93
+ end
89
94
  end
90
95
  end
91
96
 
@@ -203,16 +208,10 @@ module Pod
203
208
  aggregate_target.native_target.add_dependency(pod_target.native_target)
204
209
  configure_app_extension_api_only_for_target(pod_target) if is_app_extension
205
210
 
206
- pod_target.dependent_targets.each do |pod_dependency_target|
207
- next unless pod_dependency_target.should_build?
208
- pod_target.native_target.add_dependency(pod_dependency_target.native_target)
209
- configure_app_extension_api_only_for_target(pod_dependency_target) if is_app_extension
211
+ add_dependent_targets_to_native_target(pod_target.dependent_targets, pod_target.native_target, is_app_extension, pod_target.requires_frameworks?, frameworks_group)
210
212
 
211
- if pod_target.requires_frameworks?
212
- product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } ||
213
- frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type)
214
- pod_target.native_target.frameworks_build_phase.add_file_reference(product_ref, true)
215
- end
213
+ pod_target.test_native_targets.each do |test_native_target|
214
+ add_dependent_targets_to_native_target([pod_target, *pod_target.test_dependent_targets], test_native_target, false, pod_target.requires_frameworks?, frameworks_group)
216
215
  end
217
216
  end
218
217
  end
@@ -251,6 +250,20 @@ module Pod
251
250
 
252
251
  private
253
252
 
253
+ def add_dependent_targets_to_native_target(dependent_targets, native_target, is_app_extension, requires_frameworks, frameworks_group)
254
+ dependent_targets.each do |pod_dependency_target|
255
+ next unless pod_dependency_target.should_build?
256
+ native_target.add_dependency(pod_dependency_target.native_target)
257
+ configure_app_extension_api_only_for_target(pod_dependency_target) if is_app_extension
258
+
259
+ if requires_frameworks
260
+ product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } ||
261
+ frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type)
262
+ native_target.frameworks_build_phase.add_file_reference(product_ref, true)
263
+ end
264
+ end
265
+ end
266
+
254
267
  # Sets the APPLICATION_EXTENSION_API_ONLY build setting to YES for all
255
268
  # configurations of the given target
256
269
  #
@@ -158,18 +158,24 @@ module Pod
158
158
  #
159
159
  def create_embed_frameworks_script
160
160
  path = target.embed_frameworks_script_path
161
- frameworks_by_config = {}
161
+ frameworks_and_dsyms_by_config = {}
162
162
  target.user_build_configurations.keys.each do |config|
163
163
  relevant_pod_targets = target.pod_targets.select do |pod_target|
164
164
  pod_target.include_in_build_config?(target_definition, config)
165
165
  end
166
- frameworks_by_config[config] = relevant_pod_targets.flat_map do |pod_target|
167
- frameworks = pod_target.file_accessors.flat_map(&:vendored_dynamic_artifacts).map { |fw| "${PODS_ROOT}/#{fw.relative_path_from(sandbox.root)}" }
168
- frameworks << pod_target.build_product_path('$BUILT_PRODUCTS_DIR') if pod_target.should_build? && pod_target.requires_frameworks?
166
+ frameworks_and_dsyms_by_config[config] = relevant_pod_targets.flat_map do |pod_target|
167
+ frameworks = pod_target.file_accessors.flat_map(&:vendored_dynamic_artifacts).map do |fw|
168
+ path_to_framework = "${PODS_ROOT}/#{fw.relative_path_from(sandbox.root)}"
169
+ # Until this can be configured, assume the dSYM file uses the file name as the framework.
170
+ # See https://github.com/CocoaPods/CocoaPods/issues/1698
171
+ { :framework => path_to_framework, :dSYM => "#{path_to_framework}.dSYM" }
172
+ end
173
+ # For non vendored frameworks Xcode will generate the dSYM and copy it instead.
174
+ frameworks << { :framework => pod_target.build_product_path('$BUILT_PRODUCTS_DIR'), :dSYM => nil } if pod_target.should_build? && pod_target.requires_frameworks?
169
175
  frameworks
170
176
  end
171
177
  end
172
- generator = Generator::EmbedFrameworksScript.new(frameworks_by_config)
178
+ generator = Generator::EmbedFrameworksScript.new(frameworks_and_dsyms_by_config)
173
179
  generator.save_as(path)
174
180
  add_file_to_support_group(path)
175
181
  end
@@ -18,20 +18,24 @@ module Pod
18
18
 
19
19
  UI.message "- Installing target `#{target.name}` #{target.platform}" do
20
20
  add_target
21
+ add_test_targets if target.contains_test_specifications?
21
22
  create_support_files_dir
22
23
  add_resources_bundle_targets
23
24
  add_files_to_build_phases
24
25
  create_xcconfig_file
26
+ create_test_xcconfig_files if target.contains_test_specifications?
25
27
  if target.requires_frameworks?
26
28
  create_info_plist_file
27
29
  create_module_map
28
30
  create_umbrella_header do |generator|
31
+ file_accessors = target.file_accessors
32
+ file_accessors = file_accessors.reject { |f| f.spec.test_specification? } if target.contains_test_specifications?
29
33
  generator.imports += if header_mappings_dir
30
- target.file_accessors.flat_map(&:public_headers).map do |pathname|
34
+ file_accessors.flat_map(&:public_headers).map do |pathname|
31
35
  pathname.relative_path_from(header_mappings_dir)
32
36
  end
33
37
  else
34
- target.file_accessors.flat_map(&:public_headers).map(&:basename)
38
+ file_accessors.flat_map(&:public_headers).map(&:basename)
35
39
  end
36
40
  end
37
41
  create_build_phase_to_symlink_header_folders
@@ -59,6 +63,8 @@ module Pod
59
63
  settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'] = ''
60
64
  settings['CODE_SIGN_IDENTITY[sdk=watchos*]'] = ''
61
65
 
66
+ settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = '$(inherited) '
67
+
62
68
  if target.swift_version
63
69
  settings['SWIFT_VERSION'] = target.swift_version
64
70
  end
@@ -128,6 +134,7 @@ module Pod
128
134
  target.file_accessors.each do |file_accessor|
129
135
  consumer = file_accessor.spec_consumer
130
136
 
137
+ native_target = target.native_target_for_spec(consumer.spec)
131
138
  headers = file_accessor.headers
132
139
  public_headers = file_accessor.public_headers
133
140
  private_headers = file_accessor.private_headers
@@ -145,7 +152,7 @@ module Pod
145
152
 
146
153
  header_file_refs = project_file_references_array(headers, 'header')
147
154
  native_target.add_file_references(header_file_refs) do |build_file|
148
- add_header(build_file, public_headers, private_headers)
155
+ add_header(build_file, public_headers, private_headers, native_target)
149
156
  end
150
157
 
151
158
  other_file_refs = other_source_files.map { |sf| project.reference_for_path(sf) }
@@ -160,6 +167,39 @@ module Pod
160
167
  end
161
168
  end
162
169
 
170
+ # Adds the test targets for the library to the Pods project with the
171
+ # appropriate build configurations.
172
+ #
173
+ # @return [void]
174
+ #
175
+ def add_test_targets
176
+ target.supported_test_types.each do |test_type|
177
+ product_type = target.product_type_for_test_type(test_type)
178
+ name = target.test_target_label(test_type)
179
+ platform = target.platform.name
180
+ language = target.uses_swift? ? :swift : :objc
181
+ native_test_target = project.new_target(product_type, name, platform, deployment_target, nil, language)
182
+ native_test_target.product_reference.name = name
183
+
184
+ target.user_build_configurations.each do |bc_name, type|
185
+ native_test_target.add_build_configuration(bc_name, type)
186
+ end
187
+
188
+ native_test_target.build_configurations.each do |configuration|
189
+ configuration.build_settings.merge!(custom_build_settings)
190
+ # target_installer will automatically add an empty `OTHER_LDFLAGS`. For test
191
+ # targets those are set via a test xcconfig file instead.
192
+ configuration.build_settings.delete('OTHER_LDFLAGS')
193
+ # target_installer will automatically set the product name to the module name if the target
194
+ # requires frameworks. For tests we always use the test target name as the product name
195
+ # irrelevant to whether we use frameworks or not.
196
+ configuration.build_settings['PRODUCT_NAME'] = name
197
+ end
198
+
199
+ target.test_native_targets << native_test_target
200
+ end
201
+ end
202
+
163
203
  # Adds the resources of the Pods to the Pods project.
164
204
  #
165
205
  # @note The source files are grouped by Pod and in turn by subspec
@@ -184,6 +224,7 @@ module Pod
184
224
  bundle_target.add_resources(resource_phase_refs + compile_phase_refs)
185
225
  end
186
226
 
227
+ native_target = target.native_target_for_spec(file_accessor.spec_consumer.spec)
187
228
  target.user_build_configurations.each do |bc_name, type|
188
229
  bundle_target.add_build_configuration(bc_name, type)
189
230
  end
@@ -219,7 +260,7 @@ module Pod
219
260
  :watchos => '1,2' # The device family for watchOS is 4, but Xcode creates watchkit-compatible bundles as 1,2
220
261
  }
221
262
 
222
- if family = device_family_by_platform[target.platform.name]
263
+ if (family = device_family_by_platform[target.platform.name])
223
264
  c.build_settings['TARGETED_DEVICE_FAMILY'] = family
224
265
  end
225
266
  end
@@ -249,6 +290,38 @@ module Pod
249
290
  end
250
291
  end
251
292
 
293
+ # Generates the contents of the xcconfig file used for each test target type and saves it to disk.
294
+ #
295
+ # @return [void]
296
+ #
297
+ def create_test_xcconfig_files
298
+ target.supported_test_types.each do |test_type|
299
+ path = target.xcconfig_path(test_type.to_s)
300
+ xcconfig_gen = Generator::XCConfig::PodXCConfig.new(target, true)
301
+ xcconfig_gen.save_as(path)
302
+ xcconfig_file_ref = add_file_to_support_group(path)
303
+
304
+ target.test_native_targets.each do |test_target|
305
+ test_target.build_configurations.each do |test_target_bc|
306
+ test_target_swift_debug_hack(test_target_bc)
307
+ test_target_bc.base_configuration_reference = xcconfig_file_ref
308
+ end
309
+ end
310
+ end
311
+ end
312
+
313
+ # Manually add `libswiftSwiftOnoneSupport.dylib` as it seems there is an issue with tests that do not include it for Debug configurations.
314
+ # Possibly related to Swift module optimization.
315
+ #
316
+ # @return [void]
317
+ #
318
+ def test_target_swift_debug_hack(test_target_bc)
319
+ return unless test_target_bc.debug?
320
+ return unless [target, *target.recursive_dependent_targets].any?(&:uses_swift?)
321
+ ldflags = test_target_bc.build_settings['OTHER_LDFLAGS'] ||= '$(inherited)'
322
+ ldflags << ' -lswiftSwiftOnoneSupport'
323
+ end
324
+
252
325
  # Creates a build phase which links the versioned header folders
253
326
  # of the OS X into the framework bundle's root root directory.
254
327
  # This is only necessary because the way how headers are copied
@@ -398,7 +471,7 @@ module Pod
398
471
  end
399
472
  end
400
473
 
401
- def add_header(build_file, public_headers, private_headers)
474
+ def add_header(build_file, public_headers, private_headers, native_target)
402
475
  file_ref = build_file.file_ref
403
476
  acl = if public_headers.include?(file_ref.real_path)
404
477
  'Public'