cocoapods 1.5.3 → 1.6.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +200 -0
  3. data/lib/cocoapods.rb +0 -1
  4. data/lib/cocoapods/command/init.rb +1 -1
  5. data/lib/cocoapods/command/install.rb +7 -0
  6. data/lib/cocoapods/command/lib/lint.rb +8 -1
  7. data/lib/cocoapods/command/outdated.rb +2 -7
  8. data/lib/cocoapods/command/repo/add.rb +1 -1
  9. data/lib/cocoapods/command/repo/list.rb +1 -1
  10. data/lib/cocoapods/command/repo/push.rb +17 -12
  11. data/lib/cocoapods/command/repo/remove.rb +1 -1
  12. data/lib/cocoapods/command/repo/update.rb +1 -1
  13. data/lib/cocoapods/command/setup.rb +1 -1
  14. data/lib/cocoapods/command/spec/create.rb +39 -39
  15. data/lib/cocoapods/command/spec/lint.rb +8 -1
  16. data/lib/cocoapods/config.rb +13 -2
  17. data/lib/cocoapods/downloader/cache.rb +1 -1
  18. data/lib/cocoapods/executable.rb +2 -2
  19. data/lib/cocoapods/external_sources.rb +7 -4
  20. data/lib/cocoapods/external_sources/abstract_external_source.rb +23 -13
  21. data/lib/cocoapods/gem_version.rb +1 -1
  22. data/lib/cocoapods/generator/acknowledgements/markdown.rb +6 -0
  23. data/lib/cocoapods/generator/acknowledgements/plist.rb +11 -0
  24. data/lib/cocoapods/generator/app_target_helper.rb +102 -16
  25. data/lib/cocoapods/generator/copy_resources_script.rb +6 -0
  26. data/lib/cocoapods/generator/dummy_source.rb +14 -5
  27. data/lib/cocoapods/generator/embed_frameworks_script.rb +13 -2
  28. data/lib/cocoapods/generator/header.rb +1 -1
  29. data/lib/cocoapods/generator/info_plist_file.rb +12 -4
  30. data/lib/cocoapods/generator/prefix_header.rb +2 -2
  31. data/lib/cocoapods/hooks_manager.rb +28 -17
  32. data/lib/cocoapods/installer.rb +103 -42
  33. data/lib/cocoapods/installer/analyzer.rb +362 -277
  34. data/lib/cocoapods/installer/analyzer/analysis_result.rb +52 -22
  35. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +9 -6
  36. data/lib/cocoapods/installer/analyzer/pod_variant.rb +4 -5
  37. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +3 -14
  38. data/lib/cocoapods/installer/analyzer/specs_state.rb +28 -4
  39. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +24 -16
  40. data/lib/cocoapods/installer/analyzer/target_inspector.rb +17 -11
  41. data/lib/cocoapods/installer/pod_source_installer.rb +31 -43
  42. data/lib/cocoapods/installer/post_install_hooks_context.rb +71 -46
  43. data/lib/cocoapods/installer/pre_install_hooks_context.rb +22 -13
  44. data/lib/cocoapods/installer/source_provider_hooks_context.rb +3 -1
  45. data/lib/cocoapods/installer/user_project_integrator.rb +0 -2
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +38 -28
  47. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +44 -11
  48. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +129 -119
  49. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +25 -16
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +95 -0
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +12 -45
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +277 -169
  53. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +31 -24
  54. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +93 -0
  55. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +60 -69
  56. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +72 -0
  57. data/lib/cocoapods/installer/xcode/target_validator.rb +15 -9
  58. data/lib/cocoapods/project.rb +14 -14
  59. data/lib/cocoapods/resolver.rb +38 -50
  60. data/lib/cocoapods/sandbox.rb +22 -38
  61. data/lib/cocoapods/sandbox/file_accessor.rb +11 -6
  62. data/lib/cocoapods/sandbox/headers_store.rb +9 -8
  63. data/lib/cocoapods/sandbox/path_list.rb +5 -8
  64. data/lib/cocoapods/sources_manager.rb +1 -1
  65. data/lib/cocoapods/target.rb +92 -37
  66. data/lib/cocoapods/target/aggregate_target.rb +140 -84
  67. data/lib/cocoapods/target/build_settings.rb +1076 -0
  68. data/lib/cocoapods/target/pod_target.rb +198 -294
  69. data/lib/cocoapods/user_interface.rb +5 -0
  70. data/lib/cocoapods/validator.rb +133 -41
  71. metadata +18 -18
  72. data/lib/cocoapods/generator/xcconfig.rb +0 -13
  73. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +0 -260
  74. data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +0 -87
  75. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +0 -558
@@ -1,71 +1,86 @@
1
1
  module Pod
