cocoapods 1.7.5 → 1.8.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +175 -11
  3. data/LICENSE +13 -8
  4. data/README.md +2 -1
  5. data/lib/cocoapods/command/init.rb +18 -16
  6. data/lib/cocoapods/command/install.rb +2 -1
  7. data/lib/cocoapods/command/lib/create.rb +1 -2
  8. data/lib/cocoapods/command/lib/lint.rb +12 -11
  9. data/lib/cocoapods/command/repo/add.rb +2 -2
  10. data/lib/cocoapods/command/repo/list.rb +7 -5
  11. data/lib/cocoapods/command/repo/push.rb +15 -12
  12. data/lib/cocoapods/command/setup.rb +2 -88
  13. data/lib/cocoapods/command/spec/lint.rb +10 -9
  14. data/lib/cocoapods/command/update.rb +5 -4
  15. data/lib/cocoapods/config.rb +9 -8
  16. data/lib/cocoapods/external_sources/path_source.rb +1 -1
  17. data/lib/cocoapods/gem_version.rb +1 -1
  18. data/lib/cocoapods/generator/embed_frameworks_script.rb +1 -1
  19. data/lib/cocoapods/generator/info_plist_file.rb +2 -2
  20. data/lib/cocoapods/installer.rb +32 -12
  21. data/lib/cocoapods/installer/analyzer.rb +132 -97
  22. data/lib/cocoapods/installer/analyzer/target_inspector.rb +6 -8
  23. data/lib/cocoapods/installer/installation_options.rb +4 -0
  24. data/lib/cocoapods/installer/pod_source_installer.rb +17 -1
  25. data/lib/cocoapods/installer/podfile_validator.rb +26 -6
  26. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +37 -27
  27. data/lib/cocoapods/installer/project_cache/project_cache_version.rb +1 -1
  28. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +3 -3
  29. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +12 -6
  30. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +32 -8
  31. data/lib/cocoapods/installer/project_cache/target_metadata.rb +6 -2
  32. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +12 -0
  33. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +1 -1
  34. data/lib/cocoapods/installer/xcode/multi_pods_project_generator.rb +3 -1
  35. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +2 -2
  36. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +18 -3
  37. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +53 -11
  38. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +92 -60
  39. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +66 -50
  40. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +12 -0
  41. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +6 -2
  42. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +2 -2
  43. data/lib/cocoapods/installer/xcode/target_validator.rb +30 -14
  44. data/lib/cocoapods/native_target_extension.rb +11 -5
  45. data/lib/cocoapods/open-uri.rb +1 -1
  46. data/lib/cocoapods/project.rb +13 -7
  47. data/lib/cocoapods/resolver.rb +63 -53
  48. data/lib/cocoapods/resolver/lazy_specification.rb +14 -5
  49. data/lib/cocoapods/sandbox.rb +35 -2
  50. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +3 -4
  51. data/lib/cocoapods/sources_manager.rb +72 -43
  52. data/lib/cocoapods/target.rb +7 -1
  53. data/lib/cocoapods/target/aggregate_target.rb +13 -8
  54. data/lib/cocoapods/target/build_settings.rb +33 -10
  55. data/lib/cocoapods/target/pod_target.rb +114 -30
  56. data/lib/cocoapods/user_interface/error_report.rb +9 -5
  57. data/lib/cocoapods/validator.rb +55 -11
  58. data/lib/cocoapods/version_metadata.rb +14 -1
  59. metadata +6 -7
  60. data/lib/cocoapods/command/spec/env_spec.rb +0 -53
