xcocoapods 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,463 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+
3
+ module Pod
4
+ class Installer
5
+ class UserProjectIntegrator
6
+ # This class is responsible for integrating the library generated by a
7
+ # {TargetDefinition} with its destination project.
8
+ #
9
+ class TargetIntegrator
10
+ autoload :XCConfigIntegrator, 'cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator'
11
+
12
+ # @return [String] the string to use as prefix for every build phase added to the user project
13
+ #
14
+ BUILD_PHASE_PREFIX = '[CP] '.freeze
15
+
16
+ # @return [String] the string to use as prefix for every build phase declared by the user within a podfile
17
+ # or podspec.
18
+ #
19
+ USER_BUILD_PHASE_PREFIX = '[CP-User] '.freeze
20
+
21
+ # @return [String] the name of the check manifest phase
22
+ #
23
+ CHECK_MANIFEST_PHASE_NAME = 'Check Pods Manifest.lock'.freeze
24
+
25
+ # @return [Array<Symbol>] the symbol types, which require that the pod
26
+ # frameworks are embedded in the output directory / product bundle.
27
+ #
28
+ # @note This does not include :app_extension or :watch_extension because
29
+ # these types must have their frameworks embedded in their host targets.
30
+ # For messages extensions, this only applies if it's embedded in a messages
31
+ # application.
32
+ #
33
+ EMBED_FRAMEWORK_TARGET_TYPES = [:application, :unit_test_bundle, :ui_test_bundle, :watch2_extension, :messages_application].freeze
34
+
35
+ # @return [String] the name of the embed frameworks phase
36
+ #
37
+ EMBED_FRAMEWORK_PHASE_NAME = 'Embed Pods Frameworks'.freeze
38
+
39
+ # @return [String] the name of the copy resources phase
40
+ #
41
+ COPY_PODS_RESOURCES_PHASE_NAME = 'Copy Pods Resources'.freeze
42
+
43
+ # @return [Integer] the maximum number of input and output paths to use for a script phase
44
+ #
45
+ MAX_INPUT_OUTPUT_PATHS = 1000
46
+
47
+ # @return [AggregateTarget] the target that should be integrated.
48
+ #
49
+ attr_reader :target
50
+
51
+ # Init a new TargetIntegrator
52
+ #
53
+ # @param [AggregateTarget] target @see #target
54
+ #
55
+ def initialize(target)
56
+ @target = target
57
+ end
58
+
59
+ class << self
60
+ # Adds a shell script build phase responsible to copy (embed) the frameworks
61
+ # generated by the TargetDefinition to the bundle of the product of the
62
+ # targets.
63
+ #
64
+ # @param [PBXNativeTarget] native_target
65
+ # The native target to add the script phase into.
66
+ #
67
+ # @param [String] script_path
68
+ # The script path to execute as part of this script phase.
69
+ #
70
+ # @param [Array<String>] input_paths
71
+ # The input paths (if any) to include for this script phase.
72
+ #
73
+ # @param [Array<String>] output_paths
74
+ # The output paths (if any) to include for this script phase.
75
+ #
76
+ # @return [void]
77
+ #
78
+ def create_or_update_embed_frameworks_script_phase_to_target(native_target, script_path, input_paths = [], output_paths = [])
79
+ phase = TargetIntegrator.create_or_update_build_phase(native_target, BUILD_PHASE_PREFIX + EMBED_FRAMEWORK_PHASE_NAME)
80
+ phase.shell_script = %("#{script_path}"\n)
81
+ phase.input_paths = input_paths
82
+ phase.output_paths = output_paths
83
+ end
84
+
85
+ # Delete a 'Embed Pods Frameworks' Copy Files Build Phase if present
86
+ #
87
+ # @param [PBXNativeTarget] native_target
88
+ # The native target to remove the script phase from.
89
+ #
90
+ def remove_embed_frameworks_script_phase_from_target(native_target)
91
+ embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name && bp.name.end_with?(EMBED_FRAMEWORK_PHASE_NAME) }
92
+ return unless embed_build_phase.present?
93
+ native_target.build_phases.delete(embed_build_phase)
94
+ end
95
+
96
+ # Adds a shell script build phase responsible to copy the resources
97
+ # generated by the TargetDefinition to the bundle of the product of the
98
+ # targets.
99
+ #
100
+ # @param [PBXNativeTarget] native_target
101
+ # The native target to add the script phase into.
102
+ #
103
+ # @param [String] script_path
104
+ # The script path to execute as part of this script phase.
105
+ #
106
+ # @param [Array<String>] input_paths
107
+ # The input paths (if any) to include for this script phase.
108
+ #
109
+ # @param [Array<String>] output_paths
110
+ # The output paths (if any) to include for this script phase.
111
+ #
112
+ # @return [void]
113
+ #
114
+ def create_or_update_copy_resources_script_phase_to_target(native_target, script_path, input_paths = [], output_paths = [])
115
+ phase_name = COPY_PODS_RESOURCES_PHASE_NAME
116
+ phase = TargetIntegrator.create_or_update_build_phase(native_target, BUILD_PHASE_PREFIX + phase_name)
117
+ phase.shell_script = %("#{script_path}"\n)
118
+ phase.input_paths = input_paths
119
+ phase.output_paths = output_paths
120
+ end
121
+
122
+ # Delete a 'Copy Pods Resources' script phase if present
123
+ #
124
+ # @param [PBXNativeTarget] native_target
125
+ # The native target to remove the script phase from.
126
+ #
127
+ def remove_copy_resources_script_phase_from_target(native_target)
128
+ build_phase = native_target.shell_script_build_phases.find { |bp| bp.name && bp.name.end_with?(COPY_PODS_RESOURCES_PHASE_NAME) }
129
+ return unless build_phase.present?
130
+ native_target.build_phases.delete(build_phase)
131
+ end
132
+
133
+ # Creates or update a shell script build phase for the given target.
134
+ #
135
+ # @param [PBXNativeTarget] native_target
136
+ # The native target to add the script phase into.
137
+ #
138
+ # @param [String] phase_name
139
+ # The name of the phase to use.
140
+ #
141
+ # @param [Class] phase_class
142
+ # The class of the phase to use.
143
+ #
144
+ # @return [void]
145
+ #
146
+ def create_or_update_build_phase(native_target, phase_name, phase_class = Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
147
+ build_phases = native_target.build_phases.grep(phase_class)
148
+ build_phases.find { |phase| phase.name && phase.name.end_with?(phase_name) }.tap { |p| p.name = phase_name if p } ||
149
+ native_target.project.new(phase_class).tap do |phase|
150
+ UI.message("Adding Build Phase '#{phase_name}' to project.") do
151
+ phase.name = phase_name
152
+ phase.show_env_vars_in_log = '0'
153
+ native_target.build_phases << phase
154
+ end
155
+ end
156
+ end
157
+
158
+ # Updates all target script phases for the current target, including creating or updating, deleting
159
+ # and re-ordering.
160
+ #
161
+ # @return [void]
162
+ #
163
+ def create_or_update_user_script_phases(script_phases, native_target)
164
+ script_phase_names = script_phases.map { |k| k[:name] }
165
+ # Delete script phases no longer present in the target.
166
+ native_target_script_phases = native_target.shell_script_build_phases.select { |bp| !bp.name.nil? && bp.name.start_with?(USER_BUILD_PHASE_PREFIX) }
167
+ native_target_script_phases.each do |script_phase|
168
+ script_phase_name_without_prefix = script_phase.name.sub(USER_BUILD_PHASE_PREFIX, '')
169
+ unless script_phase_names.include?(script_phase_name_without_prefix)
170
+ native_target.build_phases.delete(script_phase)
171
+ end
172
+ end
173
+ # Create or update the ones that are expected to be.
174
+ script_phases.each do |script_phase|
175
+ name_with_prefix = USER_BUILD_PHASE_PREFIX + script_phase[:name]
176
+ phase = TargetIntegrator.create_or_update_build_phase(native_target, name_with_prefix)
177
+ phase.shell_script = script_phase[:script]
178
+ phase.shell_path = script_phase[:shell_path] if script_phase.key?(:shell_path)
179
+ phase.input_paths = script_phase[:input_files] if script_phase.key?(:input_files)
180
+ phase.output_paths = script_phase[:output_files] if script_phase.key?(:output_files)
181
+ phase.show_env_vars_in_log = script_phase[:show_env_vars_in_log] ? '1' : '0' if script_phase.key?(:show_env_vars_in_log)
182
+
183
+ execution_position = script_phase[:execution_position]
184
+ unless execution_position == :any
185
+ compile_build_phase_index = native_target.build_phases.index do |bp|
186
+ bp.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase)
187
+ end
188
+ unless compile_build_phase_index.nil?
189
+ script_phase_index = native_target.build_phases.index do |bp|
190
+ bp.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && !bp.name.nil? && bp.name == name_with_prefix
191
+ end
192
+ if (execution_position == :before_compile && script_phase_index > compile_build_phase_index) ||
193
+ (execution_position == :after_compile && script_phase_index < compile_build_phase_index)
194
+ native_target.build_phases.move_from(script_phase_index, compile_build_phase_index)
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ # Script phases can have a limited number of input and output paths due to each one being exported to `env`.
202
+ # A large number can cause a build failure because of limitations in `env`. See issue
203
+ # https://github.com/CocoaPods/CocoaPods/issues/7362.
204
+ #
205
+ # @param [Array<String>] input_paths
206
+ # The input paths to trim.
207
+ #
208
+ # @param [Array<String>] output_paths
209
+ # The output paths to trim.
210
+ #
211
+ # @return [void]
212
+ #
213
+ def validate_input_output_path_limit(input_paths, output_paths)
214
+ if (input_paths.count + output_paths.count) > MAX_INPUT_OUTPUT_PATHS
215
+ input_paths.clear
216
+ output_paths.clear
217
+ end
218
+ end
219
+
220
+ # Returns an extension in the target that corresponds to the
221
+ # resource's input extension.
222
+ #
223
+ # @param [String] input_extension
224
+ # The input extension to map to.
225
+ #
226
+ # @return [String] The output extension.
227
+ #
228
+ def output_extension_for_resource(input_extension)
229
+ case input_extension
230
+ when '.storyboard' then '.storyboardc'
231
+ when '.xib' then '.nib'
232
+ when '.framework' then '.framework'
233
+ when '.xcdatamodel' then '.mom'
234
+ when '.xcdatamodeld' then '.momd'
235
+ when '.xcmappingmodel' then '.cdm'
236
+ when '.xcassets' then '.car'
237
+ else input_extension
238
+ end
239
+ end
240
+
241
+ # Returns the resource output paths for all given input paths.
242
+ #
243
+ # @param [Array<String>] resource_input_paths
244
+ # The input paths to map to.
245
+ #
246
+ # @return [Array<String>] The resource output paths.
247
+ #
248
+ def resource_output_paths(resource_input_paths)
249
+ resource_input_paths.map do |resource_input_path|
250
+ base_path = '${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}'
251
+ extname = File.extname(resource_input_path)
252
+ basename = extname == '.xcassets' ? 'Assets' : File.basename(resource_input_path)
253
+ output_extension = TargetIntegrator.output_extension_for_resource(extname)
254
+ File.join(base_path, File.basename(basename, extname) + output_extension)
255
+ end.uniq
256
+ end
257
+ end
258
+
259
+ # Integrates the user project targets. Only the targets that do **not**
260
+ # already have the Pods library in their frameworks build phase are
261
+ # processed.
262
+ #
263
+ # @return [void]
264
+ #
265
+ def integrate!
266
+ UI.section(integration_message) do
267
+ XCConfigIntegrator.integrate(target, native_targets)
268
+
269
+ add_pods_library
270
+ add_embed_frameworks_script_phase
271
+ remove_embed_frameworks_script_phase_from_embedded_targets
272
+ add_copy_resources_script_phase
273
+ add_check_manifest_lock_script_phase
274
+ add_user_script_phases
275
+ end
276
+ end
277
+
278
+ # @return [String] a string representation suitable for debugging.
279
+ #
280
+ def inspect
281
+ "#<#{self.class} for target `#{target.label}'>"
282
+ end
283
+
284
+ private
285
+
286
+ # @!group Integration steps
287
+ #---------------------------------------------------------------------#
288
+
289
+ # Adds spec product reference to the frameworks build phase of the
290
+ # {TargetDefinition} integration libraries. Adds a file reference to
291
+ # the frameworks group of the project and adds it to the frameworks
292
+ # build phase of the targets.
293
+ #
294
+ # @return [void]
295
+ #
296
+ def add_pods_library
297
+ frameworks = user_project.frameworks_group
298
+ native_targets.each do |native_target|
299
+ build_phase = native_target.frameworks_build_phase
300
+
301
+ # Find and delete possible reference for the other product type
302
+ old_product_name = target.requires_frameworks? ? target.static_library_name : target.framework_name
303
+ old_product_ref = frameworks.files.find { |f| f.path == old_product_name }
304
+ if old_product_ref.present?
305
+ UI.message("Removing old Pod product reference #{old_product_name} from project.")
306
+ build_phase.remove_file_reference(old_product_ref)
307
+ frameworks.remove_reference(old_product_ref)
308
+ end
309
+
310
+ # Find or create and add a reference for the current product type
311
+ target_basename = target.product_basename
312
+ new_product_ref = frameworks.files.find { |f| f.path == target.product_name } ||
313
+ frameworks.new_product_ref_for_target(target_basename, target.product_type)
314
+ build_phase.build_file(new_product_ref) ||
315
+ build_phase.add_file_reference(new_product_ref, true)
316
+ end
317
+ end
318
+
319
+ # Find or create a 'Copy Pods Resources' build phase
320
+ #
321
+ # @return [void]
322
+ #
323
+ def add_copy_resources_script_phase
324
+ native_targets.each do |native_target|
325
+ # Static library targets cannot include resources. Skip this phase from being added instead.
326
+ next if native_target.symbol_type == :static_library
327
+ script_path = target.copy_resources_script_relative_path
328
+ resource_paths_by_config = target.resource_paths_by_config
329
+ if resource_paths_by_config.values.all?(&:empty?)
330
+ TargetIntegrator.remove_copy_resources_script_phase_from_target(native_target)
331
+ else
332
+ resource_paths_flattened = resource_paths_by_config.values.flatten.uniq
333
+ input_paths = [target.copy_resources_script_relative_path, *resource_paths_flattened]
334
+ output_paths = TargetIntegrator.resource_output_paths(resource_paths_flattened)
335
+ TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
336
+ TargetIntegrator.create_or_update_copy_resources_script_phase_to_target(native_target, script_path, input_paths, output_paths)
337
+ end
338
+ end
339
+ end
340
+
341
+ # Removes the embed frameworks build phase from embedded targets
342
+ #
343
+ # @note Older versions of CocoaPods would add this build phase to embedded
344
+ # targets. They should be removed on upgrade because embedded targets
345
+ # will have their frameworks embedded in their host targets.
346
+ #
347
+ def remove_embed_frameworks_script_phase_from_embedded_targets
348
+ return unless target.requires_host_target?
349
+ native_targets.each do |native_target|
350
+ if AggregateTarget::EMBED_FRAMEWORKS_IN_HOST_TARGET_TYPES.include? native_target.symbol_type
351
+ TargetIntegrator.remove_embed_frameworks_script_phase_from_target(native_target)
352
+ end
353
+ end
354
+ end
355
+
356
+ # Find or create a 'Embed Pods Frameworks' Copy Files Build Phase
357
+ #
358
+ # @return [void]
359
+ #
360
+ def add_embed_frameworks_script_phase
361
+ native_targets_to_embed_in.each do |native_target|
362
+ script_path = target.embed_frameworks_script_relative_path
363
+ framework_paths_by_config = target.framework_paths_by_config.values.flatten.uniq
364
+ if framework_paths_by_config.all?(&:empty?)
365
+ TargetIntegrator.remove_embed_frameworks_script_phase_from_target(native_target)
366
+ else
367
+ input_paths = [target.embed_frameworks_script_relative_path, *framework_paths_by_config.map { |fw| [fw[:input_path], fw[:dsym_input_path]] }.flatten.compact]
368
+ output_paths = framework_paths_by_config.map { |fw| [fw[:output_path], fw[:dsym_output_path]] }.flatten.compact.uniq
369
+ TargetIntegrator.validate_input_output_path_limit(input_paths, output_paths)
370
+ TargetIntegrator.create_or_update_embed_frameworks_script_phase_to_target(native_target, script_path, input_paths, output_paths)
371
+ end
372
+ end
373
+ end
374
+
375
+ # Updates all target script phases for the current target, including creating or updating, deleting
376
+ # and re-ordering.
377
+ #
378
+ # @return [void]
379
+ #
380
+ def add_user_script_phases
381
+ native_targets.each do |native_target|
382
+ TargetIntegrator.create_or_update_user_script_phases(target.target_definition.script_phases, native_target)
383
+ end
384
+ end
385
+
386
+ # Adds a shell script build phase responsible for checking if the Pods
387
+ # locked in the Pods/Manifest.lock file are in sync with the Pods defined
388
+ # in the Podfile.lock.
389
+ #
390
+ # @note The build phase is appended to the front because to fail
391
+ # fast.
392
+ #
393
+ # @return [void]
394
+ #
395
+ def add_check_manifest_lock_script_phase
396
+ phase_name = CHECK_MANIFEST_PHASE_NAME
397
+ native_targets.each do |native_target|
398
+ phase = TargetIntegrator.create_or_update_build_phase(native_target, BUILD_PHASE_PREFIX + phase_name)
399
+ native_target.build_phases.unshift(phase).uniq! unless native_target.build_phases.first == phase
400
+ phase.shell_script = <<-SH.strip_heredoc
401
+ diff "${PODS_PODFILE_DIR_PATH}/Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
402
+ if [ $? != 0 ] ; then
403
+ # print error to STDERR
404
+ echo "error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation." >&2
405
+ exit 1
406
+ fi
407
+ # This output is used by Xcode 'outputs' to avoid re-running this script phase.
408
+ echo "SUCCESS" > "${SCRIPT_OUTPUT_FILE_0}"
409
+ SH
410
+ phase.input_paths = %w(${PODS_PODFILE_DIR_PATH}/Podfile.lock ${PODS_ROOT}/Manifest.lock)
411
+ phase.output_paths = [target.check_manifest_lock_script_output_file_path]
412
+ end
413
+ end
414
+
415
+ private
416
+
417
+ # @!group Private Helpers
418
+ #---------------------------------------------------------------------#
419
+
420
+ # @return [Array<PBXNativeTarget>] The list of all the targets that
421
+ # match the given target.
422
+ #
423
+ def native_targets
424
+ @native_targets ||= target.user_targets
425
+ end
426
+
427
+ # @return [Array<PBXNativeTarget>] The list of all the targets that
428
+ # require that the pod frameworks are embedded in the output
429
+ # directory / product bundle.
430
+ #
431
+ def native_targets_to_embed_in
432
+ return [] if target.requires_host_target?
433
+ native_targets.select do |target|
434
+ EMBED_FRAMEWORK_TARGET_TYPES.include?(target.symbol_type)
435
+ end
436
+ end
437
+
438
+ # Read the project from the disk to ensure that it is up to date as
439
+ # other TargetIntegrators might have modified it.
440
+ #
441
+ # @return [Project]
442
+ #
443
+ def user_project
444
+ target.user_project
445
+ end
446
+
447
+ # @return [Specification::Consumer] the consumer for the specifications.
448
+ #
449
+ def spec_consumers
450
+ @spec_consumers ||= target.pod_targets.map(&:file_accessors).flatten.map(&:spec_consumer)
451
+ end
452
+
453
+ # @return [String] the message that should be displayed for the target
454
+ # integration.
455
+ #
456
+ def integration_message
457
+ "Integrating target `#{target.name}` " \
458
+ "(#{UI.path target.user_project_path} project)"
459
+ end
460
+ end
461
+ end
462
+ end
463
+ end