2
2
  # Stores the information relative to the target used to compile a single Pod.
3
- # A pod can have one or more activated spec/subspecs.
3
+ # A pod can have one or more activated spec, subspecs and test specs.
4
4
  #
5
5
  class PodTarget < Target
6
- # @return [Array<Specification>] the spec and subspecs for the target.
6
+ # @return [Array<Specification>] the spec, subspecs and test specs of the target.
7
7
  #
8
8
  attr_reader :specs
9
9
 
10
+ # @return [Array<Specification>] All of the test specs within this target.
11
+ # Subset of #specs.
12
+ #
13
+ attr_reader :test_specs
14
+
15
+ # @return [Array<Specification>] All of the specs within this target that are not test specs.
16
+ # Subset of #specs.
17
+ #
18
+ attr_reader :non_test_specs
19
+
10
20
  # @return [Array<TargetDefinition>] the target definitions of the Podfile
11
21
  # that generated this target.
12
22
  #
13
23
  attr_reader :target_definitions
14
24
 
15
- # @return [HeadersStore] the header directory for the target.
25
+ # @return [Array<Sandbox::FileAccessor>] the file accessors for the
26
+ # specifications of this target.
16
27
  #
17
- attr_reader :build_headers
28
+ attr_reader :file_accessors
18
29
 
19
- # @return [String] used as suffix in the label
30
+ # @return [String] the suffix used for this target when deduplicated. May be `nil`.
20
31
  #
21
32
  # @note This affects the value returned by #configuration_build_dir
22
33
  # and accessors relying on this as #build_product_path.
23
34
  #
24
35
  attr_reader :scope_suffix
25
36
 
37
+ # @return [HeadersStore] the header directory for the target.
38
+ #
39
+ attr_reader :build_headers
40
+
26
41
  # @return [Array<PodTarget>] the targets that this target has a dependency
27
42
  # upon.
28
43
  #
29
44
  attr_accessor :dependent_targets
30
45
 
31
- # @return [Array<PodTarget>] the targets that this target has a test dependency
32
- # upon.
46
+ # @return [Hash{String=>Array<PodTarget>}] all target dependencies by test spec name.
33
47
  #
34
- attr_accessor :test_dependent_targets
48
+ attr_accessor :test_dependent_targets_by_spec_name
35
49
 
36
- # return [Array<PBXNativeTarget>] the test target generated in the Pods project for
37
- # this library or `nil` if there is no test target created.
50
+ # Initialize a new instance
38
51
  #
39
- attr_accessor :test_native_targets
40
-
41
- # @param [Array<Specification>] specs @see #specs
52
+ # @param [Sandbox] sandbox @see Target#sandbox
53
+ # @param [Boolean] host_requires_frameworks @see Target#host_requires_frameworks
54
+ # @param [Hash{String=>Symbol}] user_build_configurations @see Target#user_build_configurations
55
+ # @param [Array<String>] archs @see Target#archs
56
+ # @param [Platform] platform @see Target#platform
42
57
  # @param [Array<TargetDefinition>] target_definitions @see #target_definitions
43
- # @param [Sandbox] sandbox @see #sandbox
58
+ # @param [Array<Sandbox::FileAccessor>] file_accessors @see #file_accessors
44
59
  # @param [String] scope_suffix @see #scope_suffix
45
60
  #
46
- def initialize(specs, target_definitions, sandbox, scope_suffix = nil)
61
+ def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs,
62
+ target_definitions, file_accessors = [], scope_suffix = nil)
63
+ super(sandbox, host_requires_frameworks, user_build_configurations, archs, platform)
47
64
  raise "Can't initialize a PodTarget without specs!" if specs.nil? || specs.empty?
48
65
  raise "Can't initialize a PodTarget without TargetDefinition!" if target_definitions.nil? || target_definitions.empty?
49
- raise "Can't initialize a PodTarget with only abstract TargetDefinitions" if target_definitions.all?(&:abstract?)
66
+ raise "Can't initialize a PodTarget with only abstract TargetDefinitions!" if target_definitions.all?(&:abstract?)
50
67
  raise "Can't initialize a PodTarget with an empty string scope suffix!" if scope_suffix == ''
51
- super()
52
68
  @specs = specs.dup.freeze
53
- @test_specs, @non_test_specs = @specs.partition(&:test_specification?)
54
69
  @target_definitions = target_definitions
55
- @sandbox = sandbox
70
+ @file_accessors = file_accessors
56
71
  @scope_suffix = scope_suffix
57
- @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private)
58
- @file_accessors = []
59
- @resource_bundle_targets = []
60
- @test_resource_bundle_targets = []
61
- @test_native_targets = []
72
+ @test_specs, @non_test_specs = @specs.partition(&:test_specification?)
73
+ @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private)
62
74
  @dependent_targets = []
