cocoapods-dykit 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pod/command.rb +2 -0
  3. data/lib/pod/command/dyinstall.rb +51 -0
  4. data/lib/pod/command/dyupdate.rb +106 -0
  5. data/lib/pod/command/fmwk.rb +4 -0
  6. data/lib/pod/command/lib/dylint.rb +1 -0
  7. data/lib/pod/gem_version.rb +1 -1
  8. data/lib/pod/installer.rb +715 -0
  9. data/lib/pod/installer/analyzer.rb +934 -0
  10. data/lib/pod/installer/analyzer/analysis_result.rb +57 -0
  11. data/lib/pod/installer/analyzer/locking_dependency_analyzer.rb +95 -0
  12. data/lib/pod/installer/analyzer/pod_variant.rb +68 -0
  13. data/lib/pod/installer/analyzer/pod_variant_set.rb +157 -0
  14. data/lib/pod/installer/analyzer/podfile_dependency_cache.rb +54 -0
  15. data/lib/pod/installer/analyzer/sandbox_analyzer.rb +251 -0
  16. data/lib/pod/installer/analyzer/specs_state.rb +84 -0
  17. data/lib/pod/installer/analyzer/target_inspection_result.rb +45 -0
  18. data/lib/pod/installer/analyzer/target_inspector.rb +254 -0
  19. data/lib/pod/installer/installation_options.rb +158 -0
  20. data/lib/pod/installer/pod_source_installer.rb +214 -0
  21. data/lib/pod/installer/pod_source_preparer.rb +77 -0
  22. data/lib/pod/installer/podfile_validator.rb +139 -0
  23. data/lib/pod/installer/post_install_hooks_context.rb +107 -0
  24. data/lib/pod/installer/pre_install_hooks_context.rb +42 -0
  25. data/lib/pod/installer/source_provider_hooks_context.rb +32 -0
  26. data/lib/pod/installer/user_project_integrator.rb +253 -0
  27. data/lib/pod/installer/user_project_integrator/target_integrator.rb +462 -0
  28. data/lib/pod/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
  29. data/lib/pod/installer/xcode.rb +8 -0
  30. data/lib/pod/installer/xcode/pods_project_generator.rb +353 -0
  31. data/lib/pod/installer/xcode/pods_project_generator/aggregate_target_installer.rb +172 -0
  32. data/lib/pod/installer/xcode/pods_project_generator/file_references_installer.rb +367 -0
  33. data/lib/pod/installer/xcode/pods_project_generator/pod_target_installer.rb +718 -0
  34. data/lib/pod/installer/xcode/pods_project_generator/pod_target_integrator.rb +111 -0
  35. data/lib/pod/installer/xcode/pods_project_generator/target_installer.rb +265 -0
  36. data/lib/pod/installer/xcode/target_validator.rb +141 -0
  37. data/lib/pod/resolver.rb +632 -0
  38. metadata +34 -2