@@ -112,7 +112,7 @@ module Pod
112
112
  regex = %r{
113
113
  ^(
114
114
  (\s* # Possible, but unlikely, space before include statement
115
- \#include\s+ # Include statement
115
+ \#include(\?)?\s+ # Include statement
116
116
  ['"] # Open quote
117
117
  (.*\/)? # Possible prefix to path
118
118
  #{Regexp.quote(target_config_path)} # The path should end in the target_config_path
@@ -13,7 +13,9 @@ module Pod
13
13
  # Generate container Pods.xcodeproj.
14
14
  container_project = create_container_project(aggregate_targets, sandbox.project_path)
15
15
 
16
- project_paths_by_pod_targets = pod_targets.group_by { |pod_target| sandbox.pod_target_project_path(pod_target.pod_name) }
16
+ project_paths_by_pod_targets = pod_targets.group_by do |pod_target|
17
+ sandbox.pod_target_project_path(pod_target.project_name)
18
+ end
17
19
  projects_by_pod_targets = Hash[project_paths_by_pod_targets.map do |project_path, pod_targets|
18
20
  project = create_pods_project(pod_targets, project_path, container_project)
19
21
  [project, pod_targets]
@@ -59,8 +59,8 @@ module Pod
59
59
  # Hit the cache
60
60
  is_local = sandbox.local?(pod_target.pod_name)
61
61
  cached_dependency = metadata_cache.target_label_by_metadata[pod_target.label]
62
- project.add_cached_pod_subproject(cached_dependency, is_local)
63
- Project.add_cached_dependency(aggregate_native_target, cached_dependency)
62
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
63
+ Project.add_cached_dependency(sandbox, aggregate_native_target, cached_dependency)
64
64
  end
65
65
  end
66
66
  end
@@ -37,6 +37,10 @@ module Pod
37
37
  #
38
38
  attr_reader :add_main
39
39
 
40
+ # @return [Hash] Info.plist entries for the app host
41
+ #
42
+ attr_reader :info_plist_entries
43
+
40
44
  # Initialize a new instance
41
45
  #
42
46
  # @param [Sandbox] sandbox @see #sandbox
@@ -46,8 +50,9 @@ module Pod
46
50
  # @param [String] group_name @see #group_name
47
51
  # @param [String] app_target_label see #app_target_label
48
52
  # @param [Boolean] add_main see #add_main
53
+ # @param [Hash] info_plist_entries see #info_plist_entries
49
54
  #
50
- def initialize(sandbox, project, platform, subgroup_name, group_name, app_target_label, add_main: true)
55
+ def initialize(sandbox, project, platform, subgroup_name, group_name, app_target_label, add_main: true, info_plist_entries: {})
51
56
  @sandbox = sandbox
52
57
  @project = project
53
58
  @platform = platform
@@ -55,6 +60,7 @@ module Pod
55
60
  @group_name = group_name
56
61
  @app_target_label = app_target_label
57
62
  @add_main = add_main
63
+ @info_plist_entries = info_plist_entries
58
64
  target_group = project.pod_group(group_name)
59
65
  @group = target_group[subgroup_name] || target_group.new_group(subgroup_name)
60
66
  end
@@ -74,9 +80,8 @@ module Pod
74
80
 
75
81
  Pod::Generator::AppTargetHelper.add_app_host_main_file(project, app_host_target, platform_name, @group, app_target_label) if add_main
76
82
  Pod::Generator::AppTargetHelper.add_launchscreen_storyboard(project, app_host_target, @group, deployment_target, app_target_label) if platform == :ios
77
- additional_entries = ADDITIONAL_INFO_PLIST_ENTRIES.merge(platform == :ios ? ADDITIONAL_IOS_INFO_PLIST_ENTRIES : {})
78
83
  create_info_plist_file_with_sandbox(sandbox, app_host_info_plist_path, app_host_target, '1.0.0', platform,
79
- :appl, additional_entries)
84
+ :appl, :additional_entries => additional_info_plist_entries)
80
85
  @group.new_file(app_host_info_plist_path)
81
86
  app_host_target
82
87
  end
@@ -104,6 +109,16 @@ module Pod
104
109
  ),
105
110
  }.freeze
106
111
 
112
+ # @return [Hash] the additional Info.plist entries to be included
113
+ #
114
+ def additional_info_plist_entries
115
+ result = {}
116
+ result.merge!(ADDITIONAL_INFO_PLIST_ENTRIES)
117
+ result.merge!(ADDITIONAL_IOS_INFO_PLIST_ENTRIES) if platform == :ios
118
+ result.merge!(info_plist_entries) if info_plist_entries
119
+ result
120
+ end
121
+
107
122
  # @return [Pathname] The absolute path of the Info.plist to use for an app host.
108
123
  #
109
124
  def app_host_info_plist_path
@@ -6,6 +6,10 @@ module Pod
6
6
  class PodTargetDependencyInstaller
7
7
  require 'cocoapods/native_target_extension.rb'
8
8
 
9
+ # @return [Sandbox] The sandbox used for this installation.
10
+ #
11
+ attr_reader :sandbox
12
+
9
13
  # @return [TargetInstallationResults] The target installation results for pod targets.
10
14
  #
11
15
  attr_reader :pod_target_installation_results
@@ -14,10 +18,6 @@ module Pod
14
18
  #
15
19
  attr_reader :metadata_cache
16
20
 
17
- # @return [Sandbox] The sandbox used for this installation.
18
- #
19
- attr_reader :sandbox
20
-
21
21
  # Initialize a new instance.
22
22
  #
23
23
  # @param [Sandbox] sandbox @see #sandbox
@@ -85,8 +85,8 @@ module Pod
85
85
  else
86
86
  # Hit the cache
87
87
  cached_dependency = metadata_cache.target_label_by_metadata[dependent_target.label]
88
- project.add_cached_pod_subproject(cached_dependency, is_local)
89
- Project.add_cached_dependency(native_target, cached_dependency)
88
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
89
+ Project.add_cached_dependency(sandbox, native_target, cached_dependency)
90
90
  end
91
91
  end
92
92
  end
@@ -98,7 +98,7 @@ module Pod
98
98
  test_native_target.add_dependency(test_resource_bundle_target)
99
99
  end
100
100
 
101
- test_dependent_targets = pod_target.test_dependent_targets_by_spec_name.fetch(test_spec.name, []).unshift(pod_target).uniq
101
+ test_dependent_targets = pod_target.test_dependent_targets_by_spec_name.fetch(test_spec.name, []).+([pod_target]).uniq
102
102
  test_dependent_targets.each do |test_dependent_target|
103
103
  is_local = sandbox.local?(test_dependent_target.pod_name)
104
104
  if dependency_installation_result = pod_target_installation_results[test_dependent_target.name]
@@ -111,10 +111,52 @@ module Pod
111
111
  else
112
112
  # Hit the cache
113
113
  cached_dependency = metadata_cache.target_label_by_metadata[test_dependent_target.label]
114
- project.add_cached_pod_subproject(cached_dependency, is_local)
115
- Project.add_cached_dependency(test_native_target, cached_dependency)
114
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
115
+ Project.add_cached_dependency(sandbox, test_native_target, cached_dependency)
116
+ end
117
+ end
118
+
119
+ if app_host_target_label = pod_target.app_host_target_label(test_spec)
120
+ app_host_pod_target_label, app_host_target_label = *app_host_target_label
121
+ wire_test_native_target_app_host(test_native_target, pod_target, pod_target_installation_results, project, metadata_cache, app_host_pod_target_label, app_host_target_label)
122
+ end
123
+ end
124
+ end
125
+
126
+ def wire_test_native_target_app_host(test_native_target, pod_target, pod_target_installation_results, project, metadata_cache, app_host_pod_target_label, app_host_target_label)
127
+ if dependency_installation_result = pod_target_installation_results[app_host_pod_target_label]
128
+ unless app_native_target = dependency_installation_result.app_host_target_labelled(app_host_target_label)
129
+ raise Informative, "Did not find target with label #{app_host_target_label} in the set of targets installed for #{app_host_pod_target_label}."
130
+ end
131
+
132
+ dependent_test_project = app_native_target.project
133
+ if dependent_test_project != project
134
+ project.add_subproject_reference(dependent_test_project, project.dependencies_group)
135
+ end
136
+
137
+ app_host_target_names = app_native_target.resolved_build_setting('PRODUCT_NAME', true)
138
+ test_native_target.build_configurations.each do |configuration|
139
+ app_host_target_name = app_host_target_names[configuration.name] || target.name
140
+ case test_native_target.symbol_type
141
+ when :unit_test_bundle
142
+ test_host = "$(BUILT_PRODUCTS_DIR)/#{app_host_target_name}.app/"
143
+ test_host << 'Contents/MacOS/' if pod_target.platform == :osx
144
+ test_host << app_host_target_name.to_s
145
+ configuration.build_settings['BUNDLE_LOADER'] = '$(TEST_HOST)'
146
+ configuration.build_settings['TEST_HOST'] = test_host
147
+ when :ui_test_bundle
148
+ configuration.build_settings['TEST_TARGET_NAME'] = app_host_target_name
116
149
  end
117
150
  end
151
+ target_attributes = project.root_object.attributes['TargetAttributes'] || {}
152
+ target_attributes[test_native_target.uuid.to_s] = { 'TestTargetID' => app_native_target.uuid.to_s }
153
+ project.root_object.attributes['TargetAttributes'] = target_attributes
154
+ test_native_target.add_dependency(app_native_target)
155
+ else
156
+ # Hit the cache
157
+ cached_dependency = metadata_cache.target_label_by_metadata[app_host_target_label]
158
+ project.add_cached_subproject_reference(sandbox, cached_dependency, project.dependencies_group)
159
+ Project.add_cached_dependency(sandbox, test_native_target, cached_dependency)
118
160
  end
119
161
  end
120
162
 
@@ -144,8 +186,8 @@ module Pod
144
186
  else
145
187
  # Hit the cache
146
188
  cached_dependency = metadata_cache.target_label_by_metadata[app_dependent_target.label]
147
- project.add_cached_pod_subproject(cached_dependency, is_local)
148
- Project.add_cached_dependency(native_target, cached_dependency)
189
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
190
+ Project.add_cached_dependency(sandbox, native_target, cached_dependency)
149
191
  end
150
192
  end
151
193
  end
@@ -48,7 +48,7 @@ module Pod
48
48
  resource_bundle_targets = add_resources_bundle_targets(library_file_accessors).values.flatten
49
49
 
50
50
  test_native_targets = add_test_targets
51
- test_app_host_targets = add_test_app_host_targets(test_native_targets)
51
+ test_app_host_targets = add_test_app_host_targets
52
52
  test_resource_bundle_targets = add_resources_bundle_targets(test_file_accessors)
53
53
 
54
54
  app_native_targets = add_app_targets
@@ -72,8 +72,8 @@ module Pod
72
72
  end
73
73
 
74
74
  file_accessor.public_headers.map do |public_header|
75
- public_header = if header_mappings_dir
76
- public_header.relative_path_from(header_mappings_dir)
75
+ public_header = if header_mappings_dir(file_accessor)
76
+ public_header.relative_path_from(header_mappings_dir(file_accessor))
77
77
  else
78
78
  public_header.basename
79
79
  end
@@ -88,7 +88,7 @@ module Pod
88
88
 
89
89
  if target.build_as_framework?
90
90
  unless skip_info_plist?(native_target)
91
- create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform)
91
+ create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform, :additional_entries => target.info_plist_entries)
92
92
  end