63
- @test_dependent_targets = []
75
+ @test_dependent_targets_by_spec_name = {}
64
76
  @build_config_cache = {}
65
77
  end
66
78
 
79
+ # Scopes the current target based on the existing pod targets within the cache.
80
+ #
67
81
  # @param [Hash{Array => PodTarget}] cache
68
- # the cached PodTarget for a previously scoped (specs, target_definition)
82
+ # the cached target for a previously scoped target.
83
+ #
69
84
  # @return [Array<PodTarget>] a scoped copy for each target definition.
70
85
  #
71
86
  def scoped(cache = {})
@@ -74,13 +89,14 @@ module Pod
74
89
  if cache[cache_key]
75
90
  cache[cache_key]
76
91
  else
77
- target = PodTarget.new(specs, [target_definition], sandbox, target_definition.label)
78
- target.file_accessors = file_accessors
79
- target.user_build_configurations = user_build_configurations
80
- target.native_target = native_target
81
- target.archs = archs
92
+ target = PodTarget.new(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs, [target_definition], file_accessors, target_definition.label)
82
93
  target.dependent_targets = dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] }
83
- target.host_requires_frameworks = host_requires_frameworks
94
+ target.test_dependent_targets_by_spec_name = Hash[test_dependent_targets_by_spec_name.map do |spec_name, test_pod_targets|
95
+ scoped_test_pod_targets = test_pod_targets.flat_map do |test_pod_target|
96
+ test_pod_target.scoped(cache).select { |pt| pt.target_definitions == [target_definition] }
97
+ end
98
+ [spec_name, scoped_test_pod_targets]
99
+ end]
84
100
  cache[cache_key] = target
85
101
  end
86
102
  end
@@ -96,7 +112,7 @@ module Pod
96
112
  end
97
113
  end
98
114
 
99
- # @return [String] the Swift version for the target. If the pod author has provided a swift version
115
+ # @return [String] the Swift version for the target. If the pod author has provided a Swift version
100
116
  # then that is the one returned, otherwise the Swift version is determined by the user
101
117
  # targets that include this pod target.
102
118
  #
@@ -110,32 +126,6 @@ module Pod
110
126
  root_spec.swift_version
111
127
  end
112
128
 
113
- # @note The deployment target for the pod target is the maximum of all
114
- # the deployment targets for the current platform of the target
115
- # (or the minimum required to support the current installation
116
- # strategy, if higher).
117
- #
118
- # @return [Platform] the platform for this target.
119
- #
120
- def platform
121
- @platform ||= begin
122
- platform_name = target_definitions.first.platform.name
123
- default = Podfile::TargetDefinition::PLATFORM_DEFAULTS[platform_name]
124
- deployment_target = specs.map do |spec|
125
- Version.new(spec.deployment_target(platform_name) || default)
126
- end.max
127
- if platform_name == :ios && requires_frameworks?
128
- minimum = Version.new('8.0')
129
- deployment_target = [deployment_target, minimum].max
130
- end
131
- Platform.new(platform_name, deployment_target)
132
- end
133
- end
134
-
135
- # @visibility private
136
- #
137
- attr_writer :platform
138
-
139
129
  # @return [Podfile] The podfile which declares the dependency.
140
130
  #
141
131
  def podfile
@@ -150,30 +140,15 @@ module Pod
150
140
  root_spec.module_name
151
141
  end
152
142
 
153
- # @return [Array<Sandbox::FileAccessor>] the file accessors for the
154
- # specifications of this target.
155
- #
156
- attr_accessor :file_accessors
157
-
158
- # @return [Array<PBXNativeTarget>] the resource bundle targets belonging
159
- # to this target.
160
- attr_reader :resource_bundle_targets
161
-
162
- # @return [Array<PBXNativeTarget>] the resource bundle test targets belonging
163
- # to this target.
164
- attr_reader :test_resource_bundle_targets
165
-
166
143
  # @return [Bool] Whether or not this target should be built.
167
144
  #
168
145
  # A target should not be built if it has no source files.
169
146
  #
170
147
  def should_build?
171
148
  return @should_build if defined? @should_build
172
-
173
- return @should_build = true if contains_script_phases?
174
-
175
- source_files = file_accessors.flat_map(&:source_files)
176
- source_files -= file_accessors.flat_map(&:headers)
149
+ accessors = file_accessors.reject { |fa| fa.spec.test_specification? }
150
+ source_files = accessors.flat_map(&:source_files)
151
+ source_files -= accessors.flat_map(&:headers)
177
152
  @should_build = !source_files.empty?
178
153
  end
179
154
 
@@ -184,17 +159,47 @@ module Pod
184
159
  specs.map { |spec| spec.consumer(platform) }
