cocoapods 1.2.1 → 1.3.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'