93
93
  create_build_phase_to_symlink_header_folders(native_target)
94
94
  end
@@ -303,7 +303,7 @@ module Pod
303
303
 
304
304
  header_file_refs = project_file_references_array(headers, 'header')
305
305
  native_target.add_file_references(header_file_refs) do |build_file|
306
- add_header(build_file, public_headers, private_headers, native_target)
306
+ add_header(file_accessor, build_file, public_headers, private_headers, native_target)
307
307
  end
308
308
 
309
309
  other_file_refs = project_file_references_array(other_source_files, 'other source')
@@ -331,7 +331,9 @@ module Pod
331
331
  name = target.test_target_label(test_spec)
332
332
  platform_name = target.platform.name
333
333
  language = target.uses_swift_for_spec?(test_spec) ? :swift : :objc
334
- test_native_target = project.new_target(product_type, name, platform_name, deployment_target, nil, language)
334
+ test_native_target = project.new_target(product_type, name, platform_name,
335
+ target.deployment_target_for_non_library_spec(test_spec), nil,
336
+ language)
335
337
  test_native_target.product_reference.name = name
336
338
 
337
339
  target.user_build_configurations.each do |bc_name, type|
@@ -372,7 +374,9 @@ module Pod
372
374
  # Generate vanilla Info.plist for test target similar to the one Xcode generates for new test target.