185
160
  end
186
161
 
187
- # @return [Boolean] Whether the target uses Swift code.
162
+ # @return [Array<Specification::Consumer>] the test specification consumers for
163
+ # the target.
164
+ #
165
+ def test_spec_consumers
166
+ test_specs.map { |test_spec| test_spec.consumer(platform) }
167
+ end
168
+
169
+ # @return [Boolean] Whether the target uses Swift code. This excludes source files from test specs.
188
170
  #
189
171
  def uses_swift?
190
172
  return @uses_swift if defined? @uses_swift
191
173
  @uses_swift = begin
192
- file_accessors.any? do |file_accessor|
174
+ file_accessors.reject { |a| a.spec.test_specification? }.any? do |file_accessor|
193
175
  file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
194
176
  end
195
177
  end
196
178
  end
197
179
 
180
+ # Checks whether a particular test specification uses Swift or not.
181
+ #
182
+ # @param [Specification] test_spec
183
+ # The test spec to query against.
184
+ #
185
+ # @return [Boolean] Whether the target uses Swift code within the requested test spec.
186
+ #
187
+ def uses_swift_for_test_spec?(test_spec)
188
+ @uses_swift_for_test_type ||= {}
189
+ return @uses_swift_for_test_type[test_spec.name] if @uses_swift_for_test_type.key?(test_spec.name)
190
+ @uses_swift_for_test_type[test_spec.name] = begin
191
+ file_accessors.select { |a| a.spec.test_specification? && a.spec == test_spec }.any? do |file_accessor|
192
+ file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
193
+ end
194
+ end
195
+ end
196
+
197
+ # @return [Boolean] Whether the target should build a static framework.
198
+ #
199
+ def static_framework?
200
+ requires_frameworks? && root_spec.static_framework
201
+ end
202
+
198
203
  # @return [Boolean] Whether the target defines a "module"
199
204
  # (and thus will need a module map and umbrella header).
200
205
  #
@@ -204,7 +209,19 @@ module Pod
204
209
  def defines_module?
205
210
  return @defines_module if defined?(@defines_module)
206
211
  return @defines_module = true if uses_swift? || requires_frameworks?
207
- return @defines_module = true if target_definitions.any? { |td| td.build_pod_as_module?(pod_name) }
212
+
213
+ explicit_target_definitions = target_definitions.select { |td| td.dependencies.any? { |d| d.root_name == pod_name } }
214
+ tds_by_answer = explicit_target_definitions.group_by { |td| td.build_pod_as_module?(pod_name) }
215
+
216
+ if tds_by_answer.size > 1
217
+ UI.warn "Unable to determine whether to build `#{label}` as a module due to a conflict " \
218
+ "between the following target definitions:\n\t- #{tds_by_answer.map do |a, td|
219
+ "`#{td.to_sentence}` #{a ? "requires `#{label}` as a module" : "does not require `#{label}` as a module"}"
220
+ end.join("\n\t- ")}\n\n" \
221
+ "Defaulting to skip building `#{label}` as a module."
222
+ elsif tds_by_answer.keys.first == true || target_definitions.all? { |td| td.build_pod_as_module?(pod_name) }
223
+ return @defines_module = true
224
+ end
208
225
 
209
226
  @defines_module = non_test_specs.any? { |s| s.consumer(platform).pod_target_xcconfig['DEFINES_MODULE'] == 'YES' }
210
227
  end
@@ -221,113 +238,58 @@ module Pod
221
238
  !script_phases.empty?
222
239
  end
223
240
 
224
- # @return [Hash{Array => Specification}] a hash where the keys are the test native targets and the value
225
- # an array of all the test specs associated with this native target.
226
- #
227
- def test_specs_by_native_target
228
- test_specs.group_by { |test_spec| native_target_for_spec(test_spec) }
229
- end
230
-
231
241
  # @return [Boolean] Whether the target has any tests specifications.
232
242
  #
233
243
  def contains_test_specifications?
234
244
  !test_specs.empty?
235
245
  end
236
246
 
