cocoapods 1.6.2 → 1.7.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -7
  3. data/README.md +9 -9
  4. data/lib/cocoapods.rb +2 -0
  5. data/lib/cocoapods/command.rb +1 -1
  6. data/lib/cocoapods/command/init.rb +2 -12
  7. data/lib/cocoapods/command/install.rb +3 -0
  8. data/lib/cocoapods/command/lib/create.rb +1 -1
  9. data/lib/cocoapods/command/lib/lint.rb +5 -1
  10. data/lib/cocoapods/command/list.rb +3 -5
  11. data/lib/cocoapods/command/repo.rb +1 -0
  12. data/lib/cocoapods/command/repo/add.rb +4 -5
  13. data/lib/cocoapods/command/repo/add_cdn.rb +58 -0
  14. data/lib/cocoapods/command/repo/list.rb +5 -6
  15. data/lib/cocoapods/command/repo/push.rb +6 -5
  16. data/lib/cocoapods/command/spec/create.rb +12 -12
  17. data/lib/cocoapods/command/spec/lint.rb +1 -1
  18. data/lib/cocoapods/command/update.rb +3 -0
  19. data/lib/cocoapods/config.rb +1 -0
  20. data/lib/cocoapods/executable.rb +32 -7
  21. data/lib/cocoapods/gem_version.rb +1 -1
  22. data/lib/cocoapods/generator/app_target_helper.rb +1 -1
  23. data/lib/cocoapods/generator/embed_frameworks_script.rb +13 -0
  24. data/lib/cocoapods/generator/file_list.rb +39 -0
  25. data/lib/cocoapods/generator/module_map.rb +1 -1
  26. data/lib/cocoapods/installer.rb +188 -46
  27. data/lib/cocoapods/installer/analyzer.rb +64 -39
  28. data/lib/cocoapods/installer/analyzer/pod_variant.rb +14 -9
  29. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +11 -2
  30. data/lib/cocoapods/installer/installation_options.rb +70 -44
  31. data/lib/cocoapods/installer/pod_source_installer.rb +9 -4
  32. data/lib/cocoapods/installer/podfile_validator.rb +9 -0
  33. data/lib/cocoapods/installer/post_install_hooks_context.rb +5 -2
  34. data/lib/cocoapods/installer/project_cache/project_cache.rb +11 -0
  35. data/lib/cocoapods/installer/project_cache/project_cache_analysis_result.rb +53 -0
  36. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +156 -0
  37. data/lib/cocoapods/installer/project_cache/project_cache_version.rb +43 -0
  38. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +77 -0
  39. data/lib/cocoapods/installer/project_cache/project_metadata_cache.rb +63 -0
  40. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +134 -0
  41. data/lib/cocoapods/installer/project_cache/target_metadata.rb +70 -0
  42. data/lib/cocoapods/installer/sandbox_dir_cleaner.rb +89 -0
  43. data/lib/cocoapods/installer/sandbox_header_paths_installer.rb +45 -0
  44. data/lib/cocoapods/installer/target_uuid_generator.rb +32 -0
  45. data/lib/cocoapods/installer/user_project_integrator.rb +8 -6
  46. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +128 -63
  47. data/lib/cocoapods/installer/xcode.rb +3 -0
  48. data/lib/cocoapods/installer/xcode/multi_pods_project_generator.rb +72 -0
  49. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +102 -218
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +75 -0
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +1 -1
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +29 -17
  53. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +31 -65
  54. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +155 -0
  55. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +265 -110
  56. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +70 -43
  57. data/lib/cocoapods/installer/xcode/pods_project_generator/pods_project_writer.rb +75 -0
  58. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +119 -0
  59. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +44 -7
  60. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +5 -7
  61. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +32 -0
  62. data/lib/cocoapods/installer/xcode/pods_project_generator_result.rb +35 -0
  63. data/lib/cocoapods/installer/xcode/single_pods_project_generator.rb +38 -0
  64. data/lib/cocoapods/installer/xcode/target_validator.rb +32 -25
  65. data/lib/cocoapods/native_target_extension.rb +54 -0
  66. data/lib/cocoapods/open-uri.rb +1 -1
  67. data/lib/cocoapods/podfile.rb +13 -0
  68. data/lib/cocoapods/project.rb +88 -10
  69. data/lib/cocoapods/resolver.rb +11 -8
  70. data/lib/cocoapods/resolver/resolver_specification.rb +7 -7
  71. data/lib/cocoapods/sandbox.rb +38 -9
  72. data/lib/cocoapods/sandbox/file_accessor.rb +21 -0
  73. data/lib/cocoapods/sandbox/headers_store.rb +18 -3
  74. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +1 -14
  75. data/lib/cocoapods/sources_manager.rb +11 -3
  76. data/lib/cocoapods/target.rb +67 -7
  77. data/lib/cocoapods/target/aggregate_target.rb +70 -8
  78. data/lib/cocoapods/target/build_settings.rb +124 -65
  79. data/lib/cocoapods/target/build_type.rb +139 -0
  80. data/lib/cocoapods/target/framework_paths.rb +12 -7
  81. data/lib/cocoapods/target/pod_target.rb +322 -65
  82. data/lib/cocoapods/user_interface.rb +2 -2
  83. data/lib/cocoapods/user_interface/error_report.rb +3 -0
  84. data/lib/cocoapods/user_interface/inspector_reporter.rb +1 -1
  85. data/lib/cocoapods/validator.rb +74 -39
  86. data/lib/cocoapods/version_metadata.rb +7 -0
  87. metadata +30 -6
