xcocoapods 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +6303 -0
  3. data/LICENSE +28 -0
  4. data/README.md +80 -0
  5. data/bin/pod +56 -0
  6. data/bin/sandbox-pod +168 -0
  7. data/lib/cocoapods.rb +73 -0
  8. data/lib/cocoapods/command.rb +175 -0
  9. data/lib/cocoapods/command/cache.rb +28 -0
  10. data/lib/cocoapods/command/cache/clean.rb +90 -0
  11. data/lib/cocoapods/command/cache/list.rb +69 -0
  12. data/lib/cocoapods/command/env.rb +66 -0
  13. data/lib/cocoapods/command/init.rb +128 -0
  14. data/lib/cocoapods/command/install.rb +45 -0
  15. data/lib/cocoapods/command/ipc.rb +19 -0
  16. data/lib/cocoapods/command/ipc/list.rb +40 -0
  17. data/lib/cocoapods/command/ipc/podfile.rb +31 -0
  18. data/lib/cocoapods/command/ipc/podfile_json.rb +30 -0
  19. data/lib/cocoapods/command/ipc/repl.rb +51 -0
  20. data/lib/cocoapods/command/ipc/spec.rb +29 -0
  21. data/lib/cocoapods/command/ipc/update_search_index.rb +24 -0
  22. data/lib/cocoapods/command/lib.rb +11 -0
  23. data/lib/cocoapods/command/lib/create.rb +105 -0
  24. data/lib/cocoapods/command/lib/lint.rb +121 -0
  25. data/lib/cocoapods/command/list.rb +39 -0
  26. data/lib/cocoapods/command/options/project_directory.rb +36 -0
  27. data/lib/cocoapods/command/options/repo_update.rb +34 -0
  28. data/lib/cocoapods/command/outdated.rb +140 -0
  29. data/lib/cocoapods/command/repo.rb +29 -0
  30. data/lib/cocoapods/command/repo/add.rb +103 -0
  31. data/lib/cocoapods/command/repo/lint.rb +82 -0
  32. data/lib/cocoapods/command/repo/list.rb +93 -0
  33. data/lib/cocoapods/command/repo/push.rb +281 -0
  34. data/lib/cocoapods/command/repo/remove.rb +36 -0
  35. data/lib/cocoapods/command/repo/update.rb +28 -0
  36. data/lib/cocoapods/command/setup.rb +103 -0
  37. data/lib/cocoapods/command/spec.rb +112 -0
  38. data/lib/cocoapods/command/spec/cat.rb +51 -0
  39. data/lib/cocoapods/command/spec/create.rb +283 -0
  40. data/lib/cocoapods/command/spec/edit.rb +87 -0
  41. data/lib/cocoapods/command/spec/env_spec.rb +53 -0
  42. data/lib/cocoapods/command/spec/lint.rb +137 -0
  43. data/lib/cocoapods/command/spec/which.rb +43 -0
  44. data/lib/cocoapods/command/update.rb +101 -0
  45. data/lib/cocoapods/config.rb +347 -0
  46. data/lib/cocoapods/core_overrides.rb +1 -0
  47. data/lib/cocoapods/downloader.rb +190 -0
  48. data/lib/cocoapods/downloader/cache.rb +233 -0
  49. data/lib/cocoapods/downloader/request.rb +86 -0
  50. data/lib/cocoapods/downloader/response.rb +16 -0
  51. data/lib/cocoapods/executable.rb +222 -0
  52. data/lib/cocoapods/external_sources.rb +57 -0
  53. data/lib/cocoapods/external_sources/abstract_external_source.rb +205 -0
  54. data/lib/cocoapods/external_sources/downloader_source.rb +30 -0
  55. data/lib/cocoapods/external_sources/path_source.rb +55 -0
  56. data/lib/cocoapods/external_sources/podspec_source.rb +54 -0
  57. data/lib/cocoapods/gem_version.rb +5 -0
  58. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  59. data/lib/cocoapods/generator/acknowledgements/markdown.rb +44 -0
  60. data/lib/cocoapods/generator/acknowledgements/plist.rb +94 -0
  61. data/lib/cocoapods/generator/app_target_helper.rb +244 -0
  62. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  63. data/lib/cocoapods/generator/constant.rb +19 -0
  64. data/lib/cocoapods/generator/copy_resources_script.rb +230 -0
  65. data/lib/cocoapods/generator/dummy_source.rb +31 -0
  66. data/lib/cocoapods/generator/embed_frameworks_script.rb +215 -0
  67. data/lib/cocoapods/generator/header.rb +103 -0
  68. data/lib/cocoapods/generator/info_plist_file.rb +116 -0
  69. data/lib/cocoapods/generator/module_map.rb +99 -0
  70. data/lib/cocoapods/generator/prefix_header.rb +60 -0
  71. data/lib/cocoapods/generator/umbrella_header.rb +46 -0
  72. data/lib/cocoapods/hooks_manager.rb +132 -0
  73. data/lib/cocoapods/installer.rb +703 -0
  74. data/lib/cocoapods/installer/analyzer.rb +972 -0
  75. data/lib/cocoapods/installer/analyzer/analysis_result.rb +87 -0
  76. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +98 -0
  77. data/lib/cocoapods/installer/analyzer/pod_variant.rb +67 -0
  78. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +157 -0
  79. data/lib/cocoapods/installer/analyzer/podfile_dependency_cache.rb +54 -0
  80. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +240 -0
  81. data/lib/cocoapods/installer/analyzer/specs_state.rb +84 -0
  82. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +53 -0
  83. data/lib/cocoapods/installer/analyzer/target_inspector.rb +260 -0
  84. data/lib/cocoapods/installer/installation_options.rb +158 -0
  85. data/lib/cocoapods/installer/pod_source_installer.rb +202 -0
  86. data/lib/cocoapods/installer/pod_source_preparer.rb +77 -0
  87. data/lib/cocoapods/installer/podfile_validator.rb +139 -0
  88. data/lib/cocoapods/installer/post_install_hooks_context.rb +132 -0
  89. data/lib/cocoapods/installer/pre_install_hooks_context.rb +51 -0
  90. data/lib/cocoapods/installer/source_provider_hooks_context.rb +34 -0
  91. data/lib/cocoapods/installer/user_project_integrator.rb +250 -0
  92. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +463 -0
  93. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
  94. data/lib/cocoapods/installer/xcode.rb +8 -0
  95. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +416 -0
  96. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +181 -0
  97. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +84 -0
  98. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +334 -0
  99. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +777 -0
  100. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +116 -0
  101. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +86 -0
  102. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +256 -0
  103. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +68 -0
  104. data/lib/cocoapods/installer/xcode/target_validator.rb +147 -0
  105. data/lib/cocoapods/open-uri.rb +33 -0
  106. data/lib/cocoapods/project.rb +414 -0
  107. data/lib/cocoapods/resolver.rb +585 -0
  108. data/lib/cocoapods/resolver/lazy_specification.rb +79 -0
  109. data/lib/cocoapods/sandbox.rb +404 -0
  110. data/lib/cocoapods/sandbox/file_accessor.rb +444 -0
  111. data/lib/cocoapods/sandbox/headers_store.rb +146 -0
  112. data/lib/cocoapods/sandbox/path_list.rb +220 -0
  113. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +85 -0
  114. data/lib/cocoapods/sandbox/podspec_finder.rb +23 -0
  115. data/lib/cocoapods/sources_manager.rb +157 -0
  116. data/lib/cocoapods/target.rb +261 -0
  117. data/lib/cocoapods/target/aggregate_target.rb +338 -0
  118. data/lib/cocoapods/target/build_settings.rb +1075 -0
  119. data/lib/cocoapods/target/pod_target.rb +559 -0
  120. data/lib/cocoapods/user_interface.rb +459 -0
  121. data/lib/cocoapods/user_interface/error_report.rb +187 -0
  122. data/lib/cocoapods/user_interface/inspector_reporter.rb +109 -0
  123. data/lib/cocoapods/validator.rb +981 -0
  124. metadata +533 -0