237
- # @return [Array<Specification>] All of the test specs within this target.
238
- #
239
- attr_reader :test_specs
240
-
241
- # @return [Array<Specification>] All of the specs within this target that are not test specs.
242
- #
243
- attr_reader :non_test_specs
244
-
245
- # @return [Array<Symbol>] All of the test supported types within this target.
246
- #
247
- def supported_test_types
248
- test_specs.map(&:test_type).uniq
249
- end
250
-
251
- # Returns the framework paths associated with this target. By default all paths include the framework paths
252
- # that are part of test specifications.
253
- #
254
- # @param [Boolean] include_test_spec_paths
255
- # Whether to include framework paths from test specifications or not.
256
- #
257
- # @return [Array<Hash{Symbol => [String]}>] The vendored and non vendored framework paths
258
- # this target depends upon.
259
- #
260
- def framework_paths(include_test_spec_paths = true)
261
- @framework_paths ||= {}
262
- return @framework_paths[include_test_spec_paths] if @framework_paths.key?(include_test_spec_paths)
263
- @framework_paths[include_test_spec_paths] = begin
264
- accessors = file_accessors
265
- accessors = accessors.reject { |a| a.spec.test_specification? } unless include_test_spec_paths
266
- frameworks = []
267
- accessors.flat_map(&:vendored_dynamic_artifacts).map do |framework_path|
268
- relative_path_to_sandbox = framework_path.relative_path_from(sandbox.root)
269
- framework = { :name => framework_path.basename.to_s,
270
- :input_path => "${PODS_ROOT}/#{relative_path_to_sandbox}",
271
- :output_path => "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/#{framework_path.basename}" }
272
- # Until this can be configured, assume the dSYM file uses the file name as the framework.
273
- # See https://github.com/CocoaPods/CocoaPods/issues/1698
274
- dsym_name = "#{framework_path.basename}.dSYM"
275
- dsym_path = Pathname.new("#{framework_path.dirname}/#{dsym_name}")
276
- if dsym_path.exist?
277
- framework[:dsym_name] = dsym_name
278
- framework[:dsym_input_path] = "${PODS_ROOT}/#{relative_path_to_sandbox}.dSYM"
279
- framework[:dsym_output_path] = "${DWARF_DSYM_FOLDER_PATH}/#{dsym_name}"
247
+ # @return [Hash{String=>Array<Hash{Symbol=>String}>}] The vendored and non vendored framework paths this target
248
+ # depends upon keyed by spec name. For the root spec and subspecs the framework path of the target itself
249
+ # is included.
250
+ #
251
+ def framework_paths
252
+ @framework_paths ||= begin
253
+ file_accessors.each_with_object({}) do |file_accessor, hash|
254
+ frameworks = []
255
+ file_accessor.vendored_dynamic_artifacts.map do |framework_path|
256
+ relative_path_to_sandbox = framework_path.relative_path_from(sandbox.root)
257
+ framework = { :name => framework_path.basename.to_s,
258
+ :input_path => "${PODS_ROOT}/#{relative_path_to_sandbox}",
259
+ :output_path => "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/#{framework_path.basename}" }
260
+ # Until this can be configured, assume the dSYM file uses the file name as the framework.
261
+ # See https://github.com/CocoaPods/CocoaPods/issues/1698
262
+ dsym_name = "#{framework_path.basename}.dSYM"
263
+ dsym_path = Pathname.new("#{framework_path.dirname}/#{dsym_name}")
264
+ if dsym_path.exist?
265
+ framework[:dsym_name] = dsym_name
266
+ framework[:dsym_input_path] = "${PODS_ROOT}/#{relative_path_to_sandbox}.dSYM"
267
+ framework[:dsym_output_path] = "${DWARF_DSYM_FOLDER_PATH}/#{dsym_name}"
268
+ end
269
+ frameworks << framework
280
270
  end
281
- frameworks << framework
282
- end
283
- if should_build? && requires_frameworks? && !static_framework?
284
- frameworks << { :name => product_name,
285
- :input_path => build_product_path('${BUILT_PRODUCTS_DIR}'),
286
- :output_path => "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/#{product_name}" }
271
+ if !file_accessor.spec.test_specification? && should_build? && requires_frameworks? && !static_framework?
272
+ frameworks << { :name => product_name,
273
+ :input_path => build_product_path('${BUILT_PRODUCTS_DIR}'),
274
+ :output_path => "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/#{product_name}" }
275
+ end
276
+ hash[file_accessor.spec.name] = frameworks
287
277
  end
288
- frameworks
289
278
  end
290
279
  end
291
280
 
292
- # Returns the resource paths associated with this target. By default all paths include the resource paths
293
- # that are part of test specifications.
294
- #
295
- # @param [Boolean] include_test_spec_paths
296
- # Whether to include resource paths from test specifications or not.
297
- #
298
- # @return [Array<String>] The resource and resource bundle paths this target depends upon.
281
+ # @return [Hash{String=>Array<String>}] The resource and resource bundle paths this target depends upon keyed by
282
+ # spec name.
299
283
  #