@@ -0,0 +1,139 @@
1
+ module Pod
2
+ class Target
3
+ class BuildType
4
+ # @return [Array<Symbol>] known packaging options.
5
+ #
6
+ KNOWN_PACKAGING_OPTIONS = %i(library framework).freeze
7
+
8
+ # @return [Array<Symbol>] known linking options.
9
+ #
10
+ KNOWN_LINKAGE_OPTIONS = %i(static dynamic).freeze
11
+
12
+ # @return [Symbol] the packaging for this build type, one of KNOWN_PACKAGING_OPTIONS
13
+ #
14
+ attr_reader :packaging
15
+
16
+ # @return [Symbol] the linkage for this build type, one of KNOWN_LINKAGE_OPTIONS
17
+ #
18
+ attr_reader :linkage
19
+
20
+ attr_reader :hash
21
+
22
+ def initialize(linkage: :static, packaging: :library)
23
+ raise ArgumentError, "Invalid linkage option #{linkage.inspect}, valid options are #{KNOWN_LINKAGE_OPTIONS.inspect}" unless KNOWN_LINKAGE_OPTIONS.include?(linkage)
24
+ raise ArgumentError, "Invalid packaging option #{packaging.inspect}, valid options are #{KNOWN_PACKAGING_OPTIONS.inspect}" unless KNOWN_PACKAGING_OPTIONS.include?(packaging)
25
+
26
+ @packaging = packaging
27
+ @linkage = linkage
28
+ @hash = packaging.hash ^ linkage.hash
29
+ end
30
+
31
+ # @param [Specification] spec
32
+ # the specification to infer the build type from
33
+ #
34
+ # @param [Boolean] host_requires_frameworks
35
+ # whether the host target definition specified `use_frameworks!`
36
+ #
37
+ # @return [BuildType] the appropriate build type for the given spec,
38
+ # based on whether the host target definition requires frameworks.
39
+ #
40
+ def self.infer_from_spec(spec, host_requires_frameworks: false)
41
+ if host_requires_frameworks
42
+ root_spec = spec && spec.root
43
+ if root_spec && root_spec.static_framework
44
+ static_framework
45
+ else
46
+ dynamic_framework
47
+ end
48
+ else
49
+ static_library
50
+ end
51
+ end
52
+
53
+ # @return [BuildType] the build type for a dynamic library
54
+ #
55
+ def self.dynamic_library
56
+ new(:linkage => :dynamic, :packaging => :library)
57
+ end
58
+
59
+ # @return [BuildType] the build type for a static library
60
+ #
61
+ def self.static_library
62
+ new(:linkage => :static, :packaging => :library)
63
+ end
64
+
65
+ # @return [BuildType] the build type for a dynamic framework
66
+ #
67
+ def self.dynamic_framework
68
+ new(:linkage => :dynamic, :packaging => :framework)
69
+ end
70
+
71
+ # @return [BuildType] the build type for a static framework
72
+ #
73
+ def self.static_framework
74
+ new(:linkage => :static, :packaging => :framework)
75
+ end
76
+
77
+ # @return [Boolean] whether the target is built dynamically
78
+ #
79
+ def dynamic?
80
+ linkage == :dynamic
81
+ end
82
+
83
+ # @return [Boolean] whether the target is built statically
84
+ #
85
+ def static?
86
+ linkage == :static
87
+ end
88
+
89
+ # @return [Boolean] whether the target is built as a framework
90
+ #
91
+ def framework?
92
+ packaging == :framework
93
+ end
94
+
95
+ # @return [Boolean] whether the target is built as a library
96
+ #
97
+ def library?
98
+ packaging == :library
99
+ end
100
+
101
+ # @return [Boolean] whether the target is built as a dynamic framework
102
+ #
103
+ def dynamic_framework?
104
+ dynamic? && framework?
105
+ end
106
+
107
+ # @return [Boolean] whether the target is built as a dynamic library
108
+ #
109
+ def dynamic_library?
110
+ dynamic? && library?
111
+ end
112
+
113
+ # @return [Boolean] whether the target is built as a static framework
114
+ #
115
+ def static_framework?
116
+ static? && framework?
117
+ end
118
+
119
+ # @return [Boolean] whether the target is built as a static library
120
+ #
121
+ def static_library?
122
+ static? && library?
123
+ end
124
+
125
+ def to_s
126
+ "#{linkage} #{packaging}"
127
+ end
128
+
129
+ def inspect
130
+ "#<#{self.class} linkage=#{linkage} packaging=#{packaging}>"
131
+ end
132
+
133
+ def ==(other)
134
+ linkage == other.linkage &&
135
+ packaging == other.packaging
136
+ end
137
+ end
138
+ end
139
+ end
@@ -9,14 +9,19 @@ module Pod
9
9
  #