373
375
  # This creates valid test bundle accessible at the runtime, allowing tests to load bundle resources
374
376
  # defined in podspec.
375
- create_info_plist_file(target.info_plist_path_for_spec(test_spec), test_native_target, '1.0', target.platform, :bndl)
377
+ additional_entries = spec_consumer.info_plist
378
+ path = target.info_plist_path_for_spec(test_spec)
379
+ create_info_plist_file(path, test_native_target, '1.0', target.platform, :bndl, :additional_entries => additional_entries)
376
380
 
377
381
  test_native_target
378
382
  end
@@ -381,32 +385,17 @@ module Pod
381
385
  # Adds the test app host targets for the library to the Pods project with the
382
386
  # appropriate build configurations.
383
387
  #
384
- # @param [Array<PBXNativeTarget>] test_native_targets
385
- # the test native targets that have been created to use as a lookup when linking the app host to.
386
- #
387
388
  # @return [Array<PBXNativeTarget>] the app host targets created.
388
389
  #
389
- def add_test_app_host_targets(test_native_targets)
390
- target.test_spec_consumers.select(&:requires_app_host?).group_by(&:test_type).map do |test_type, test_spec_consumers|
391
- platform = target.platform
392
- name = "AppHost-#{target.label}-#{test_type.capitalize}-Tests"
393
- app_host_target = AppHostInstaller.new(sandbox, project, platform, name, target.pod_name, name).install!
394
- # Wire test native targets to the generated app host.
395
- test_spec_consumers.each do |test_spec_consumer|
396
- test_native_target = test_native_target_from_spec(test_spec_consumer.spec, test_native_targets)
397
- test_native_target.build_configurations.each do |configuration|
398
- test_host = "$(BUILT_PRODUCTS_DIR)/#{app_host_target.name}.app/"
399
- test_host << 'Contents/MacOS/' if platform == :osx
400
- test_host << app_host_target.name.to_s
401
- configuration.build_settings['TEST_HOST'] = test_host
402
- end
403
- target_attributes = project.root_object.attributes['TargetAttributes'] || {}
404
- target_attributes[test_native_target.uuid.to_s] = { 'TestTargetID' => app_host_target.uuid.to_s }
405
- project.root_object.attributes['TargetAttributes'] = target_attributes
406
- test_native_target.add_dependency(app_host_target)
407
- end
408
- app_host_target
390
+ def add_test_app_host_targets
391
+ target.test_spec_consumers.reject(&:requires_app_host?).select(&:app_host_name).each do |test_spec_consumer|
392
+ raise Informative, "`#{target.label}-#{test_spec_consumer.test_type}-Tests` manually specifies an app host but has not specified `requires_app_host = true`."
409
393
  end
