cocoapods-dykit 0.5.2 → 0.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 (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