10
10
  attr_reader :dsym_path
11
11
 
12
- def initialize(source_path, dsym_path = nil)
12
+ # @return [Array, Nil] the bcsymbolmap files path array, if one exists
13
+ #
14
+ attr_reader :bcsymbolmap_paths
15
+
16
+ def initialize(source_path, dsym_path = nil, bcsymbolmap_paths = nil)
13
17
  @source_path = source_path
14
18
  @dsym_path = dsym_path
19
+ @bcsymbolmap_paths = bcsymbolmap_paths
15
20
  end
16
21
 
17
22
  def ==(other)
18
23
  if other.class == self.class
19
- other.source_path == @source_path && other.dsym_path == @dsym_path
24
+ other.source_path == @source_path && other.dsym_path == @dsym_path && other.bcsymbolmap_paths == @bcsymbolmap_paths
20
25
  else
21
26
  false
22
27
  end
@@ -25,11 +30,11 @@ module Pod
25
30
  alias eql? ==
26
31
 
27
32
  def hash
28
- if (dsym = dsym_path)
29
- [source_path, dsym].hash
30
- else
31
- source_path.hash
32
- end
33
+ [source_path, dsym_path, bcsymbolmap_paths].hash
34
+ end
35
+
36
+ def all_paths
37
+ [source_path, dsym_path, bcsymbolmap_paths].flatten.compact
33
38
  end
34
39
  end
35
40
  end
@@ -14,10 +14,15 @@ module Pod
14
14
  #
15
15
  attr_reader :test_specs
16
16
 
17
- # @return [Array<Specification>] All of the specs within this target that are not test specs.
17
+ # @return [Array<Specification>] All of the specs within this target that are library specs.
18
18
  # Subset of #specs.
19
19
  #
20
- attr_reader :non_test_specs
20
+ attr_reader :library_specs
21
+
22
+ # @return [Array<Specification>] All of the specs within this target that are app specs.
23
+ # Subset of #specs.
24
+ #
25
+ attr_reader :app_specs
21
26
 
22
27
  # @return [Array<TargetDefinition>] the target definitions of the Podfile
23
28
  # that generated this target.
@@ -49,6 +54,18 @@ module Pod
49
54
  #
50
55
  attr_accessor :test_dependent_targets_by_spec_name
51
56
 
57
+ # @return [Hash{String=>Array<PodTarget>}] all target dependencies by app spec name.
58
+ #
59
+ attr_accessor :app_dependent_targets_by_spec_name
60
+
61
+ # @return [Hash{String => BuildSettings}] the test spec build settings for this target.
62
+ #
63
+ attr_reader :test_spec_build_settings
64
+
65
+ # @return [Hash{String => BuildSettings}] the app spec build settings for this target.
66
+ #
67
+ attr_reader :app_spec_build_settings
68
+
52
69
  # Initialize a new instance
53
70
  #
54
71
  # @param [Sandbox] sandbox @see Target#sandbox
@@ -56,13 +73,16 @@ module Pod
56
73
  # @param [Hash{String=>Symbol}] user_build_configurations @see Target#user_build_configurations
57
74
  # @param [Array<String>] archs @see Target#archs
58
75
  # @param [Platform] platform @see Target#platform
76
+ # @param [Array<Specification>] specs @see #specs
59
77
  # @param [Array<TargetDefinition>] target_definitions @see #target_definitions
60
78
  # @param [Array<Sandbox::FileAccessor>] file_accessors @see #file_accessors
61
79
  # @param [String] scope_suffix @see #scope_suffix
80
+ # @param [Target::BuildType] build_type @see #build_type
62
81
  #
63
82
  def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs,
64
- target_definitions, file_accessors = [], scope_suffix = nil)
65
- super(sandbox, host_requires_frameworks, user_build_configurations, archs, platform)
83
+ target_definitions, file_accessors = [], scope_suffix = nil,
84
+ build_type: Target::BuildType.infer_from_spec(specs.first, :host_requires_frameworks => host_requires_frameworks))
85
+ super(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, :build_type => build_type)
66
86
  raise "Can't initialize a PodTarget without specs!" if specs.nil? || specs.empty?
67
87
  raise "Can't initialize a PodTarget without TargetDefinition!" if target_definitions.nil? || target_definitions.empty?
68
88
  raise "Can't initialize a PodTarget with only abstract TargetDefinitions!" if target_definitions.all?(&:abstract?)
@@ -71,11 +91,17 @@ module Pod
71
91
  @target_definitions = target_definitions
72
92
  @file_accessors = file_accessors
73
93
  @scope_suffix = scope_suffix
74
- @test_specs, @non_test_specs = @specs.partition(&:test_specification?)
94
+ all_specs_by_type = @specs.group_by(&:spec_type)
95
+ @library_specs = all_specs_by_type[:library] || []
96
+ @test_specs = all_specs_by_type[:test] || []
97
+ @app_specs = all_specs_by_type[:app] || []
75
98
  @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private)
76
99
  @dependent_targets = []
77
100
  @test_dependent_targets_by_spec_name = {}