@@ -0,0 +1,777 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ class PodsProjectGenerator
5
+ # Creates the target for the Pods libraries in the Pods project and the
6
+ # relative support files.
7
+ #
8
+ class PodTargetInstaller < TargetInstaller
9
+ # @return [Array<Pathname>] Array of umbrella header paths in the headers directory
10
+ #
11
+ attr_reader :umbrella_header_paths
12
+
13
+ # Initialize a new instance
14
+ #
15
+ # @param [Sandbox] sandbox @see TargetInstaller#sandbox
16
+ # @param [Pod::Project] project @see TargetInstaller#project
17
+ # @param [Target] target @see TargetInstaller#target
18
+ # @param [Array<Pathname>] umbrella_header_paths @see #umbrella_header_paths
19
+ #
20
+ def initialize(sandbox, project, target, umbrella_header_paths = nil)
21
+ super(sandbox, project, target)
22
+ @umbrella_header_paths = umbrella_header_paths
23
+ end
24
+
25
+ # Creates the target in the Pods project and the relative support files.
26
+ #
27
+ # @return [TargetInstallationResult] the result of the installation of this target.
28
+ #
29
+ def install!
30
+ UI.message "- Installing target `#{target.name}` #{target.platform}" do
31
+ create_support_files_dir
32
+ test_file_accessors, file_accessors = target.file_accessors.partition { |fa| fa.spec.test_specification? }
33
+
34
+ unless target.should_build?
35
+ # For targets that should not be built (e.g. pre-built vendored frameworks etc), we add a placeholder
36
+ # PBXAggregateTarget that will be used to wire up dependencies later.
37
+ native_target = add_placeholder_target
38
+ resource_bundle_targets = add_resources_bundle_targets(file_accessors).values.flatten
39
+ create_xcconfig_file(native_target, resource_bundle_targets)
40
+ return TargetInstallationResult.new(target, native_target, resource_bundle_targets)
41
+ end
42
+
43
+ native_target = add_target
44
+ resource_bundle_targets = add_resources_bundle_targets(file_accessors).values.flatten
45
+
46
+ test_native_targets = add_test_targets
47
+ test_resource_bundle_targets = add_resources_bundle_targets(test_file_accessors)
48
+
49
+ add_files_to_build_phases(native_target, test_native_targets)
50
+
51
+ create_xcconfig_file(native_target, resource_bundle_targets)
52
+ create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets.values.flatten)
53
+
54
+ if target.defines_module?
55
+ create_module_map(native_target) do |generator|
56
+ generator.headers.concat module_map_additional_headers
57
+ end
58
+ create_umbrella_header(native_target) do |generator|
59
+ generator.imports += file_accessors.flat_map do |file_accessor|
60
+ header_dir = if !target.requires_frameworks? && dir = file_accessor.spec_consumer.header_dir
61
+ Pathname.new(dir)
62
+ end
63
+
64
+ file_accessor.public_headers.map do |public_header|
65
+ public_header = if header_mappings_dir
66
+ public_header.relative_path_from(header_mappings_dir)
67
+ else
68
+ public_header.basename
69
+ end
70
+ if header_dir
71
+ public_header = header_dir.join(public_header)
72
+ end
73
+ public_header
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ if target.requires_frameworks?
80
+ unless skip_info_plist?(native_target)
81
+ create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform)
82
+ end
83
+ create_build_phase_to_symlink_header_folders(native_target)
84
+ elsif target.uses_swift?
85
+ add_swift_static_library_compatibility_header_phase(native_target)
86
+ end
87
+
88
+ unless skip_pch?(target.non_test_specs)
89
+ path = target.prefix_header_path
90
+ create_prefix_header(path, file_accessors, target.platform, [native_target])
91
+ end
92
+ unless skip_pch?(target.test_specs)
93
+ target.supported_test_types.each do |test_type|
94
+ path = target.prefix_header_path_for_test_type(test_type)
95
+ create_prefix_header(path, test_file_accessors, target.platform, test_native_targets)
96
+ end
97
+ end
98
+ create_dummy_source(native_target)
99
+ clean_support_files_temp_dir
100
+ TargetInstallationResult.new(target, native_target, resource_bundle_targets, test_native_targets,
101
+ test_resource_bundle_targets)
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ # @param [Array<Specification>] specs
108
+ # the specs to check against whether `.pch` generation should be skipped or not.
109
+ #
110
+ # @return [Boolean] Whether the target should build a pch file.
111
+ #
112
+ def skip_pch?(specs)
113
+ specs.any? { |spec| spec.prefix_header_file.is_a?(FalseClass) }
114
+ end
115
+
116
+ # True if info.plist generation should be skipped
117
+ #
118
+ # @param [PXNativeTarget] native_target
119
+ #
120
+ # @return [Boolean] Whether the target should build an Info.plist file
121
+ #
122
+ def skip_info_plist?(native_target)
123
+ return true if target.static_framework?
124
+ existing_setting = native_target.resolved_build_setting('INFOPLIST_FILE', true).values.compact
125
+ !existing_setting.empty?
126
+ end
127
+
128
+ # Remove the default headers folder path settings for static library pod
129
+ # targets.
130
+ #
131
+ # @return [Hash{String => String}]
132
+ #
133
+ def custom_build_settings
134
+ settings = super
135
+ unless target.requires_frameworks?
136
+ settings['PRIVATE_HEADERS_FOLDER_PATH'] = ''
137
+ settings['PUBLIC_HEADERS_FOLDER_PATH'] = ''
138
+ end
139
+
140
+ settings['PRODUCT_NAME'] = target.product_basename
141
+ settings['PRODUCT_MODULE_NAME'] = target.product_module_name
142
+
143
+ settings['CODE_SIGN_IDENTITY[sdk=appletvos*]'] = ''
144
+ settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'] = ''
145
+ settings['CODE_SIGN_IDENTITY[sdk=watchos*]'] = ''
146
+
147
+ settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = '$(inherited) '
148
+
149
+ if target.swift_version
150
+ settings['SWIFT_VERSION'] = target.swift_version
151
+ end
152
+
153
+ settings
154
+ end
155
+
156
+ # Filters the given resource file references discarding empty paths which are
157
+ # added by their parent directory. This will also include references to the parent [PBXVariantGroup]
158
+ # for all resources underneath it.
159
+ #
160
+ # @param [Array<Pathname>] resource_file_references
161
+ # The array of all resource file references to filter.
162
+ #
163
+ # @yield_param [Array<PBXFileReference>} The filtered resource file references to be installed
164
+ # in the copy resources phase.
165
+ #
166
+ # @yield_param [Array<PBXFileReference>} The filtered resource file references to be installed
167
+ # in the compile sources phase.
168
+ #
169
+ # @note Core Data model directories (.xcdatamodeld) used to be added to the
170
+ # `Copy Resources` build phase like all other resources, since they would
171
+ # compile correctly in either the resources or compile phase. In recent
172
+ # versions of xcode, there's an exception for data models that generate
173
+ # headers. These need to be added to the compile sources phase of a real
174
+ # target for the headers to be built in time for code in the target to
175
+ # use them. These kinds of models generally break when added to resource
176
+ # bundles.
177
+ #
178
+ def filter_resource_file_references(resource_file_references)
179
+ file_references = resource_file_references.map do |resource_file_reference|
180
+ ref = project.reference_for_path(resource_file_reference)
181
+
182
+ # Some nested files are not directly present in the Xcode project, such as the contents
183
+ # of an .xcdatamodeld directory. These files are implicitly included by including their
184
+ # parent directory.
185
+ next if ref.nil?
186
+
187
+ # For variant groups, the variant group itself is added, not its members.
188
+ next ref.parent if ref.parent.is_a?(Xcodeproj::Project::Object::PBXVariantGroup)
189
+
190
+ ref
191
+ end.compact.uniq
192
+ compile_phase_matcher = lambda { |ref| !(ref.path =~ /.*\.xcdatamodeld/i).nil? }
193
+ resources_phase_refs = file_references.reject(&compile_phase_matcher)
194
+ compile_phase_refs = file_references.select(&compile_phase_matcher)
195
+ yield resources_phase_refs, compile_phase_refs
196
+ end
197
+
198
+ #-----------------------------------------------------------------------#
199
+
200
+ # Adds the build files of the pods to the target and adds a reference to
201
+ # the frameworks of the Pods.
202
+ #
203
+ # @note The Frameworks are used only for presentation purposes as the
204
+ # xcconfig is the authoritative source about their information.
205
+ #
206
+ # @note Core Data model directories (.xcdatamodeld) defined in the `resources`
207
+ # property are currently added to the `Copy Resources` build phase like
208
+ # all other resources. The Xcode UI adds these to the `Compile Sources`
209
+ # build phase, but they will compile correctly either way.
210
+ #
211
+ # @return [void]
212
+ #
213
+ def add_files_to_build_phases(native_target, test_native_targets)
214
+ target.file_accessors.each do |file_accessor|
215
+ consumer = file_accessor.spec_consumer
216
+
217
+ native_target = if !consumer.spec.test_specification?
218
+ native_target
219
+ else
220
+ test_native_target_from_spec_consumer(consumer, test_native_targets)
221
+ end
222
+
223
+ headers = file_accessor.headers
224
+ public_headers = file_accessor.public_headers.map(&:realpath)
225
+ private_headers = file_accessor.private_headers.map(&:realpath)
226
+ other_source_files = file_accessor.other_source_files
227
+
228
+ {
229
+ true => file_accessor.arc_source_files,
230
+ false => file_accessor.non_arc_source_files,
231
+ }.each do |arc, files|
232
+ next if files.empty?
233
+ files = files - headers - other_source_files
234
+ flags = compiler_flags_for_consumer(consumer, arc)
235
+ regular_file_refs = project_file_references_array(files, 'source')
236
+ native_target.add_file_references(regular_file_refs, flags)
237
+ end
238
+
239
+ header_file_refs = project_file_references_array(headers, 'header')
240
+ native_target.add_file_references(header_file_refs) do |build_file|
241
+ add_header(build_file, public_headers, private_headers, native_target)
242
+ end
243
+
244
+ other_file_refs = project_file_references_array(other_source_files, 'other source')
245
+ native_target.add_file_references(other_file_refs, nil)
246
+
247
+ next unless target.requires_frameworks?
248
+
249
+ filter_resource_file_references(file_accessor.resources.flatten) do |resource_phase_refs, compile_phase_refs|
250
+ native_target.add_file_references(compile_phase_refs, nil)
251
+ native_target.add_resources(resource_phase_refs)
252
+ end
253
+ end
254
+ end
255
+
256
+ # Adds the test targets for the library to the Pods project with the
257
+ # appropriate build configurations.
258
+ #
259
+ # @return [Array<PBXNativeTarget>] the test native targets created.
260
+ #
261
+ def add_test_targets
262
+ target.supported_test_types.map do |test_type|
263
+ product_type = target.product_type_for_test_type(test_type)
264
+ name = target.test_target_label(test_type)
265
+ platform_name = target.platform.name
266
+ language = target.uses_swift_for_test_type?(test_type) ? :swift : :objc
267
+ test_native_target = project.new_target(product_type, name, platform_name, deployment_target, nil, language)
268
+ test_native_target.product_reference.name = name
269
+
270
+ target.user_build_configurations.each do |bc_name, type|
271
+ test_native_target.add_build_configuration(bc_name, type)
272
+ end
273
+
274
+ test_native_target.build_configurations.each do |configuration|
275
+ configuration.build_settings.merge!(custom_build_settings)
276
+ # target_installer will automatically add an empty `OTHER_LDFLAGS`. For test
277
+ # targets those are set via a test xcconfig file instead.
278
+ configuration.build_settings.delete('OTHER_LDFLAGS')
279
+ # target_installer will automatically set the product name to the module name if the target
280
+ # requires frameworks. For tests we always use the test target name as the product name
281
+ # irrelevant to whether we use frameworks or not.
282
+ configuration.build_settings['PRODUCT_NAME'] = name
283
+ # Use xcode default product module name, which is $(PRODUCT_NAME:c99extidentifier)
284
+ # this gives us always valid name that is distinct from the parent spec module name
285
+ # which allow tests to use either import or @testable import to access the parent framework
286
+ configuration.build_settings.delete('PRODUCT_MODULE_NAME')
287
+ # We must codesign iOS XCTest bundles that contain binary frameworks to allow them to be launchable in the simulator
288
+ unless target.platform == :osx
289
+ configuration.build_settings['CODE_SIGNING_REQUIRED'] = 'YES'
290
+ configuration.build_settings['CODE_SIGNING_ALLOWED'] = 'YES'
291
+ end
292
+ # For macOS we do not code sign the XCTest bundle because we do not code sign the frameworks either.
293
+ configuration.build_settings['CODE_SIGN_IDENTITY'] = '' if target.platform == :osx
294
+ end
295
+
296
+ # Test native targets also need frameworks and resources to be copied over to their xctest bundle.
297
+ create_test_target_embed_frameworks_script(test_type)
298
+ create_test_target_copy_resources_script(test_type)
299
+
300
+ # Generate vanila Info.plist for test target similar to the one xcode gererates for new test target.
301
+ # This creates valid test bundle accessible at the runtime, allowing tests to load bundle resources
302
+ # defined in podspec.
303
+ create_info_plist_file(target.info_plist_path_for_test_type(test_type), test_native_target, '1.0', target.platform, :bndl)
304
+
305
+ test_native_target
306
+ end
307
+ end
308
+
309
+ # Adds the resources of the Pods to the Pods project.
310
+ #
311
+ # @note The source files are grouped by Pod and in turn by subspec
312
+ # (recursively) in the resources group.
313
+ #
314
+ # @param [Array<Sandbox::FileAccessor>] file_accessors
315
+ # the file accessors list to generate resource bundles for.
316
+ #
317
+ # @return [Array<PBXNativeTarget] the resource bundle native targets created.
318
+ #
319
+ def add_resources_bundle_targets(file_accessors)
320
+ file_accessors.each_with_object({}) do |file_accessor, hash|
321
+ hash[file_accessor.spec.name] = file_accessor.resource_bundles.map do |bundle_name, paths|
322
+ label = target.resources_bundle_target_label(bundle_name)
323
+ resource_bundle_target = project.new_resources_bundle(label, file_accessor.spec_consumer.platform_name)
324
+ resource_bundle_target.product_reference.tap do |bundle_product|
325
+ bundle_file_name = "#{bundle_name}.bundle"
326
+ bundle_product.name = bundle_file_name
327
+ end
328
+
329
+ filter_resource_file_references(paths) do |resource_phase_refs, compile_phase_refs|
330
+ # Resource bundles are only meant to have resources, so install everything
331
+ # into the resources phase. See note in filter_resource_file_references.
332
+ resource_bundle_target.add_resources(resource_phase_refs + compile_phase_refs)
333
+ end
334
+
335
+ target.user_build_configurations.each do |bc_name, type|
336
+ resource_bundle_target.add_build_configuration(bc_name, type)
337
+ end
338
+ resource_bundle_target.deployment_target = deployment_target
339
+
340
+ # Create Info.plist file for bundle
341
+ path = target.info_plist_path
342
+ path.dirname.mkdir unless path.dirname.exist?
343
+ info_plist_path = path.dirname + "ResourceBundle-#{bundle_name}-#{path.basename}"
344
+ create_info_plist_file(info_plist_path, resource_bundle_target, target.version, target.platform, :bndl)
345
+
346
+ resource_bundle_target.build_configurations.each do |c|
347
+ c.build_settings['PRODUCT_NAME'] = bundle_name
348
+ # Do not set the CONFIGURATION_BUILD_DIR for resource bundles that are only meant for test targets.
349
+ # This is because the test target itself also does not set this configuration build dir and it expects
350
+ # all bundles to be copied from the default path.
351
+ unless file_accessor.spec.test_specification?
352
+ c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir('$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)')
353
+ end
354
+
355
+ # Set the correct device family for this bundle, based on the platform
356
+ device_family_by_platform = {
357
+ :ios => '1,2',
358
+ :tvos => '3',
359
+ :watchos => '1,2' # The device family for watchOS is 4, but Xcode creates watchkit-compatible bundles as 1,2
360
+ }
361
+
362
+ if (family = device_family_by_platform[target.platform.name])
363
+ c.build_settings['TARGETED_DEVICE_FAMILY'] = family
364
+ end
365
+ end
366
+
367
+ resource_bundle_target
368
+ end
369
+ end
370
+ end
371
+
372
+ # Generates the contents of the xcconfig file and saves it to disk.
373
+ #
374
+ # @param [PBXNativeTarget] native_target
375
+ # the native target to link the xcconfig file into.
376
+ #
377
+ # @param [Array<PBXNativeTarget>] resource_bundle_targets
378
+ # the additional resource bundle targets to link the xcconfig file into.
379
+ #
380
+ # @return [void]
381
+ #
382
+ def create_xcconfig_file(native_target, resource_bundle_targets)
383
+ path = target.xcconfig_path
384
+ update_changed_file(target.build_settings, path)
385
+ xcconfig_file_ref = add_file_to_support_group(path)
386
+
387
+ native_target.build_configurations.each do |c|
388
+ c.base_configuration_reference = xcconfig_file_ref
389
+ end
390
+
391
+ # also apply the private config to resource bundle targets.
392
+ apply_xcconfig_file_ref_to_resource_bundle_targets(resource_bundle_targets, xcconfig_file_ref)
393
+ end
394
+
395
+ # Generates the contents of the xcconfig file used for each test target type and saves it to disk.
396
+ #
397
+ # @param [Array<PBXNativeTarget>] test_native_targets
398
+ # the test native target to link the xcconfig file into.
399
+ #
400
+ # @param [Array<PBXNativeTarget>] test_resource_bundle_targets
401
+ # the additional test resource bundle targets to link the xcconfig file into.
402
+ #
403
+ # @return [void]
404
+ #
405
+ def create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets)
406
+ target.test_specs.each do |test_spec|
407
+ spec_consumer = test_spec.consumer(target.platform)
408
+ test_type = spec_consumer.test_type
409
+ path = target.xcconfig_path(test_type.to_s)
410
+ update_changed_file(Target::BuildSettings::PodTargetSettings.new(target, test_spec), path)
411
+ xcconfig_file_ref = add_file_to_support_group(path)
412
+
413
+ test_native_targets.each do |test_target|
414
+ test_target.build_configurations.each do |test_target_bc|
415
+ test_target_swift_debug_hack(test_target_bc)
416
+ test_target_bc.base_configuration_reference = xcconfig_file_ref
417
+ end
418
+ end
419
+
420
+ # also apply the private config to resource bundle test targets.
421
+ apply_xcconfig_file_ref_to_resource_bundle_targets(test_resource_bundle_targets, xcconfig_file_ref)
422
+ end
423
+ end
424
+
425
+ # Creates a script that copies the resources to the bundle of the test target.
426
+ #
427
+ # @param [Symbol] test_type
428
+ # The test type to create the script for.
429
+ #
430
+ # @return [void]
431
+ #
432
+ def create_test_target_copy_resources_script(test_type)
433
+ path = target.copy_resources_script_path_for_test_type(test_type)
434
+ pod_targets = target.all_dependent_targets
435
+ resource_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config|
436
+ resources_by_config[config] = pod_targets.flat_map do |pod_target|
437
+ spec_paths_to_include = pod_target == target ? pod_target.specs.map(&:name) : pod_target.non_test_specs.map(&:name)
438
+ pod_target.resource_paths.values_at(*spec_paths_to_include).flatten.compact
439
+ end
440
+ end
441
+ generator = Generator::CopyResourcesScript.new(resource_paths_by_config, target.platform)
442
+ update_changed_file(generator, path)
443
+ add_file_to_support_group(path)
444
+ end
445
+
446
+ # Creates a script that embeds the frameworks to the bundle of the test target.
447
+ #
448
+ # @param [Symbol] test_type
449
+ # The test type to create the script for.
450
+ #
451
+ # @return [void]
452
+ #
453
+ def create_test_target_embed_frameworks_script(test_type)
454
+ path = target.embed_frameworks_script_path_for_test_type(test_type)
455
+ pod_targets = target.all_dependent_targets
456
+ framework_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, paths_by_config|
457
+ paths_by_config[config] = pod_targets.flat_map do |pod_target|
458
+ spec_paths_to_include = pod_target == target ? pod_target.specs.map(&:name) : pod_target.non_test_specs.map(&:name)
459
+ pod_target.framework_paths.values_at(*spec_paths_to_include).flatten.compact.uniq
460
+ end
461
+ end
462
+ generator = Generator::EmbedFrameworksScript.new(framework_paths_by_config)
463
+ update_changed_file(generator, path)
464
+ add_file_to_support_group(path)
465
+ end
466
+
467
+ # Manually add `libswiftSwiftOnoneSupport.dylib` as it seems there is an issue with tests that do not include it for Debug configurations.
468
+ # Possibly related to Swift module optimization.
469
+ #
470
+ # @return [void]
471
+ #
472
+ def test_target_swift_debug_hack(test_target_bc)
473
+ return unless test_target_bc.debug?
474
+ return unless target.all_dependent_targets.any?(&:uses_swift?)
475
+ ldflags = test_target_bc.build_settings['OTHER_LDFLAGS'] ||= '$(inherited)'
476
+ ldflags << ' -lswiftSwiftOnoneSupport'
477
+ end
478
+
479
+ # Creates a build phase which links the versioned header folders
480
+ # of the OS X into the framework bundle's root root directory.
481
+ # This is only necessary because the way how headers are copied
482
+ # via custom copy file build phases in combination with
483
+ # header_mappings_dir interferes with xcodebuild's expectations
484
+ # about the existence of private or public headers.
485
+ #
486
+ # @param [PBXNativeTarget] native_target
487
+ # the native target to add the script phase into.
488
+ #
489
+ # @return [void]
490
+ #
491
+ def create_build_phase_to_symlink_header_folders(native_target)
492
+ return unless target.platform.name == :osx && header_mappings_dir
493
+
494
+ build_phase = native_target.new_shell_script_build_phase('Create Symlinks to Header Folders')
495
+ build_phase.shell_script = <<-eos.strip_heredoc
496
+ base="$CONFIGURATION_BUILD_DIR/$WRAPPER_NAME"
497
+ ln -fs "$base/${PUBLIC_HEADERS_FOLDER_PATH\#$WRAPPER_NAME/}" "$base/${PUBLIC_HEADERS_FOLDER_PATH\#\$CONTENTS_FOLDER_PATH/}"
498
+ ln -fs "$base/${PRIVATE_HEADERS_FOLDER_PATH\#\$WRAPPER_NAME/}" "$base/${PRIVATE_HEADERS_FOLDER_PATH\#\$CONTENTS_FOLDER_PATH/}"
499
+ eos
500
+ end
501
+
502
+ # Creates a prefix header file which imports `UIKit` or `Cocoa` according
503
+ # to the platform of the target. This file also include any prefix header
504
+ # content reported by the specification of the pods.
505
+ #
506
+ # @param [Pathname] path
507
+ # the path to generate the prefix header for.
508
+ #
509
+ # @param [Array<Sandbox::FileAccessor>] file_accessors
510
+ # the file accessors to use for this prefix header that point to a path of a prefix header.
511
+ #
512
+ # @param [Platform] platform
513
+ # the platform to use for this prefix header.
514
+ #
515
+ # @param [Array<PBXNativeTarget>] native_targets
516
+ # the native targets on which the prefix header should be configured for.
517
+ #
518
+ # @return [void]
519
+ #
520
+ def create_prefix_header(path, file_accessors, platform, native_targets)
521
+ generator = Generator::PrefixHeader.new(file_accessors, platform)
522
+ update_changed_file(generator, path)
523
+ add_file_to_support_group(path)
524
+
525
+ native_targets.each do |native_target|
526
+ native_target.build_configurations.each do |c|
527
+ relative_path = path.relative_path_from(project.path.dirname)
528
+ c.build_settings['GCC_PREFIX_HEADER'] = relative_path.to_s
529
+ end
530
+ end
531
+ end
532
+
533
+ ENABLE_OBJECT_USE_OBJC_FROM = {
534
+ :ios => Version.new('6'),
535
+ :osx => Version.new('10.8'),
536
+ :watchos => Version.new('2.0'),
537
+ :tvos => Version.new('9.0'),
538
+ }.freeze
539
+
540
+ # Returns the compiler flags for the source files of the given specification.
541
+ #
542
+ # The following behavior is regarding the `OS_OBJECT_USE_OBJC` flag. When
543
+ # set to `0`, it will allow code to use `dispatch_release()` on >= iOS 6.0
544
+ # and OS X 10.8.
545
+ #
546
+ # * New libraries that do *not* require ARC don’t need to care about this
547
+ # issue at all.
548
+ #
549
+ # * New libraries that *do* require ARC _and_ have a deployment target of
550
+ # >= iOS 6.0 or OS X 10.8:
551
+ #
552
+ # These no longer use `dispatch_release()` and should *not* have the
553
+ # `OS_OBJECT_USE_OBJC` flag set to `0`.
554
+ #
555
+ # **Note:** this means that these libraries *have* to specify the
556
+ # deployment target in order to function well.
557
+ #
558
+ # * New libraries that *do* require ARC, but have a deployment target of
559
+ # < iOS 6.0 or OS X 10.8:
560
+ #
561
+ # These contain `dispatch_release()` calls and as such need the
562
+ # `OS_OBJECT_USE_OBJC` flag set to `1`.
563
+ #
564
+ # **Note:** libraries that do *not* specify a platform version are
565
+ # assumed to have a deployment target of < iOS 6.0 or OS X 10.8.
566
+ #
567
+ # For more information, see: http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h
568
+ #
569
+ # @param [Specification::Consumer] consumer
570
+ # The consumer for the specification for which the compiler flags
571
+ # are needed.
572
+ #
573
+ # @return [String] The compiler flags.
574
+ #
575
+ def compiler_flags_for_consumer(consumer, arc)
576
+ flags = consumer.compiler_flags.dup
577
+ if !arc
578
+ flags << '-fno-objc-arc'
579
+ else
580
+ platform_name = consumer.platform_name
581
+ spec_deployment_target = consumer.spec.deployment_target(platform_name)
582
+ if spec_deployment_target.nil? || Version.new(spec_deployment_target) < ENABLE_OBJECT_USE_OBJC_FROM[platform_name]
583
+ flags << '-DOS_OBJECT_USE_OBJC=0'
584
+ end
585
+ end
586
+ if target.inhibit_warnings?
587
+ flags << '-w -Xanalyzer -analyzer-disable-all-checks'
588
+ end
589
+ flags * ' '
590
+ end
591
+
592
+ def apply_xcconfig_file_ref_to_resource_bundle_targets(resource_bundle_targets, xcconfig_file_ref)
593
+ resource_bundle_targets.each do |rsrc_target|
594
+ rsrc_target.build_configurations.each do |rsrc_bc|
595
+ rsrc_bc.base_configuration_reference = xcconfig_file_ref
596
+ end
597
+ end
598
+ end
599
+
600
+ def create_module_map(native_target)
601
+ return super(native_target) unless custom_module_map
602
+
603
+ path = target.module_map_path_to_write
604
+ UI.message "- Copying module map file to #{UI.path(path)}" do
605
+ contents = custom_module_map.read
606
+ unless target.requires_frameworks?
607
+ contents.gsub!(/^(\s*)framework\s+(module[^{}]+){/, '\1\2{')
608
+ end
609
+ generator = Generator::Constant.new(contents)
610
+ update_changed_file(generator, path)
611
+ add_file_to_support_group(path)
612
+
613
+ linked_path = target.module_map_path
614
+ if path != linked_path
615
+ linked_path.dirname.mkpath
616
+ FileUtils.ln_sf(path, linked_path)
617
+ end
618
+
619
+ relative_path = target.module_map_path.relative_path_from(sandbox.root).to_s
620
+ native_target.build_configurations.each do |c|
621
+ c.build_settings['MODULEMAP_FILE'] = relative_path.to_s
622
+ end
623
+ end
624
+ end
625
+
626
+ def module_map_additional_headers
627
+ return [] unless umbrella_header_paths
628
+
629
+ other_paths = umbrella_header_paths - [target.umbrella_header_path]
630
+ other_paths.map do |module_map_path|
631
+ # exclude other targets umbrella headers, to avoid
632
+ # incomplete umbrella warnings
633
+ Generator::ModuleMap::Header.new(module_map_path.basename, nil, nil, nil, true)
634
+ end
635
+ end
636
+
637
+ def create_umbrella_header(native_target)
638
+ return super(native_target) unless custom_module_map
639
+ end
640
+
641
+ def custom_module_map
642
+ @custom_module_map ||= target.file_accessors.first.module_map
643
+ end
644
+
645
+ def project_file_references_array(files, file_type)
646
+ files.map do |sf|
647
+ project.reference_for_path(sf).tap do |ref|
648
+ raise Informative, "Unable to find #{file_type} ref for #{sf} for target #{target.name}." unless ref
649
+ end
650
+ end
651
+ end
652
+
653
+ def header_mappings_dir
654
+ return @header_mappings_dir if defined?(@header_mappings_dir)
655
+ file_accessor = target.file_accessors.first
656
+ @header_mappings_dir = if dir = file_accessor.spec_consumer.header_mappings_dir
657
+ file_accessor.path_list.root + dir
658
+ end
659
+ end
660
+
661
+ def add_header(build_file, public_headers, private_headers, native_target)
662
+ file_ref = build_file.file_ref
663
+ acl = if !target.requires_frameworks? # Headers are already rooted at ${PODS_ROOT}/Headers/P*/[pod]/...
664
+ 'Project'
665
+ elsif public_headers.include?(file_ref.real_path)
666
+ 'Public'
667
+ elsif private_headers.include?(file_ref.real_path)
668
+ 'Private'
669
+ else
670
+ 'Project'
671
+ end
672
+
673
+ if target.requires_frameworks? && header_mappings_dir && acl != 'Project'
674
+ relative_path = file_ref.real_path.relative_path_from(header_mappings_dir)
675
+ sub_dir = relative_path.dirname
676
+ copy_phase_name = "Copy #{sub_dir} #{acl} Headers"
677
+ copy_phase = native_target.copy_files_build_phases.find { |bp| bp.name == copy_phase_name } ||
678
+ native_target.new_copy_files_build_phase(copy_phase_name)
679
+ copy_phase.symbol_dst_subfolder_spec = :products_directory
680
+ copy_phase.dst_path = "$(#{acl.upcase}_HEADERS_FOLDER_PATH)/#{sub_dir}"
681
+ copy_phase.add_file_reference(file_ref, true)
682
+ else
683
+ build_file.settings ||= {}
684
+ build_file.settings['ATTRIBUTES'] = [acl]
685
+ end
686
+ end
687
+
688
+ def support_files_group
689
+ pod_name = target.pod_name
690
+ dir = target.support_files_dir
691
+ project.pod_support_files_group(pod_name, dir)
692
+ end
693
+
694
+ # @param [String] name
695
+ # The name of the app host.
696
+
697
+ # @param [Symbol] test_type
698
+ # The test type this Info.plist path is for.
699
+ #
700
+ # @return [Pathname] The absolute path of the Info.plist to use for an app host.
701
+ #
702
+ def app_host_info_plist_path_for_test_type(name, test_type)
703
+ project.path.dirname.+("#{name}/#{target.app_host_label(test_type)}-Info.plist")
704
+ end
705
+
706
+ def test_native_target_from_spec_consumer(spec_consumer, test_native_targets)
707
+ test_native_targets.find do |native_target|
708
+ native_target.symbol_type == target.product_type_for_test_type(spec_consumer.test_type)
709
+ end
710
+ end
711
+
712
+ # Adds a placeholder native target for the library to the Pods project with the
713
+ # appropriate build configurations.
714
+ #
715
+ # @return [PBXAggregateTarget] the native target that was added.
716
+ #
717
+ def add_placeholder_target
718
+ native_target = project.new_aggregate_target(target.label)
719
+ native_target.deployment_target = deployment_target
720
+ target.user_build_configurations.each do |bc_name, type|
721
+ native_target.add_build_configuration(bc_name, type)
722
+ end
723
+ native_target.build_configurations.each do |configuration|
724
+ configuration.build_settings['ARCHS'] = target.archs
725
+ end
726
+ native_target
727
+ end
728
+
729
+ # Adds a shell script phase, intended only for static library targets that contain swift,
730
+ # to copy the ObjC compatibility header (the -Swift.h file that the swift compiler generates)
731
+ # to the built products directory. Additionally, the script phase copies the module map, appending a `.Swift`
732
+ # submodule that references the (moved) compatibility header. Since the module map has been moved, the umbrella header
733
+ # is _also_ copied, so that it is sitting next to the module map. This is necessary for a successful archive build.
734
+ #
735
+ # @param [PBXNativeTarget] native_target
736
+ # the native target to add the Swift static library script phase into.
737
+ #
738
+ # @return [Void]
739
+ #
740
+ def add_swift_static_library_compatibility_header_phase(native_target)
741
+ if custom_module_map
742
+ raise Informative, 'Using Swift static libraries with custom module maps does not yet work.' \
743
+ "Please build #{pod_target.label} as a framework or remove the custom module map for the time being."
744
+ end
745
+
746
+ build_phase = native_target.new_shell_script_build_phase('Copy generated compatibility header')
747
+
748
+ relative_module_map_path = target.module_map_path.relative_path_from(target.sandbox.root)
749
+ relative_umbrella_header_path = target.umbrella_header_path.relative_path_from(target.sandbox.root)
750
+
751
+ build_phase.shell_script = <<-SH.strip_heredoc
752
+ COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"
753
+ MODULE_MAP_PATH="${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap"
754
+
755
+ ditto "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h" "${COMPATIBILITY_HEADER_PATH}"
756
+ ditto "${PODS_ROOT}/#{relative_module_map_path}" "${MODULE_MAP_PATH}"
757
+ ditto "${PODS_ROOT}/#{relative_umbrella_header_path}" "${BUILT_PRODUCTS_DIR}"
758
+ printf "\\n\\nmodule ${PRODUCT_MODULE_NAME}.Swift {\\n header \\"${COMPATIBILITY_HEADER_PATH}\\"\\n requires objc\\n}\\n" >> "${MODULE_MAP_PATH}"
759
+ SH
760
+ build_phase.input_paths = %W(
761
+ ${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h
762
+ ${PODS_ROOT}/#{relative_module_map_path}
763
+ ${PODS_ROOT}/#{relative_umbrella_header_path}
764
+ )
765
+ build_phase.output_paths = %W(
766
+ ${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap
767
+ ${BUILT_PRODUCTS_DIR}/#{relative_umbrella_header_path.basename}
768
+ ${BUILT_PRODUCTS_DIR}/Swift\ Compatibility\ Header/${PRODUCT_MODULE_NAME}-Swift.h
769
+ )
770
+ end
771
+
772
+ #-----------------------------------------------------------------------#
773
+ end
774
+ end
775
+ end
776
+ end
777
+ end