300
- def resource_paths(include_test_spec_paths = true)
301
- @resource_paths ||= {}
302
- return @resource_paths[include_test_spec_paths] if @resource_paths.key?(include_test_spec_paths)
303
- @resource_paths[include_test_spec_paths] = begin
304
- accessors = file_accessors
305
- accessors = accessors.reject { |a| a.spec.test_specification? } unless include_test_spec_paths
306
- resource_paths = accessors.flat_map do |accessor|
307
- accessor.resources.flat_map { |res| "${PODS_ROOT}/#{res.relative_path_from(sandbox.project.path.dirname)}" }
284
+ def resource_paths
285
+ @resource_paths ||= begin
286
+ file_accessors.each_with_object({}) do |file_accessor, hash|
287
+ resource_paths = file_accessor.resources.map { |res| "${PODS_ROOT}/#{res.relative_path_from(sandbox.project.path.dirname)}" }
288
+ prefix = Pod::Target::BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE
289
+ prefix = configuration_build_dir unless file_accessor.spec.test_specification?
290
+ resource_bundle_paths = file_accessor.resource_bundles.keys.map { |name| "#{prefix}/#{name.shellescape}.bundle" }
291
+ hash[file_accessor.spec.name] = resource_paths + resource_bundle_paths
308
292
  end
309
- resource_bundles = accessors.flat_map do |accessor|
310
- prefix = Generator::XCConfig::XCConfigHelper::CONFIGURATION_BUILD_DIR_VARIABLE
311
- prefix = configuration_build_dir unless accessor.spec.test_specification?
312
- accessor.resource_bundles.keys.map { |name| "#{prefix}/#{name.shellescape}.bundle" }
313
- end
314
- resource_paths + resource_bundles
315
- end
316
- end
317
-
318
- # Returns the corresponding native target to use based on the provided specification.
319
- # This is used to figure out whether to add a source file into the library native target or any of the
320
- # test native targets.
321
- #
322
- # @param [Specification] spec
323
- # The specification to base from in order to find the native target.
324
- #
325
- # @return [PBXNativeTarget] the native target to use or `nil` if none is found.
326
- #
327
- def native_target_for_spec(spec)
328
- return native_target unless spec.test_specification?
329
- test_native_targets.find do |native_target|
330
- native_target.symbol_type == product_type_for_test_type(spec.test_type)
331
293
  end
332
294
  end
333
295
 
@@ -349,22 +311,6 @@ module Pod
349
311
  end
350
312
  end
351
313
 
352
- # Returns the corresponding test type given the product type.
353
- #
354
- # @param [Symbol] product_type
355
- # The product type to map to a test type.
356
- #
357
- # @return [Symbol] The native product type to use.
358
- #
359
- def test_type_for_product_type(product_type)
360
- case product_type
361
- when :unit_test_bundle
362
- :unit
363
- else
364
- raise Informative, "Unknown product type `#{product_type}`."
365
- end
366
- end
367
-
368
314
  # @return [Specification] The root specification for the target.
369
315
  #
370
316
  def root_spec
@@ -391,6 +337,12 @@ module Pod
391
337
  end
392
338
  end
393
339
 
340
+ # @return [Pathname] the absolute path of the prefix header file.
341
+ #
342
+ def prefix_header_path
343
+ support_files_dir + "#{label}-prefix.pch"
344
+ end
345
+
394
346
  # @param [String] bundle_name
395
347
  # The name of the bundle product, which is given by the +spec+.
396
348
  #
@@ -400,64 +352,49 @@ module Pod
400
352
  "#{label}-#{bundle_name}"
401
353
  end
402
354
 
403
- # @param [Symbol] test_type
404
- # The test type to use for producing the test label.
355
+ # @param [Specification] test_spec
356
+ # The test spec to use for producing the test label.
405
357
  #
406
358
  # @return [String] The derived name of the test target.
407
359
  #
408
- def test_target_label(test_type)
409
- "#{label}-#{test_type.capitalize}-Tests"
360
+ def test_target_label(test_spec)
361
+ "#{label}-#{test_spec.test_type.capitalize}-#{test_spec.name.split('/')[1..-1].join('-')}"
410
362
  end
411
363
 
412
- # @param [Symbol] test_type
413
- # The test type to use for producing the test label.
414
- #
415
- # @return [String] The label of the app host label to use given the platform and test type.
416
- #
417
- def app_host_label(test_type)
418
- "AppHost-#{Platform.string_name(platform.symbolic_name)}-#{test_type.capitalize}-Tests"
419
- end
420
-
421
- # @param [Symbol] test_type
422
- # The test type this embed frameworks script path is for.
364
+ # @param [Specification] test_spec
365
+ # The test spec this embed frameworks script path is for.
423
366
  #
424
367
  # @return [Pathname] The absolute path of the copy resources script for the given test type.
425
368
  #
426
- def copy_resources_script_path_for_test_type(test_type)
427
- support_files_dir + "#{test_target_label(test_type)}-resources.sh"
369
+ def copy_resources_script_path_for_test_spec(test_spec)
370
+ support_files_dir + "#{test_target_label(test_spec)}-resources.sh"
428
371
  end