101
+ @app_dependent_targets_by_spec_name = {}
78
102
  @build_config_cache = {}
103
+ @test_spec_build_settings = create_test_build_settings
104
+ @app_spec_build_settings = create_app_build_settings
79
105
  end
80
106
 
81
107
  # Scopes the current target based on the existing pod targets within the cache.
@@ -91,7 +117,8 @@ module Pod
91
117
  if cache[cache_key]
92
118
  cache[cache_key]
93
119
  else
94
- target = PodTarget.new(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs, [target_definition], file_accessors, target_definition.label)
120
+ target = PodTarget.new(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs, [target_definition], file_accessors, target_definition.label,
121
+ :build_type => build_type)
95
122
  target.dependent_targets = dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] }
96
123
  target.test_dependent_targets_by_spec_name = Hash[test_dependent_targets_by_spec_name.map do |spec_name, test_pod_targets|
97
124
  scoped_test_pod_targets = test_pod_targets.flat_map do |test_pod_target|
@@ -114,18 +141,64 @@ module Pod
114
141
  end
115
142
  end
116
143
 
117
- # @return [String] the Swift version for the target. If the pod author has provided a Swift version
118
- # then that is the one returned, otherwise the Swift version is determined by the user
119
- # targets that include this pod target.
144
+ # @return [Array<FileAccessor>] The list of all files tracked.
145
+ #
146
+ def all_files
147
+ Sandbox::FileAccessor.all_files(file_accessors)
148
+ end
149
+
150
+ # @return [Pathname] the pathname for headers in the sandbox.
151
+ #
152
+ def headers_sandbox
153
+ Pathname.new(pod_name)
154
+ end
155
+
156
+ # @return [Hash{FileAccessor => Hash}] Hash of file accessors by header mappings.
157
+ #
158
+ def header_mappings_by_file_accessor
159
+ valid_accessors = file_accessors.reject { |fa| fa.spec.non_library_specification? }
160
+ Hash[valid_accessors.map do |file_accessor|
161
+ # Private headers will always end up in Pods/Headers/Private/PodA/*.h
162
+ # This will allow for `""` imports to work.
163
+ [file_accessor, header_mappings(file_accessor, file_accessor.headers)]
164
+ end]
165
+ end
166
+
167
+ # @return [Hash{FileAccessor => Hash}] Hash of file accessors by public header mappings.
168
+ #
169
+ def public_header_mappings_by_file_accessor
170
+ valid_accessors = file_accessors.reject { |fa| fa.spec.non_library_specification? }
171
+ Hash[valid_accessors.map do |file_accessor|
172
+ # Public headers on the other hand will be added in Pods/Headers/Public/PodA/PodA/*.h
173
+ # The extra folder is intentional in order for `<>` imports to work.
174
+ [file_accessor, header_mappings(file_accessor, file_accessor.public_headers)]
175
+ end]
176
+ end
177
+
178
+ # @return [String] the Swift version for the target. If the pod author has provided a set of Swift versions
179
+ # supported by their pod then the max Swift version across all of target definitions is chosen, unless
180
+ # a target definition specifies explicit requirements for supported Swift versions. Otherwise the Swift
181
+ # version is derived by the target definitions that integrate this pod as long as they are the same.
120
182
  #
121
183
  def swift_version
122
- spec_swift_version || target_definitions.map(&:swift_version).compact.uniq.first
184
+ @swift_version ||= begin
185
+ if spec_swift_versions.empty?
186
+ target_definitions.map(&:swift_version).compact.uniq.first
187
+ else
188
+ spec_swift_versions.sort.reverse_each.find do |swift_version|
189
+ target_definitions.all? do |td|
190
+ td.supports_swift_version?(swift_version)
191
+ end
192
+ end.to_s
193
+ end
194
+ end
123
195
  end
124
196
 
125
- # @return [String] the Swift version within the root spec. Might be `nil` if none is set.
197
+ # @return [Array<Version>] the Swift versions supported. Might be empty if the author has not
198
+ # specified any versions, most likely due to legacy reasons.
126
199
  #
127
- def spec_swift_version
128
- root_spec.swift_version
200
+ def spec_swift_versions
201
+ root_spec.swift_versions
129
202
  end
130
203
 
131
204
  # @return [Podfile] The podfile which declares the dependency.
@@ -148,7 +221,7 @@ module Pod
148
221
  #
149
222
  def should_build?
150
223
  return @should_build if defined? @should_build
151
- accessors = file_accessors.reject { |fa| fa.spec.test_specification? }
224
+ accessors = file_accessors.select { |fa| fa.spec.library_specification? }
152
225
  source_files = accessors.flat_map(&:source_files)
153
226
  source_files -= accessors.flat_map(&:headers)
154
227
  @should_build = !source_files.empty?
@@ -168,40 +241,41 @@ module Pod
168
241
  test_specs.map { |test_spec| test_spec.consumer(platform) }
169
242
  end
170
243
 
171
- # @return [Boolean] Whether the target uses Swift code. This excludes source files from test specs.
244
+ # @return [Array<Specification::Consumer>] the test specification consumers for
245
+ # the target.
246
+ #
247
+ def app_spec_consumers
248
+ app_specs.map { |app_spec| app_spec.consumer(platform) }
249
+ end
250
+
251
+ # @return [Boolean] Whether the target uses Swift code. This excludes source files from non library specs.
172
252
  #
173
253
  def uses_swift?
174
254
  return @uses_swift if defined? @uses_swift
175
255
  @uses_swift = begin
176
- file_accessors.reject { |a| a.spec.test_specification? }.any? do |file_accessor|
177
- file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
256
+ file_accessors.select { |a| a.spec.library_specification? }.any? do |file_accessor|
257
+ uses_swift_for_spec?(file_accessor.spec)
178
258
  end
179
259
  end
180
260
  end
181
261
 
182
- # Checks whether a particular test specification uses Swift or not.
262
+ # Checks whether a specification uses Swift or not.
183
263
  #
184
- # @param [Specification] test_spec
185
- # The test spec to query against.
264
+ # @param [Specification] spec
265
+ # The spec to query against.
186
266
  #
187
- # @return [Boolean] Whether the target uses Swift code within the requested test spec.
267
+ # @return [Boolean] Whether the target uses Swift code within the requested non library spec.
188
268
  #
189
- def uses_swift_for_test_spec?(test_spec)
190
- @uses_swift_for_test_type ||= {}
191
- return @uses_swift_for_test_type[test_spec.name] if @uses_swift_for_test_type.key?(test_spec.name)
192
- @uses_swift_for_test_type[test_spec.name] = begin
193
- file_accessors.select { |a| a.spec.test_specification? && a.spec == test_spec }.any? do |file_accessor|
194
- file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
195
- end
269
+ def uses_swift_for_spec?(spec)
270
+ @uses_swift_for_spec_cache ||= {}
271
+ return @uses_swift_for_spec_cache[spec.name] if @uses_swift_for_spec_cache.key?(spec.name)
272
+ @uses_swift_for_spec_cache[spec.name] = begin
273
+ file_accessor = file_accessors.find { |fa| fa.spec == spec }
274
+ raise "[Bug] Unable to find file accessor for spec `#{spec.inspect}` in pod target `#{label}`" unless file_accessor
275
+ file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
196
276
  end
197
277
  end
198
278
 
199
- # @return [Boolean] Whether the target should build a static framework.
200
- #
201
- def static_framework?
202
- requires_frameworks? && root_spec.static_framework
203
- end
204
-
205
279
  # @return [Boolean] Whether the target defines a "module"
206
280
  # (and thus will need a module map and umbrella header).
207
281
  #
@@ -210,7 +284,7 @@ module Pod
210
284
  #
211
285
  def defines_module?
212
286
  return @defines_module if defined?(@defines_module)
213
- return @defines_module = true if uses_swift? || requires_frameworks?
287
+ return @defines_module = true if uses_swift? || build_as_framework?
214
288
 
215
289
  explicit_target_definitions = target_definitions.select { |td| td.dependencies.any? { |d| d.root_name == pod_name } }
216
290
  tds_by_answer = explicit_target_definitions.group_by { |td| td.build_pod_as_module?(pod_name) }
@@ -225,7 +299,7 @@ module Pod
225
299
  return @defines_module = true
226
300
  end
227
301
 
228
- @defines_module = non_test_specs.any? { |s| s.consumer(platform).pod_target_xcconfig['DEFINES_MODULE'] == 'YES' }
302
+ @defines_module = library_specs.any? { |s| s.consumer(platform).pod_target_xcconfig['DEFINES_MODULE'] == 'YES' }
229
303
  end
230
304
 
231
305
  # @return [Array<Hash{Symbol=>String}>] An array of hashes where each hash represents a single script phase.
@@ -246,6 +320,12 @@ module Pod
246
320
  !test_specs.empty?
247
321
  end
248
322
 
323
+ # @return [Boolean] Whether the target has any tests specifications.
324
+ #
325
+ def contains_app_specifications?
326
+ !app_specs.empty?
327
+ end
328
+
249
329
  # @return [Hash{String=>Array<FrameworkPaths>}] The vendored and non vendored framework paths this target
250
330
  # depends upon keyed by spec name. For the root spec and subspecs the framework path of the target itself
251
331
  # is included.
@@ -263,9 +343,18 @@ module Pod
263
343
  dsym_source = if dsym_path.exist?
264
344
  "${PODS_ROOT}/#{relative_path_to_sandbox}.dSYM"
265
345
  end
266
- FrameworkPaths.new(framework_source, dsym_source)
346
+ dirname = framework_path.dirname
347
+ bcsymbolmap_paths = if dirname.exist?
348
+ Dir.chdir(dirname) do
349
+ Dir.glob('*.bcsymbolmap').map do |bcsymbolmap_file_name|
350
+ bcsymbolmap_path = dirname + bcsymbolmap_file_name
351
+ "${PODS_ROOT}/#{bcsymbolmap_path.relative_path_from(sandbox.root)}"
352
+ end
353
+ end
354
+ end
355
+ FrameworkPaths.new(framework_source, dsym_source, bcsymbolmap_paths)
267
356
  end
268
- if !file_accessor.spec.test_specification? && should_build? && requires_frameworks? && !static_framework?
357
+ if !file_accessor.spec.test_specification? && should_build? && build_as_dynamic_framework?
269
358
  frameworks << FrameworkPaths.new(build_product_path('${BUILT_PRODUCTS_DIR}'))
270
359
  end
271
360
  hash[file_accessor.spec.name] = frameworks
@@ -279,7 +368,8 @@ module Pod
279
368
  def resource_paths
280
369
  @resource_paths ||= begin
281
370
  file_accessors.each_with_object({}) do |file_accessor, hash|
282
- resource_paths = file_accessor.resources.map { |res| "${PODS_ROOT}/#{res.relative_path_from(sandbox.project.path.dirname)}" }
371
+ resource_paths = file_accessor.resources.map { |res| "${PODS_ROOT}/#{res.relative_path_from(sandbox.project_path.dirname)}" }
372
+ resource_paths = [] if file_accessor.spec.app_specification?
283
373
  prefix = Pod::Target::BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE
284
374
  prefix = configuration_build_dir unless file_accessor.spec.test_specification?
285
375
  resource_bundle_paths = file_accessor.resource_bundles.keys.map { |name| "#{prefix}/#{name.shellescape}.bundle" }
@@ -302,7 +392,7 @@ module Pod
302
392
  when :unit
303
393
  :unit_test_bundle
304
394
  else
305
- raise Informative, "Unknown test type `#{test_type}`."
395
+ raise ArgumentError, "Unknown test type `#{test_type}`."
306
396
  end
307
397
  end
308
398
 
@@ -323,7 +413,7 @@ module Pod
323
413
  #
324
414
  def module_map_path
325
415
  basename = "#{label}.modulemap"
326
- if requires_frameworks?
416
+ if build_as_framework?
327
417
  super
328
418
  elsif file_accessors.any?(&:module_map)
329
419
  build_headers.root + product_module_name + basename
@@ -347,49 +437,121 @@ module Pod
347
437
  "#{label}-#{bundle_name}"
348
438
  end
349
439
 
440
+ # @param [Specification] subspec
441
+ # The subspec to use for producing the label.
442
+ #
443
+ # @return [String] The derived name of the target.
444
+ #
445
+ def subspec_label(subspec)
446
+ raise ArgumentError, 'Must not be a root spec' if subspec.root?
447
+ subspec.name.split('/')[1..-1].join('-').to_s
448
+ end
449
+
350
450
  # @param [Specification] test_spec
351
451
  # The test spec to use for producing the test label.
352
452
  #
353
453
  # @return [String] The derived name of the test target.
354
454
  #
355
455
  def test_target_label(test_spec)
356
- "#{label}-#{test_spec.test_type.capitalize}-#{test_spec.name.split('/')[1..-1].join('-')}"
456
+ "#{label}-#{test_spec.test_type.capitalize}-#{subspec_label(test_spec)}"
357
457
  end
358
458
 
359
- # @param [Specification] test_spec
360
- # The test spec this embed frameworks script path is for.
459
+ # @param [Specification] app_spec
460
+ # The app spec to use for producing the app label.
361
461
  #
362
- # @return [Pathname] The absolute path of the copy resources script for the given test type.
462
+ # @return [String] The derived name of the app target.
363
463
  #
364
- def copy_resources_script_path_for_test_spec(test_spec)
365
- support_files_dir + "#{test_target_label(test_spec)}-resources.sh"
464
+ def app_target_label(app_spec)
465
+ "#{label}-#{subspec_label(app_spec)}"
366
466
  end
367
467
 
368
- # @param [Specification] test_spec
369
- # The test spec this embed frameworks script path is for.
468
+ def non_library_spec_label(spec)
469
+ case spec.spec_type
470
+ when :test then test_target_label(spec)
471
+ when :app then app_target_label(spec)
472
+ else raise ArgumentError, "Unhandled spec type #{spec.spec_type.inspect} for #{spec.inspect}"
473
+ end
474
+ end
475
+
476
+ # @param [Specification] spec
477
+ # The spec to return scheme configuration for.
370
478
  #
371
- # @return [Pathname] The absolute path of the embed frameworks script for the given test type.
479
+ # @return [Hash] The scheme configuration used or empty if none is specified.
372
480
  #
373
- def embed_frameworks_script_path_for_test_spec(test_spec)
374
- support_files_dir + "#{test_target_label(test_spec)}-frameworks.sh"
481
+ def scheme_for_spec(spec)
482
+ spec.consumer(platform).scheme
375
483
  end
376
484
 
377
- # @param [Specification] test_spec
378
- # The test spec this Info.plist path is for.
485
+ # @param [Specification] spec
486
+ # The spec this copy resources script path is for.
379
487
  #
380
- # @return [Pathname] The absolute path of the Info.plist for the given test type.
488
+ # @return [Pathname] The absolute path of the copy resources script for the given spec.
381
489
  #
382
- def info_plist_path_for_test_spec(test_spec)
383
- support_files_dir + "#{test_target_label(test_spec)}-Info.plist"
490
+ def copy_resources_script_path_for_spec(spec)
491
+ support_files_dir + "#{non_library_spec_label(spec)}-resources.sh"
384
492
  end
385
493
 
386
- # @param [Specification] test_spec
387
- # The test spec this prefix header path is for.
494
+ # @param [Specification] spec
495
+ # The spec this copy resources script path is for.
388
496
  #
389
- # @return [Pathname] the absolute path of the prefix header file for the given test type.
497
+ # @return [Pathname] The absolute path of the copy resources script input file list for the given spec.
390
498
  #
391
- def prefix_header_path_for_test_spec(test_spec)
392
- support_files_dir + "#{test_target_label(test_spec)}-prefix.pch"
499
+ def copy_resources_script_input_files_path_for_spec(spec)
500
+ support_files_dir + "#{non_library_spec_label(spec)}-resources-input-files.xcfilelist"
501
+ end
502
+
503
+ # @param [Specification] spec
504
+ # The spec this copy resources script path is for.
505
+ #
506
+ # @return [Pathname] The absolute path of the copy resources script output file list for the given spec.
507
+ #
508
+ def copy_resources_script_output_files_path_for_spec(spec)
509
+ support_files_dir + "#{non_library_spec_label(spec)}-resources-output-files.xcfilelist"
510
+ end
511
+
512
+ # @param [Specification] spec
513
+ # The spec this embed frameworks script path is for.
514
+ #
515
+ # @return [Pathname] The absolute path of the embed frameworks script for the given spec.
516
+ #
517
+ def embed_frameworks_script_path_for_spec(spec)
518
+ support_files_dir + "#{non_library_spec_label(spec)}-frameworks.sh"
519
+ end
520
+
521
+ # @param [Specification] spec
522
+ # The spec this embed frameworks script path is for.
523
+ #
524
+ # @return [Pathname] The absolute path of the embed frameworks script input file list for the given spec.
525
+ #
526
+ def embed_frameworks_script_input_files_path_for_spec(spec)
527
+ support_files_dir + "#{non_library_spec_label(spec)}-frameworks-input-files.xcfilelist"
528
+ end
529
+
530
+ # @param [Specification] spec
531
+ # The spec this embed frameworks script path is for.
532
+ #
533
+ # @return [Pathname] The absolute path of the embed frameworks script output file list for the given spec.
534
+ #
535
+ def embed_frameworks_script_output_files_path_for_spec(spec)
536
+ support_files_dir + "#{non_library_spec_label(spec)}-frameworks-output-files.xcfilelist"
537
+ end
538
+
539
+ # @param [Specification] spec
540
+ # The spec this Info.plist path is for.
541
+ #
542
+ # @return [Pathname] The absolute path of the Info.plist for the given spec.
543
+ #
544
+ def info_plist_path_for_spec(spec)
545
+ support_files_dir + "#{non_library_spec_label(spec)}-Info.plist"
546
+ end
547
+
548
+ # @param [Specification] spec
549
+ # The spec this prefix header path is for.
550
+ #
551
+ # @return [Pathname] the absolute path of the prefix header file for the given spec.
552
+ #
553
+ def prefix_header_path_for_spec(spec)
554
+ support_files_dir + "#{non_library_spec_label(spec)}-prefix.pch"
393
555
  end
394
556
 
395
557
  # @return [Array<String>] The names of the Pods on which this target
@@ -450,6 +612,39 @@ module Pod
450
612
  [self, *recursive_dependent_targets, *recursive_test_dependent_targets(test_spec)].uniq
451
613
  end
452
614
 
615
+ # @param [Specification] app_spec
616
+ # the app spec to scope dependencies for
617
+ #
618
+ # @return [Array<PodTarget>] the recursive targets that this target has a
619
+ # app dependency upon.
620
+ #
621
+ def recursive_app_dependent_targets(app_spec)
622
+ @recursive_app_dependent_targets ||= {}
623
+ @recursive_app_dependent_targets[app_spec] ||= _add_recursive_app_dependent_targets(app_spec, Set.new).to_a
624
+ end
625
+
626
+ def _add_recursive_app_dependent_targets(app_spec, set)
627
+ raise ArgumentError, 'Must give a app spec' unless app_spec
628
+ return unless dependent_targets = app_dependent_targets_by_spec_name[app_spec.name]
629
+
630
+ dependent_targets.each do |target|
631
+ target._add_recursive_dependent_targets(set) if set.add?(target)
632
+ end
633
+
634
+ set
635
+ end
636
+ private :_add_recursive_app_dependent_targets
637
+
638
+ # @param [Specification] app_spec
639
+ # the app spec to scope dependencies for
640
+ #
641
+ # @return [Array<PodTarget>] the canonical list of dependent targets this target has a dependency upon.
642
+ # This list includes the target itself as well as its recursive dependent and app dependent targets.
643
+ #
644
+ def dependent_targets_for_app_spec(app_spec)
645
+ [self, *recursive_dependent_targets, *recursive_app_dependent_targets(app_spec)].uniq
646
+ end
647
+
453
648
  # Checks if warnings should be inhibited for this pod.
454
649
  #
455
650
  # @return [Bool]
@@ -468,11 +663,11 @@ module Pod
468
663
  whitelists.first
469
664
  else
470
665
  UI.warn "The pod `#{pod_name}` is linked to different targets " \
471
- "(#{target_definitions.map(&:label)}), which contain different " \
666
+ "(#{target_definitions.map { |td| "`#{td.label}`" }.to_sentence}), which contain different " \
472
667
  'settings to inhibit warnings. CocoaPods does not currently ' \
473
668
  'support different settings and will fall back to your preference ' \
474
669
  'set in the root target definition.'
475
- podfile.root_target_definitions.first.inhibits_warnings_for_pod?(root_spec.name)
670
+ @inhibit_warnings = podfile.root_target_definitions.first.inhibits_warnings_for_pod?(root_spec.name)
476
671
  end
477
672
  end
478
673
 
@@ -512,24 +707,40 @@ module Pod
512
707
  # @param [Boolean] include_dependent_targets_for_test_spec
513
708
  # whether to include header search paths for test dependent targets
514
709
  #
710
+ # @param [Boolean] include_dependent_targets_for_app_spec
711
+ # whether to include header search paths for app dependent targets
712
+ #
515
713
  # @param [Boolean] include_private_headers
516
714
  # whether to include header search paths for private headers of this
517
715
  # target
518
716
  #
519
717
  # @return [Array<String>] The set of header search paths this target uses.
520
718
  #
521
- def header_search_paths(include_dependent_targets_for_test_spec: nil, include_private_headers: true)
719
+ def header_search_paths(include_dependent_targets_for_test_spec: nil, include_dependent_targets_for_app_spec: nil, include_private_headers: true)
522
720
  header_search_paths = []
523
721
  header_search_paths.concat(build_headers.search_paths(platform, nil, false)) if include_private_headers
524
722
  header_search_paths.concat(sandbox.public_headers.search_paths(platform, pod_name, uses_modular_headers?))
525
723
  dependent_targets = recursive_dependent_targets
526
724
  dependent_targets += recursive_test_dependent_targets(include_dependent_targets_for_test_spec) if include_dependent_targets_for_test_spec
725
+ dependent_targets += recursive_app_dependent_targets(include_dependent_targets_for_app_spec) if include_dependent_targets_for_app_spec
527
726
  dependent_targets.uniq.each do |dependent_target|
528
727
  header_search_paths.concat(sandbox.public_headers.search_paths(platform, dependent_target.pod_name, defines_module? && dependent_target.uses_modular_headers?(false)))
529
728
  end
530
729
  header_search_paths.uniq
531
730
  end
532
731
 
732
+ # @param [Specification] spec
733
+ #
734
+ # @return [BuildSettings::PodTargetSettings] The build settings for the given spec
735
+ #
736
+ def build_settings_for_spec(spec)
737
+ case spec.spec_type
738
+ when :test then test_spec_build_settings[spec.name]
739
+ when :app then app_spec_build_settings[spec.name]
740
+ else build_settings
741
+ end || raise(ArgumentError, "No build settings for #{spec}")
742
+ end
743
+
533
744
  protected
534
745
 
535
746
  # Returns whether the pod target should use modular headers.
@@ -552,5 +763,51 @@ module Pod
552
763
  def create_build_settings
553
764
  BuildSettings::PodTargetSettings.new(self)
554
765
  end
766
+
767
+ def create_test_build_settings
768
+ Hash[test_specs.map do |test_spec|
769
+ [test_spec.name, BuildSettings::PodTargetSettings.new(self, test_spec)]
770
+ end]
771
+ end
772
+
773
+ def create_app_build_settings
774
+ Hash[app_specs.map do |app_spec|
775
+ [app_spec.name, BuildSettings::PodTargetSettings.new(self, app_spec)]
776
+ end]
777
+ end
778
+
779
+ # Computes the destination sub-directory in the sandbox
780
+ #
781
+ # @param [Sandbox::FileAccessor] file_accessor
782
+ # The consumer file accessor for which the headers need to be
783
+ # linked.
784
+ #
785
+ # @param [Array<Pathname>] headers
786
+ # The absolute paths of the headers which need to be mapped.
787
+ #
788
+ # @return [Hash{Pathname => Array<Pathname>}] A hash containing the
789
+ # headers folders as the keys and the absolute paths of the
790
+ # header files as the values.
791
+ #
792
+ def header_mappings(file_accessor, headers)
793
+ consumer = file_accessor.spec_consumer
794
+ header_mappings_dir = consumer.header_mappings_dir
795
+ dir = headers_sandbox
796
+ dir += consumer.header_dir if consumer.header_dir
797
+
798
+ mappings = {}
799
+ headers.each do |header|
800
+ next if header.to_s.include?('.framework/')
801
+
802
+ sub_dir = dir
803
+ if header_mappings_dir
804
+ relative_path = header.relative_path_from(file_accessor.path_list.root + header_mappings_dir)
805
+ sub_dir += relative_path.dirname
806
+ end
807
+ mappings[sub_dir] ||= []
808
+ mappings[sub_dir] << header
809
+ end
810
+ mappings
811
+ end
555
812
  end
556
813
  end