394
+
395
+ target.test_spec_consumers.select(&:requires_app_host?).reject(&:app_host_name).group_by { |consumer| target.app_host_target_label(consumer.spec) }.
396
+ map do |(_, target_name), _|
397
+ AppHostInstaller.new(sandbox, project, target.platform, target_name, target.pod_name, target_name).install!
398
+ end
410
399
  end
411
400
 
412
401
  # Adds the app targets for the library to the Pods project with the
@@ -416,12 +405,15 @@ module Pod
416
405
  #
417
406
  def add_app_targets
418
407
  target.app_specs.map do |app_spec|
408
+ spec_consumer = app_spec.consumer(target.platform)
419
409
  spec_name = app_spec.parent.name
420
410
  subspec_name = target.subspec_label(app_spec)
421
411
  app_target_label = target.app_target_label(app_spec)
422
- platform = target.platform
412
+ platform = Platform.new(target.platform.symbolic_name, target.deployment_target_for_non_library_spec(app_spec))
413
+ info_plist_entries = spec_consumer.info_plist
423
414
  app_native_target = AppHostInstaller.new(sandbox, project, platform, subspec_name, spec_name,
424
- app_target_label, :add_main => false).install!
415
+ app_target_label, :add_main => false,
416
+ :info_plist_entries => info_plist_entries).install!
425
417
 
426
418
  app_native_target.product_reference.name = app_target_label
427
419
  target.user_build_configurations.each do |bc_name, type|
@@ -507,8 +499,11 @@ module Pod
507
499
  target.user_build_configurations.each do |bc_name, type|
508
500
  resource_bundle_target.add_build_configuration(bc_name, type)
509
501
  end
510
- resource_bundle_target.deployment_target = deployment_target
511
-
502
+ resource_bundle_target.deployment_target = if file_accessor.spec.non_library_specification?
503
+ target.deployment_target_for_non_library_spec(file_accessor.spec)
504
+ else
505
+ deployment_target
506
+ end
512
507
  # Create Info.plist file for bundle
513
508
  path = target.info_plist_path
514
509
  path.dirname.mkdir unless path.dirname.exist?
@@ -524,6 +519,10 @@ module Pod
524
519
  configuration.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir('$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)')
525
520
  end
526
521
 
522
+ # Set the 'IBSC_MODULE' build settings for resource bundles so that Storyboards and Xibs can load
523
+ # classes from the parent module.
524
+ configuration.build_settings['IBSC_MODULE'] = target.product_module_name
525
+
527
526
  # Set the `SWIFT_VERSION` build setting for resource bundles that could have resources that get
528
527
  # compiled such as an `xcdatamodeld` file which has 'Swift' as its code generation language.