429
372
 
430
- # @param [Symbol] test_type
431
- # The test type this embed frameworks script path is for.
373
+ # @param [Specification] test_spec
374
+ # The test spec this embed frameworks script path is for.
432
375
  #
433
376
  # @return [Pathname] The absolute path of the embed frameworks script for the given test type.
434
377
  #
435
- def embed_frameworks_script_path_for_test_type(test_type)
436
- support_files_dir + "#{test_target_label(test_type)}-frameworks.sh"
378
+ def embed_frameworks_script_path_for_test_spec(test_spec)
379
+ support_files_dir + "#{test_target_label(test_spec)}-frameworks.sh"
437
380
  end
438
381
 
439
- # @param [Symbol] test_type
440
- # The test type this Info.plist path is for.
382
+ # @param [Specification] test_spec
383
+ # The test spec this Info.plist path is for.
441
384
  #
442
385
  # @return [Pathname] The absolute path of the Info.plist for the given test type.
443
386
  #
444
- def info_plist_path_for_test_type(test_type)
445
- support_files_dir + "#{test_target_label(test_type)}-Info.plist"
387
+ def info_plist_path_for_test_spec(test_spec)
388
+ support_files_dir + "#{test_target_label(test_spec)}-Info.plist"
446
389
  end
447
390
 
448
- # @return [Pathname] the absolute path of the prefix header file.
449
- #
450
- def prefix_header_path
451
- support_files_dir + "#{label}-prefix.pch"
452
- end
453
-
454
- # @param [Symbol] test_type
455
- # The test type prefix header path is for.
391
+ # @param [Specification] test_spec
392
+ # The test spec this prefix header path is for.
456
393
  #
457
394
  # @return [Pathname] the absolute path of the prefix header file for the given test type.
458
395
  #
459
- def prefix_header_path_for_test_type(test_type)
460
- support_files_dir + "#{test_target_label(test_type)}-prefix.pch"
396
+ def prefix_header_path_for_test_spec(test_spec)
397
+ support_files_dir + "#{test_target_label(test_spec)}-prefix.pch"
461
398
  end
462
399
 
463
400
  # @return [Array<String>] The names of the Pods on which this target
@@ -473,72 +410,49 @@ module Pod
473
410
  # dependency upon.
474
411
  #
475
412
  def recursive_dependent_targets
476
- @recursive_dependent_targets ||= begin
477
- targets = dependent_targets.clone
478
-
479
- targets.each do |target|
480
- target.dependent_targets.each do |t|
481
- targets.push(t) unless t == self || targets.include?(t)
482
- end
483
- end
413
+ @recursive_dependent_targets ||= _add_recursive_dependent_targets(Set.new).delete(self).to_a
414
+ end
484
415
 
485
- targets
416
+ def _add_recursive_dependent_targets(set)
417
+ dependent_targets.each do |target|
418
+ target._add_recursive_dependent_targets(set) if set.add?(target)
486
419
  end
420
+
421
+ set
487
422
  end
423
+ protected :_add_recursive_dependent_targets
488
424
 
425
+ # @param [Specification] test_spec
426
+ # the test spec to scope dependencies for
427
+ #
489
428
  # @return [Array<PodTarget>] the recursive targets that this target has a
490
429
  # test dependency upon.
491
430
  #
492
- def recursive_test_dependent_targets
493
- @recursive_test_dependent_targets ||= begin
494
- targets = test_dependent_targets.clone
431
+ def recursive_test_dependent_targets(test_spec)
432
+ @recursive_test_dependent_targets ||= {}
433
+ @recursive_test_dependent_targets[test_spec] ||= _add_recursive_test_dependent_targets(test_spec, Set.new).to_a
434
+ end
495
435
 
496
- targets.each do |target|
497
- target.test_dependent_targets.each do |t|
498
- targets.push(t) unless t == self || targets.include?(t)
499
- end
500
- end
436
+ def _add_recursive_test_dependent_targets(test_spec, set)
437
+ raise ArgumentError, 'Must give a test spec' unless test_spec
438
+ return unless dependent_targets = test_dependent_targets_by_spec_name[test_spec.name]
501
439
 
502
- targets
440
+ dependent_targets.each do |target|
441
+ target._add_recursive_dependent_targets(set) if set.add?(target)
503
442
  end
504
- end
505
443
 
506
- # @return [Array<PodTarget>] the canonical list of dependent targets this target has a dependency upon.
507
- # This list includes the target itself as well as its recursive dependent and test dependent targets.
508
- #
509
- def all_dependent_targets
510
- [self, *recursive_dependent_targets, *recursive_test_dependent_targets].uniq
444
+ set
511
445
  end
446
+ private :_add_recursive_test_dependent_targets
512
447
 