@@ -0,0 +1,172 @@
1
+ module Pod
2
+ class DyInstaller
3
+ class Xcode
4
+ class PodsProjectGenerator
5
+ # Creates the targets which aggregate the Pods libraries in the Pods
6
+ # project and the relative support files.
7
+ #
8
+ class AggregateTargetInstaller < TargetInstaller
9
+ # Creates the target in the Pods project and the relative support files.
10
+ #
11
+ # @return [void]
12
+ #
13
+ def install!
14
+ UI.message "- Installing target `#{target.name}` #{target.platform}" do
15
+ add_target
16
+ create_support_files_dir
17
+ create_support_files_group
18
+ create_xcconfig_file
19
+ if target.requires_frameworks?
20
+ create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform)
21
+ create_module_map
22
+ create_umbrella_header
23
+ elsif target.uses_swift?
24
+ create_module_map
25
+ create_umbrella_header
26
+ end
27
+ # Because embedded targets live in their host target, CocoaPods
28
+ # copies all of the embedded target's pod_targets to its host
29
+ # targets. Having this script for the embedded target would
30
+ # cause an App Store rejection because frameworks cannot be
31
+ # embedded in embedded targets.
32
+ #
33
+ create_embed_frameworks_script unless target.requires_host_target?
34
+ create_bridge_support_file
35
+ create_copy_resources_script
36
+ create_acknowledgements
37
+ create_dummy_source
38
+ end
39
+ end
40
+
41
+ #-----------------------------------------------------------------------#
42
+
43
+ private
44
+
45
+ # @return [TargetDefinition] the target definition of the library.
46
+ #
47
+ def target_definition
48
+ target.target_definition
49
+ end
50
+
51
+ # Ensure that vendored static frameworks and libraries are not linked
52
+ # twice to the aggregate target, which shares the xcconfig of the user
53
+ # target.
54
+ #
55
+ def custom_build_settings
56
+ settings = {
57
+ 'CODE_SIGN_IDENTITY[sdk=appletvos*]' => '',
58
+ 'CODE_SIGN_IDENTITY[sdk=iphoneos*]' => '',
59
+ 'CODE_SIGN_IDENTITY[sdk=watchos*]' => '',
60
+ 'MACH_O_TYPE' => 'staticlib',
61
+ 'OTHER_LDFLAGS' => '',
62
+ 'OTHER_LIBTOOLFLAGS' => '',
63
+ 'PODS_ROOT' => '$(SRCROOT)',
64
+ 'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
65
+ 'SKIP_INSTALL' => 'YES',
66
+
67
+ # Needed to ensure that static libraries won't try to embed the swift stdlib,
68
+ # since there's no where to embed in for a static library.
69
+ # Not necessary for dynamic frameworks either, since the aggregate targets are never shipped
70
+ # on their own, and are always further embedded into an app target.
71
+ 'ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES' => 'NO',
72
+ }
73
+ super.merge(settings)
74
+ end
75
+
76
+ # Creates the group that holds the references to the support files
77
+ # generated by this installer.
78
+ #
79
+ # @return [void]
80
+ #
81
+ def create_support_files_group
82
+ parent = project.support_files_group
83
+ name = target.name
84
+ dir = target.support_files_dir
85
+ @support_files_group = parent.new_group(name, dir)
86
+ end
87
+
88
+ # Generates the contents of the xcconfig file and saves it to disk.
89
+ #
90
+ # @return [void]
91
+ #
92
+ def create_xcconfig_file
93
+ native_target.build_configurations.each do |configuration|
94
+ path = target.xcconfig_path(configuration.name)
95
+ gen = Generator::XCConfig::AggregateXCConfig.new(target, configuration.name)
96
+ update_changed_file(gen, path)
97
+ target.xcconfigs[configuration.name] = gen.xcconfig
98
+ xcconfig_file_ref = add_file_to_support_group(path)
99
+ configuration.base_configuration_reference = xcconfig_file_ref
100
+ end
101
+ end
102
+
103
+ # Generates the bridge support metadata if requested by the {Podfile}.
104
+ #
105
+ # @note The bridge support metadata is added to the resources of the
106
+ # target because it is needed for environments interpreted at
107
+ # runtime.
108
+ #
109
+ # @return [void]
110
+ #
111
+ def create_bridge_support_file
112
+ if target.podfile.generate_bridge_support?
113
+ path = target.bridge_support_path
114
+ headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path }
115
+ generator = Generator::BridgeSupport.new(headers)
116
+ update_changed_file(generator, path)
117
+ add_file_to_support_group(path)
118
+ end
119
+ end
120
+
121
+ # Creates a script that copies the resources to the bundle of the client
122
+ # target.
123
+ #
124
+ # @note The bridge support file needs to be created before the prefix
125
+ # header, otherwise it will not be added to the resources script.
126
+ #
127
+ # @return [void]
128
+ #
129
+ def create_copy_resources_script
130
+ path = target.copy_resources_script_path
131
+ generator = Generator::CopyResourcesScript.new(target.resource_paths_by_config, target.platform)
132
+ update_changed_file(generator, path)
133
+ add_file_to_support_group(path)
134
+ end
135
+
136
+ # Creates a script that embeds the frameworks to the bundle of the client
137
+ # target.
138
+ #
139
+ # @note We can't use Xcode default copy bundle resource phase, because
140
+ # we need to ensure that we only copy the resources, which are
141
+ # relevant for the current build configuration.
142
+ #
143
+ # @return [void]
144
+ #
145
+ def create_embed_frameworks_script
146
+ path = target.embed_frameworks_script_path
147
+ generator = Generator::EmbedFrameworksScript.new(target.framework_paths_by_config)
148
+ update_changed_file(generator, path)
149
+ add_file_to_support_group(path)
150
+ end
151
+
152
+ # Generates the acknowledgement files (markdown and plist) for the target.
153
+ #
154
+ # @return [void]
155
+ #
156
+ def create_acknowledgements
157
+ basepath = target.acknowledgements_basepath
158
+ Generator::Acknowledgements.generators.each do |generator_class|
159
+ path = generator_class.path_from_basepath(basepath)
160
+ file_accessors = target.pod_targets.map(&:file_accessors).flatten
161
+ generator = generator_class.new(file_accessors)
162
+ update_changed_file(generator, path)
163
+ add_file_to_support_group(path)
164
+ end
165
+ end
166
+
167
+ #-----------------------------------------------------------------------#
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,367 @@
1
+ module Pod
2
+ class DyInstaller
3
+ class Xcode
4
+ class PodsProjectGenerator
5
+ # Controller class responsible of installing the file references of the
6
+ # specifications in the Pods project.
7
+ #
8
+ class FileReferencesInstaller
9
+ # @return [Sandbox] The sandbox of the installation.
10
+ #
11
+ attr_reader :sandbox
12
+
13
+ # @return [Array<PodTarget>] The pod targets of the installation.
14
+ #
15
+ attr_reader :pod_targets
16
+
17
+ # @return [Project] The Pods project.
18
+ #
19
+ attr_reader :pods_project
20
+
21
+ # Initialize a new instance
22
+ #
23
+ # @param [Sandbox] sandbox @see sandbox
24
+ # @param [Array<PodTarget>] pod_targets @see pod_targets
25
+ # @param [Project] pods_project @see pod_project
26
+ #
27
+ def initialize(sandbox, pod_targets, pods_project)
28
+ @sandbox = sandbox
29
+ @pod_targets = pod_targets
30
+ @pods_project = pods_project
31
+ end
32
+
33
+ # Installs the file references.
34
+ #
35
+ # @return [void]
36
+ #
37
+ def install!
38
+ refresh_file_accessors
39
+ add_source_files_references
40
+ add_frameworks_bundles
41
+ add_vendored_libraries
42
+ add_resources
43
+ add_developer_files unless sandbox.development_pods.empty?
44
+ link_headers
45
+ end
46
+
47
+ #-----------------------------------------------------------------------#
48
+
49
+ private
50
+
51
+ # @!group Installation Steps
52
+
53
+ # Reads the file accessors contents from the file system.
54
+ #
55
+ # @note The contents of the file accessors are modified by the clean
56
+ # step of the #{PodSourceInstaller} and by the pre install hooks.
57
+ #
58
+ # @return [void]
59
+ #
60
+ def refresh_file_accessors
61
+ file_accessors.map(&:path_list).uniq.each(&:read_file_system)
62
+ end
63
+
64
+ # Adds the source files of the Pods to the Pods project.
65
+ #
66
+ # @note The source files are grouped by Pod and in turn by subspec
67
+ # (recursively).
68
+ #
69
+ # @return [void]
70
+ #
71
+ def add_source_files_references
72
+ UI.message '- Adding source files to Pods project' do
73
+ add_file_accessors_paths_to_pods_group(:source_files, nil, true)
74
+ end
75
+ end
76
+
77
+ # Adds the bundled frameworks to the Pods project
78
+ #
79
+ # @return [void]
80
+ #
81
+ def add_frameworks_bundles
82
+ UI.message '- Adding frameworks to Pods project' do
83
+ add_file_accessors_paths_to_pods_group(:vendored_frameworks, :frameworks)
84
+ end
85
+ end
86
+
87
+ # Adds the bundled libraries to the Pods project
88
+ #
89
+ # @return [void]
90
+ #
91
+ def add_vendored_libraries
92
+ UI.message '- Adding libraries to Pods project' do
93
+ add_file_accessors_paths_to_pods_group(:vendored_libraries, :frameworks)
94
+ end
95
+ end
96
+
97
+ # Adds the resources of the Pods to the Pods project.
98
+ #
99
+ # @note The source files are grouped by Pod and in turn by subspec
100
+ # (recursively) in the resources group.
101
+ #
102
+ # @return [void]
103
+ #
104
+ def add_resources
105
+ UI.message '- Adding resources to Pods project' do
106
+ add_file_accessors_paths_to_pods_group(:resources, :resources, true)
107
+ add_file_accessors_paths_to_pods_group(:resource_bundle_files, :resources, true)
108
+ end
109
+ end
110
+
111
+ def add_developer_files
112
+ UI.message '- Adding development pod helper files to Pods project' do
113
+ file_accessors.each do |file_accessor|
114
+ pod_name = file_accessor.spec.name
115
+ next unless sandbox.local?(pod_name)
116
+ root_name = Specification.root_name(pod_name)
117
+ paths = file_accessor.developer_files
118
+ paths.each do |path|
119
+ group = pods_project.group_for_spec(root_name, :developer)
120
+ ref = pods_project.add_file_reference(path, group, false)
121
+ if path.extname == '.podspec'
122
+ pods_project.mark_ruby_file_ref(ref)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ # Creates the link to the headers of the Pod in the sandbox.
130
+ #
131
+ # @return [void]
132
+ #
133
+ def link_headers
134
+ UI.message '- Linking headers' do
135
+ pod_targets.each do |pod_target|
136
+ # When integrating Pod as frameworks, built Pods are built into
137
+ # frameworks, whose headers are included inside the built
138
+ # framework. Those headers do not need to be linked from the
139
+ # sandbox.
140
+ next if pod_target.requires_frameworks? && pod_target.should_build?
141
+
142
+ headers_sandbox = Pathname.new(pod_target.pod_name)
143
+ added_build_headers = false
144
+ added_public_headers = false
145
+
146
+ pod_target.file_accessors.each do |file_accessor|
147
+ # Private headers will always end up in Pods/Headers/Private/PodA/*.h
148
+ # This will allow for `""` imports to work.
149
+ header_mappings(headers_sandbox, file_accessor, file_accessor.headers).each do |namespaced_path, files|
150
+ added_build_headers = true
151
+ pod_target.build_headers.add_files(namespaced_path, files)
152
+ end
153
+
154
+ # Public headers on the other hand will be added in Pods/Headers/Public/PodA/PodA/*.h
155
+ # The extra folder is intentional in order for `<>` imports to work.
156
+ header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers).each do |namespaced_path, files|
157
+ added_public_headers = true
158
+ sandbox.public_headers.add_files(namespaced_path, files)
159
+ end
160
+
161
+ unless pod_target.requires_frameworks?
162
+ vendored_frameworks_header_mappings(headers_sandbox, file_accessor).each do |namespaced_path, files|
163
+ added_public_headers = true
164
+ sandbox.public_headers.add_files(namespaced_path, files)
165
+ end
166
+ end
167
+ end
168
+
169
+ pod_target.build_headers.add_search_path(headers_sandbox, pod_target.platform) if added_build_headers
170
+ sandbox.public_headers.add_search_path(headers_sandbox, pod_target.platform) if added_public_headers
171
+ end
172
+ end
173
+ end
174
+
175
+ #-----------------------------------------------------------------------#
176
+
177
+ private
178
+
179
+ # @!group Private Helpers
180
+
181
+ # @return [Array<Sandbox::FileAccessor>] The file accessors for all the
182
+ # specs platform combinations.
183
+ #
184
+ def file_accessors
185
+ @file_accessors ||= pod_targets.flat_map(&:file_accessors).compact
186
+ end
187
+
188
+ # Adds file references to the list of the paths returned by the file
189
+ # accessor with the given key to the given group of the Pods project.
190
+ #
191
+ # @param [Symbol] file_accessor_key
192
+ # The method of the file accessor which would return the list of
193
+ # the paths.
194
+ #
195
+ # @param [Symbol] group_key
196
+ # The key of the group of the Pods project.
197
+ #
198
+ # @param [Bool] reflect_file_system_structure_for_development
199
+ # Whether organizing a local pod's files in subgroups inside
200
+ # the pod's group is allowed.
201
+ #
202
+ # @return [void]
203
+ #
204
+ def add_file_accessors_paths_to_pods_group(file_accessor_key, group_key = nil, reflect_file_system_structure_for_development = false)
205
+ file_accessors.each do |file_accessor|
206
+ pod_name = file_accessor.spec.name
207
+ local = sandbox.local?(pod_name)
208
+ paths = file_accessor.send(file_accessor_key)
209
+ paths = allowable_project_paths(paths)
210
+ base_path = local ? common_path(paths) : nil
211
+ paths.each do |path|
212
+ group = pods_project.group_for_spec(pod_name, group_key)
213
+ pods_project.add_file_reference(path, group, local && reflect_file_system_structure_for_development, base_path)
214
+ end
215
+ end
216
+ end
217
+
218
+ # Filters a list of paths down to those paths which can be added to
219
+ # the Xcode project. Some paths are intermediates and only their children
220
+ # should be added, while some paths are treated as bundles and their
221
+ # children should not be added directly.
222
+ #
223
+ # @param [Array<Pathname>] paths
224
+ # The paths to files or directories on disk.
225
+ #
226
+ # @return [Array<Pathname>] The paths which can be added to the Xcode project
227
+ #
228
+ def allowable_project_paths(paths)
229
+ lproj_paths = Set.new
230
+ lproj_paths_with_files = Set.new
231
+ allowable_paths = paths.select do |path|
232
+ path_str = path.to_s
233
+
234
+ # We add the directory for a Core Data model, but not the items in it.
235
+ next if path_str =~ /.*\.xcdatamodeld\/.+/i
236
+
237
+ # We add the directory for a Core Data migration mapping, but not the items in it.
238
+ next if path_str =~ /.*\.xcmappingmodel\/.+/i
239
+
240
+ # We add the directory for an asset catalog, but not the items in it.
241
+ next if path_str =~ /.*\.xcassets\/.+/i
242
+
243
+ if path_str =~ /\.lproj(\/|$)/i
244
+ # If the element is an .lproj directory then save it and potentially
245
+ # add it later if we don't find any contained items.
246
+ if path_str =~ /\.lproj$/i && path.directory?
247
+ lproj_paths << path
248
+ next
249
+ end
250
+
251
+ # Collect the paths for the .lproj directories that contain files.
252
+ lproj_path = /(^.*\.lproj)\/.*/i.match(path_str)[1]
253
+ lproj_paths_with_files << Pathname(lproj_path)
254
+
255
+ # Directories nested within an .lproj directory are added as file
256
+ # system references so their contained items are not added directly.
257
+ next if path.dirname.dirname == lproj_path
258
+ end
259
+
260
+ true
261
+ end
262
+
263
+ # Only add the path for the .lproj directories that do not have anything
264
+ # within them added as well. This generally happens if the glob within the
265
+ # resources directory was not a recursive glob.
266
+ allowable_paths + lproj_paths.subtract(lproj_paths_with_files).to_a
267
+ end
268
+
269
+ # Returns a Pathname of the nearest parent from which all the given paths descend.
270
+ # Converts each Pathname to a list of path components and finds the longest common prefix
271
+ #
272
+ # @param [Array<Pathname>] paths
273
+ # The paths to files or directories on disk. Must be absolute paths
274
+ #
275
+ # @return [Pathname] Pathname of the nearest parent shared by paths, or nil if none exists
276
+ #
277
+ def common_path(paths)
278
+ return nil if paths.empty?
279
+ strs = paths.map do |path|
280
+ unless path.absolute?
281
+ raise ArgumentError, "Paths must be absolute #{path}"
282
+ end
283
+ path.dirname.to_s
284
+ end
285
+ min, max = strs.minmax
286
+ min = min.split('/')
287
+ max = max.split('/')
288
+ idx = min.size.times { |i| break i if min[i] != max[i] }
289
+ result = Pathname.new(min[0...idx].join('/'))
290
+ # Don't consider "/" a common path
291
+ return result unless result.to_s == '' || result.to_s == '/'
292
+ end
293
+
294
+ # Computes the destination sub-directory in the sandbox
295
+ #
296
+ # @param [Pathname] headers_sandbox
297
+ # The sandbox where the header links should be stored for this
298
+ # Pod.
299
+ #
300
+ # @param [Sandbox::FileAccessor] file_accessor
301
+ # The consumer file accessor for which the headers need to be
302
+ # linked.
303
+ #
304
+ # @param [Array<Pathname>] headers
305
+ # The absolute paths of the headers which need to be mapped.
306
+ #
307
+ # @return [Hash{Pathname => Array<Pathname>}] A hash containing the
308
+ # headers folders as the keys and the absolute paths of the
309
+ # header files as the values.
310
+ #
311
+ def header_mappings(headers_sandbox, file_accessor, headers)
312
+ consumer = file_accessor.spec_consumer
313
+ header_mappings_dir = consumer.header_mappings_dir
314
+ dir = headers_sandbox
315
+ dir += consumer.header_dir if consumer.header_dir
316
+
317
+ mappings = {}
318
+ headers.each do |header|
319
+ next if header.to_s.include?('.framework/')
320
+
321
+ sub_dir = dir
322
+ if header_mappings_dir
323
+ relative_path = header.relative_path_from(file_accessor.path_list.root + header_mappings_dir)
324
+ sub_dir += relative_path.dirname
325
+ end
326
+ mappings[sub_dir] ||= []
327
+ mappings[sub_dir] << header
328
+ end
329
+ mappings
330
+ end
331
+
332
+ # Computes the destination sub-directory in the sandbox for headers
333
+ # from inside vendored frameworks.
334
+ #
335
+ # @param [Pathname] headers_sandbox
336
+ # The sandbox where the header links should be stored for this
337
+ # Pod.
338
+ #
339
+ # @param [Sandbox::FileAccessor] file_accessor
340
+ # The consumer file accessor for which the headers need to be
341
+ # linked.
342
+ #
343
+ def vendored_frameworks_header_mappings(headers_sandbox, file_accessor)
344
+ mappings = {}
345
+ file_accessor.vendored_frameworks.each do |framework|
346
+ headers_dir = Sandbox::FileAccessor.vendored_frameworks_headers_dir(framework)
347
+ headers = Sandbox::FileAccessor.vendored_frameworks_headers(framework)
348
+ framework_name = framework.basename(framework.extname)
349
+ dir = headers_sandbox + framework_name
350
+ headers.each do |header|
351
+ # the relative path of framework headers should be kept,
352
+ # not flattened like is done for most public headers.
353
+ relative_path = header.relative_path_from(headers_dir)
354
+ sub_dir = dir + relative_path.dirname
355
+ mappings[sub_dir] ||= []
356
+ mappings[sub_dir] << header
357
+ end
358
+ end
359
+ mappings
360
+ end
361
+
362
+ #-----------------------------------------------------------------------#
363
+ end
364
+ end
365
+ end
366
+ end
367
+ end