529
528
  if contains_compile_phase_refs && file_accessors.any? { |fa| target.uses_swift_for_spec?(fa.spec) }
@@ -608,16 +607,22 @@ module Pod
608
607
  def create_test_target_copy_resources_script(test_spec)
609
608
  path = target.copy_resources_script_path_for_spec(test_spec)
610
609
  pod_targets = target.dependent_targets_for_test_spec(test_spec)
610
+ host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt|
611
+ pt.specs.map(&:name)
612
+ end.uniq
611
613
  resource_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config|
612
614
  resources_by_config[config] = pod_targets.flat_map do |pod_target|
613
615
  spec_paths_to_include = pod_target.library_specs.map(&:name)
616
+ spec_paths_to_include -= host_target_spec_names
614
617
  spec_paths_to_include << test_spec.name if pod_target == target
615
618
  pod_target.resource_paths.values_at(*spec_paths_to_include).flatten.compact
616
619
  end
617
620
  end
618
- generator = Generator::CopyResourcesScript.new(resource_paths_by_config, target.platform)
619
- update_changed_file(generator, path)
620
- add_file_to_support_group(path)
621
+ unless resource_paths_by_config.each_value.all?(&:empty?)
622
+ generator = Generator::CopyResourcesScript.new(resource_paths_by_config, target.platform)
623
+ update_changed_file(generator, path)
624
+ add_file_to_support_group(path)
625
+ end
621
626
  end
622
627
 
623
628
  # Creates a script that embeds the frameworks to the bundle of the test target.
@@ -630,16 +635,22 @@ module Pod
630
635
  def create_test_target_embed_frameworks_script(test_spec)
631
636
  path = target.embed_frameworks_script_path_for_spec(test_spec)
632
637
  pod_targets = target.dependent_targets_for_test_spec(test_spec)
638
+ host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt|
639
+ pt.specs.map(&:name)
640
+ end.uniq
633
641
  framework_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, paths_by_config|
634
642
  paths_by_config[config] = pod_targets.flat_map do |pod_target|
635
643
  spec_paths_to_include = pod_target.library_specs.map(&:name)
644
+ spec_paths_to_include -= host_target_spec_names
636
645
  spec_paths_to_include << test_spec.name if pod_target == target
637
646
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
638
647
  end
639
648
  end
640
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
641
- update_changed_file(generator, path)
642
- add_file_to_support_group(path)
649
+ unless framework_paths_by_config.each_value.all?(&:empty?)
650
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
651
+ update_changed_file(generator, path)
652
+ add_file_to_support_group(path)
653
+ end
643
654
  end
644
655
 
645
656
  # Generates the contents of the xcconfig file used for each app target type and saves it to disk.
@@ -684,9 +695,11 @@ module Pod
684
695
  pod_target.resource_paths.values_at(*spec_paths_to_include).flatten.compact
685
696
  end
686
697
  end
687
- generator = Generator::CopyResourcesScript.new(resource_paths_by_config, target.platform)
688
- update_changed_file(generator, path)
689
- add_file_to_support_group(path)
698
+ unless resource_paths_by_config.each_value.all?(&:empty?)
699
+ generator = Generator::CopyResourcesScript.new(resource_paths_by_config, target.platform)
700
+ update_changed_file(generator, path)
701
+ add_file_to_support_group(path)
702
+ end
690
703
  end
691
704
 
692
705
  # Creates a script that embeds the frameworks to the bundle of the app target.
@@ -706,9 +719,11 @@ module Pod
706
719
  pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
707
720
  end
708
721
  end
709
- generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
710
- update_changed_file(generator, path)
711
- add_file_to_support_group(path)
722
+ unless framework_paths_by_config.each_value.all?(&:empty?)
723
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
724
+ update_changed_file(generator, path)
725
+ add_file_to_support_group(path)
726
+ end
712
727
  end
713
728
 
714
729
  # Manually add `libswiftSwiftOnoneSupport.dylib` as it seems there is an issue with tests that do not include it for Debug configurations.
@@ -736,13 +751,21 @@ module Pod
736
751
  # @return [void]
737
752
  #
738
753
  def create_build_phase_to_symlink_header_folders(native_target)
739
- return unless target.platform.name == :osx && header_mappings_dir
754
+ return unless target.platform.name == :osx && any_header_mapping_dirs?
740
755
 
741
756
  build_phase = native_target.new_shell_script_build_phase('Create Symlinks to Header Folders')