513
- # Checks if the target should be included in the build configuration with
514
- # the given name of a given target definition.
448
+ # @param [Specification] test_spec
449
+ # the test spec to scope dependencies for
515
450
  #
516
- # @param [TargetDefinition] target_definition
517
- # The target definition to check.
518
- #
519
- # @param [String] configuration_name
520
- # The name of the build configuration.
451
+ # @return [Array<PodTarget>] the canonical list of dependent targets this target has a dependency upon.
452
+ # This list includes the target itself as well as its recursive dependent and test dependent targets.
521
453
  #
522
- def include_in_build_config?(target_definition, configuration_name)
523
- key = [target_definition.label, configuration_name]
524
- if @build_config_cache.key?(key)
525
- return @build_config_cache[key]
526
- end
527
-
528
- whitelists = target_definition_dependencies(target_definition).map do |dependency|
529
- target_definition.pod_whitelisted_for_configuration?(dependency.name, configuration_name)
530
- end.uniq
531
-
532
- if whitelists.empty?
533
- @build_config_cache[key] = true
534
- elsif whitelists.count == 1
535
- @build_config_cache[key] = whitelists.first
536
- else
537
- raise Informative, "The subspecs of `#{pod_name}` are linked to " \
538
- "different build configurations for the `#{target_definition}` " \
539
- 'target. CocoaPods does not currently support subspecs across ' \
540
- 'different build configurations.'
541
- end
454
+ def dependent_targets_for_test_spec(test_spec)
455
+ [self, *recursive_dependent_targets, *recursive_test_dependent_targets(test_spec)].uniq
542
456
  end
543
457
 
544
458
  # Checks if warnings should be inhibited for this pod.
@@ -574,7 +488,7 @@ module Pod
574
488
  #
575
489
  # @return [String] The absolute path to the configuration build dir
576
490
  #
577
- def configuration_build_dir(dir = Generator::XCConfig::XCConfigHelper::CONFIGURATION_BUILD_DIR_VARIABLE)
491
+ def configuration_build_dir(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
578
492
  "#{dir}/#{label}"
579
493
  end
580
494
 
@@ -583,7 +497,7 @@ module Pod
583
497
  #
584
498
  # @return [String] The absolute path to the build product
585
499
  #
586
- def build_product_path(dir = Generator::XCConfig::XCConfigHelper::CONFIGURATION_BUILD_DIR_VARIABLE)
500
+ def build_product_path(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
587
501
  "#{configuration_build_dir(dir)}/#{product_name}"
588
502
  end
589
503
 
@@ -600,18 +514,18 @@ module Pod
600
514
  [version.major, version.minor, version.patch].join('.')
601
515
  end
602
516
 
603
- # @param [Boolean] include_test_dependent_targets
517
+ # @param [Boolean] include_dependent_targets_for_test_spec
604
518
  # whether to include header search paths for test dependent targets
605
519
  #
606
520
  # @return [Array<String>] The set of header search paths this target uses.
607
521
  #
608
- def header_search_paths(include_test_dependent_targets = false)
522
+ def header_search_paths(include_dependent_targets_for_test_spec: nil)
609
523
  header_search_paths = []
610
524
  header_search_paths.concat(build_headers.search_paths(platform, nil, false))
611
525
  header_search_paths.concat(sandbox.public_headers.search_paths(platform, pod_name, uses_modular_headers?))
612
526
  dependent_targets = recursive_dependent_targets
613
- dependent_targets += recursive_test_dependent_targets if include_test_dependent_targets
614
- dependent_targets.each do |dependent_target|
527
+ dependent_targets += recursive_test_dependent_targets(include_dependent_targets_for_test_spec) if include_dependent_targets_for_test_spec
528
+ dependent_targets.uniq.each do |dependent_target|
615
529
  header_search_paths.concat(sandbox.public_headers.search_paths(platform, dependent_target.pod_name, defines_module? && dependent_target.uses_modular_headers?(false)))
616
530
  end
617
531
  header_search_paths.uniq
@@ -636,18 +550,8 @@ module Pod
636
550
 
637
551
  private
638
552
 
639
- # @param [TargetDefinition] target_definition
640
- # The target definition to check.
641
- #
642
- # @return [Array<Dependency>] The dependency of the target definition for
643
- # this Pod. Return an empty array if the Pod is not a direct
644
- # dependency of the target definition but the dependency of one or
645
- # more Pods.
646
- #
647
- def target_definition_dependencies(target_definition)
648
- target_definition.dependencies.select do |dependency|
649
- Specification.root_name(dependency.name) == pod_name
650
- end
553
+ def create_build_settings
554
+ BuildSettings::PodTargetSettings.new(self)
651
555
  end
652
556
  end
653
557
  end