742
757
  build_phase.shell_script = <<-eos.strip_heredoc
743
- base="$CONFIGURATION_BUILD_DIR/$WRAPPER_NAME"
744
- ln -fs "$base/${PUBLIC_HEADERS_FOLDER_PATH\#$WRAPPER_NAME/}" "$base/${PUBLIC_HEADERS_FOLDER_PATH\#\$CONTENTS_FOLDER_PATH/}"
745
- ln -fs "$base/${PRIVATE_HEADERS_FOLDER_PATH\#\$WRAPPER_NAME/}" "$base/${PRIVATE_HEADERS_FOLDER_PATH\#\$CONTENTS_FOLDER_PATH/}"
758
+ cd "$CONFIGURATION_BUILD_DIR/$WRAPPER_NAME" || exit 1
759
+
760
+ public_path="${PUBLIC_HEADERS_FOLDER_PATH\#\$CONTENTS_FOLDER_PATH/}"
761
+ if [ ! -f "$public_path" ]; then
762
+ ln -fs "${PUBLIC_HEADERS_FOLDER_PATH\#$WRAPPER_NAME/}" "$public_path"
763
+ fi
764
+
765
+ private_path="${PRIVATE_HEADERS_FOLDER_PATH\#\$CONTENTS_FOLDER_PATH/}"
766
+ if [ ! -f "$private_path" ]; then
767
+ ln -fs "${PRIVATE_HEADERS_FOLDER_PATH\#\$WRAPPER_NAME/}" "$private_path"
768
+ fi
746
769
  eos
747
770
  end
748
771
 
@@ -868,20 +891,25 @@ module Pod
868
891
  def project_file_references_array(files, file_type)
869
892
  files.map do |sf|
870
893
  project.reference_for_path(sf).tap do |ref|
871
- raise Informative, "Unable to find #{file_type} ref for #{sf} for target #{target.name}." unless ref
894
+ raise Informative, "Unable to find #{file_type} ref for `#{sf.basename}` for target `#{target.name}`." unless ref
872
895
  end
873
896
  end
874
897
  end
875
898
 
876
- def header_mappings_dir
877
- return @header_mappings_dir if defined?(@header_mappings_dir)
878
- file_accessor = target.file_accessors.first
879
- @header_mappings_dir = if dir = file_accessor.spec_consumer.header_mappings_dir
880
- file_accessor.path_list.root + dir
881
- end
899
+ def any_header_mapping_dirs?
900
+ return @any_header_mapping_dirs if defined?(@any_header_mapping_dirs)
901
+ @any_header_mapping_dirs = target.file_accessors.any? { |fa| fa.spec_consumer.header_mappings_dir }
902
+ end
903
+
904
+ def header_mappings_dir(file_accessor)
905
+ @header_mappings_dirs ||= {}
906
+ return @header_mappings_dirs[file_accessor] if @header_mappings_dirs.key?(file_accessor)
907
+ @header_mappings_dirs[file_accessor] = if dir = file_accessor.spec_consumer.header_mappings_dir
908
+ file_accessor.path_list.root + dir
909
+ end
882
910
  end
883
911
 
884
- def add_header(build_file, public_headers, private_headers, native_target)
912
+ def add_header(file_accessor, build_file, public_headers, private_headers, native_target)
885
913
  file_ref = build_file.file_ref
886
914
  acl = if !target.build_as_framework? # Headers are already rooted at ${PODS_ROOT}/Headers/P*/[pod]/...
887
915
  'Project'
@@ -893,8 +921,12 @@ module Pod
893
921
  'Project'
894
922
  end
895
923
 
896
- if target.build_as_framework? && header_mappings_dir && acl != 'Project'
897
- relative_path = file_ref.real_path.relative_path_from(header_mappings_dir)
924
+ if target.build_as_framework? && any_header_mapping_dirs? && acl != 'Project'
925
+ relative_path = if mapping_dir = header_mappings_dir(file_accessor)
926
+ file_ref.real_path.relative_path_from(mapping_dir)
927
+ else
928
+ file_ref.real_path.relative_path_from(file_accessor.path_list.root)
929
+ end
898
930
  sub_dir = relative_path.dirname
899
931
  copy_phase_name = "Copy #{sub_dir} #{acl} Headers"
900
932
  copy_phase = native_target.copy_files_build_phases.find { |bp| bp.name == copy_phase_name } ||