plasmo_xcodeproj 1.21.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +19 -0
  3. data/README.md +95 -0
  4. data/bin/xcodeproj +10 -0
  5. data/lib/xcodeproj/command/config_dump.rb +91 -0
  6. data/lib/xcodeproj/command/project_diff.rb +56 -0
  7. data/lib/xcodeproj/command/show.rb +60 -0
  8. data/lib/xcodeproj/command/sort.rb +44 -0
  9. data/lib/xcodeproj/command/target_diff.rb +43 -0
  10. data/lib/xcodeproj/command.rb +63 -0
  11. data/lib/xcodeproj/config/other_linker_flags_parser.rb +73 -0
  12. data/lib/xcodeproj/config.rb +386 -0
  13. data/lib/xcodeproj/constants.rb +465 -0
  14. data/lib/xcodeproj/differ.rb +239 -0
  15. data/lib/xcodeproj/gem_version.rb +5 -0
  16. data/lib/xcodeproj/helper.rb +30 -0
  17. data/lib/xcodeproj/plist.rb +94 -0
  18. data/lib/xcodeproj/project/case_converter.rb +90 -0
  19. data/lib/xcodeproj/project/object/build_configuration.rb +255 -0
  20. data/lib/xcodeproj/project/object/build_file.rb +84 -0
  21. data/lib/xcodeproj/project/object/build_phase.rb +369 -0
  22. data/lib/xcodeproj/project/object/build_rule.rb +109 -0
  23. data/lib/xcodeproj/project/object/configuration_list.rb +117 -0
  24. data/lib/xcodeproj/project/object/container_item_proxy.rb +116 -0
  25. data/lib/xcodeproj/project/object/file_reference.rb +338 -0
  26. data/lib/xcodeproj/project/object/group.rb +506 -0
  27. data/lib/xcodeproj/project/object/helpers/build_settings_array_settings_by_object_version.rb +72 -0
  28. data/lib/xcodeproj/project/object/helpers/file_references_factory.rb +245 -0
  29. data/lib/xcodeproj/project/object/helpers/groupable_helper.rb +260 -0
  30. data/lib/xcodeproj/project/object/native_target.rb +751 -0
  31. data/lib/xcodeproj/project/object/reference_proxy.rb +86 -0
  32. data/lib/xcodeproj/project/object/root_object.rb +100 -0
  33. data/lib/xcodeproj/project/object/swift_package_product_dependency.rb +29 -0
  34. data/lib/xcodeproj/project/object/swift_package_remote_reference.rb +33 -0
  35. data/lib/xcodeproj/project/object/target_dependency.rb +94 -0
  36. data/lib/xcodeproj/project/object.rb +534 -0
  37. data/lib/xcodeproj/project/object_attributes.rb +522 -0
  38. data/lib/xcodeproj/project/object_dictionary.rb +210 -0
  39. data/lib/xcodeproj/project/object_list.rb +223 -0
  40. data/lib/xcodeproj/project/project_helper.rb +341 -0
  41. data/lib/xcodeproj/project/uuid_generator.rb +132 -0
  42. data/lib/xcodeproj/project.rb +874 -0
  43. data/lib/xcodeproj/scheme/abstract_scheme_action.rb +100 -0
  44. data/lib/xcodeproj/scheme/analyze_action.rb +19 -0
  45. data/lib/xcodeproj/scheme/archive_action.rb +59 -0
  46. data/lib/xcodeproj/scheme/build_action.rb +298 -0
  47. data/lib/xcodeproj/scheme/buildable_product_runnable.rb +55 -0
  48. data/lib/xcodeproj/scheme/buildable_reference.rb +129 -0
  49. data/lib/xcodeproj/scheme/command_line_arguments.rb +162 -0
  50. data/lib/xcodeproj/scheme/environment_variables.rb +170 -0
  51. data/lib/xcodeproj/scheme/execution_action.rb +86 -0
  52. data/lib/xcodeproj/scheme/launch_action.rb +179 -0
  53. data/lib/xcodeproj/scheme/location_scenario_reference.rb +49 -0
  54. data/lib/xcodeproj/scheme/macro_expansion.rb +34 -0
  55. data/lib/xcodeproj/scheme/profile_action.rb +57 -0
  56. data/lib/xcodeproj/scheme/remote_runnable.rb +92 -0
  57. data/lib/xcodeproj/scheme/send_email_action_content.rb +84 -0
  58. data/lib/xcodeproj/scheme/shell_script_action_content.rb +77 -0
  59. data/lib/xcodeproj/scheme/test_action.rb +394 -0
  60. data/lib/xcodeproj/scheme/xml_element_wrapper.rb +82 -0
  61. data/lib/xcodeproj/scheme.rb +375 -0
  62. data/lib/xcodeproj/user_interface.rb +22 -0
  63. data/lib/xcodeproj/workspace/file_reference.rb +79 -0
  64. data/lib/xcodeproj/workspace/group_reference.rb +67 -0
  65. data/lib/xcodeproj/workspace/reference.rb +40 -0
  66. data/lib/xcodeproj/workspace.rb +277 -0
  67. data/lib/xcodeproj/xcodebuild_helper.rb +108 -0
  68. data/lib/xcodeproj.rb +29 -0
  69. metadata +208 -0
@@ -0,0 +1,341 @@
1
+ module Xcodeproj
2
+ class Project
3
+ module ProjectHelper
4
+ include Object
5
+
6
+ # @!group Targets
7
+
8
+ #-----------------------------------------------------------------------#
9
+
10
+ # Creates a new target and adds it to the project.
11
+ #
12
+ # The target is configured for the given platform and its file reference it
13
+ # is added to the {products_group}.
14
+ #
15
+ # The target is pre-populated with common build settings, and the
16
+ # appropriate Framework according to the platform is added to to its
17
+ # Frameworks phase.
18
+ #
19
+ # @param [Project] project
20
+ # the project to which the target should be added.
21
+ #
22
+ # @param [Symbol] type
23
+ # the type of target. Can be `:application`, `:dynamic_library`,
24
+ # `framework` or `:static_library`.
25
+ #
26
+ # @param [String] name
27
+ # the name of the target product.
28
+ #
29
+ # @param [Symbol] platform
30
+ # the platform of the target. Can be `:ios` or `:osx`.
31
+ #
32
+ # @param [String] deployment_target
33
+ # the deployment target for the platform.
34
+ #
35
+ # @param [PBXGroup] product_group
36
+ # the product group, where to add to a file reference of the
37
+ # created target.
38
+ #
39
+ # @param [Symbol] language
40
+ # the primary language of the target, can be `:objc` or `:swift`.
41
+ #
42
+ # @return [PBXNativeTarget] the target.
43
+ #
44
+ def self.new_target(project, type, name, platform, deployment_target, product_group, language, product_basename)
45
+ # Target
46
+ target = project.new(PBXNativeTarget)
47
+ project.targets << target
48
+ target.name = name
49
+ target.product_name = product_basename
50
+ target.product_type = Constants::PRODUCT_TYPE_UTI[type]
51
+ target.build_configuration_list = configuration_list(project, platform, deployment_target, type, language)
52
+
53
+ # Product
54
+ product = product_group.new_product_ref_for_target(target.product_name, type)
55
+ target.product_reference = product
56
+
57
+ # Build phases
58
+ build_phases_for_target_type(type).each { |phase| target.build_phases << project.new(phase) }
59
+
60
+ # Frameworks
61
+ unless type == :static_library
62
+ framework_name = (platform == :osx) ? 'Cocoa' : 'Foundation'
63
+ target.add_system_framework(framework_name)
64
+ end
65
+
66
+ target
67
+ end
68
+
69
+ # Creates a new resource bundles target and adds it to the project.
70
+ #
71
+ # The target is configured for the given platform and its file reference it
72
+ # is added to the {products_group}.
73
+ #
74
+ # The target is pre-populated with common build settings
75
+ #
76
+ # @param [Project] project
77
+ # the project to which the target should be added.
78
+ #
79
+ # @param [String] name
80
+ # the name of the resources bundle.
81
+ #
82
+ # @param [Symbol] platform
83
+ # the platform of the resources bundle. Can be `:ios` or `:osx`.
84
+ #
85
+ # @param [PBXGroup] product_group
86
+ # the product group, where to add to a file reference of the
87
+ # created target.
88
+ #
89
+ # @return [PBXNativeTarget] the target.
90
+ #
91
+ def self.new_resources_bundle(project, name, platform, product_group, product_basename)
92
+ # Target
93
+ target = project.new(PBXNativeTarget)
94
+ project.targets << target
95
+ target.name = name
96
+ target.product_name = product_basename
97
+ target.product_type = Constants::PRODUCT_TYPE_UTI[:bundle]
98
+
99
+ # Configuration List
100
+ cl = project.new(XCConfigurationList)
101
+ cl.default_configuration_is_visible = '0'
102
+ cl.default_configuration_name = 'Release'
103
+ release_conf = project.new(XCBuildConfiguration)
104
+ release_conf.name = 'Release'
105
+ release_conf.build_settings = common_build_settings(nil, platform, nil, target.product_type)
106
+ debug_conf = project.new(XCBuildConfiguration)
107
+ debug_conf.name = 'Debug'
108
+ debug_conf.build_settings = common_build_settings(nil, platform, nil, target.product_type)
109
+ cl.build_configurations << release_conf
110
+ cl.build_configurations << debug_conf
111
+ target.build_configuration_list = cl
112
+
113
+ # Product
114
+ product = product_group.new_bundle(target.product_name)
115
+ target.product_reference = product
116
+
117
+ # Build phases
118
+ build_phases_for_target_type(:bundle).each { |phase| target.build_phases << project.new(phase) }
119
+
120
+ target
121
+ end
122
+
123
+ # Creates a new aggregate target and adds it to the project.
124
+ #
125
+ # The target is configured for the given platform.
126
+ #
127
+ # @param [Project] project
128
+ # the project to which the target should be added.
129
+ #
130
+ # @param [String] name
131
+ # the name of the aggregate target.
132
+ #
133
+ # @param [Symbol] platform
134
+ # the platform of the aggregate target. Can be `:ios` or `:osx`.
135
+ #
136
+ # @param [String] deployment_target
137
+ # the deployment target for the platform.
138
+ #
139
+ # @return [PBXAggregateTarget] the target.
140
+ #
141
+ def self.new_aggregate_target(project, name, platform, deployment_target)
142
+ target = project.new(PBXAggregateTarget)
143
+ project.targets << target
144
+ target.name = name
145
+ target.build_configuration_list = configuration_list(project, platform, deployment_target)
146
+ target
147
+ end
148
+
149
+ # Creates a new legacy target and adds it to the project.
150
+ #
151
+ # The target is configured for the given platform.
152
+ #
153
+ # @param [Project] project
154
+ # the project to which the target should be added.
155
+ #
156
+ # @param [String] name
157
+ # the name of the aggregate target.
158
+ #
159
+ # @param [String] build_tool_path
160
+ # the build tool path to use for this target.
161
+ #
162
+ # @param [String] build_arguments_string
163
+ # the build arguments string to use for this target.
164
+ #
165
+ # @param [String] build_working_directory
166
+ # the build working directory to use for this target.
167
+ #
168
+ # @param [String] pass_build_settings_in_environment
169
+ # whether to pass build settings in the environment during execution of this target.
170
+ #
171
+ # @return [PBXLegacyTarget] the target.
172
+ #
173
+ def self.new_legacy_target(project, name, build_tool_path = '/usr/bin/make', build_arguments_string = '$(ACTION)',
174
+ build_working_directory = nil, pass_build_settings_in_environment = '1')
175
+ target = project.new(PBXLegacyTarget)
176
+ project.targets << target
177
+ target.name = name
178
+ target.build_configuration_list = configuration_list(project)
179
+ target.build_tool_path = build_tool_path
180
+ target.build_arguments_string = build_arguments_string
181
+ target.build_working_directory = build_working_directory
182
+ target.pass_build_settings_in_environment = pass_build_settings_in_environment
183
+ target
184
+ end
185
+
186
+ # @!group Private Helpers
187
+
188
+ #-----------------------------------------------------------------------#
189
+
190
+ # Returns a new configuration list, populated with release and debug
191
+ # configurations with common build settings for the given platform.
192
+ #
193
+ # @param [Project] project
194
+ # the project to which the configuration list should be added.
195
+ #
196
+ # @param [Symbol] platform
197
+ # the platform for the configuration list, can be `:ios` or `:osx`.
198
+ #
199
+ # @param [String] deployment_target
200
+ # the deployment target for the platform.
201
+ #
202
+ # @param [Symbol] target_product_type
203
+ # the product type of the target, can be any of `Constants::PRODUCT_TYPE_UTI.values`
204
+ # or `Constants::PRODUCT_TYPE_UTI.keys`.
205
+ #
206
+ # @param [Symbol] language
207
+ # the primary language of the target, can be `:objc` or `:swift`.
208
+ #
209
+ # @return [XCConfigurationList] the generated configuration list.
210
+ #
211
+ def self.configuration_list(project, platform = nil, deployment_target = nil, target_product_type = nil, language = nil)
212
+ cl = project.new(XCConfigurationList)
213
+ cl.default_configuration_is_visible = '0'
214
+ cl.default_configuration_name = 'Release'
215
+
216
+ release_conf = project.new(XCBuildConfiguration)
217
+ release_conf.name = 'Release'
218
+ release_conf.build_settings = common_build_settings(:release, platform, deployment_target, target_product_type, language)
219
+
220
+ debug_conf = project.new(XCBuildConfiguration)
221
+ debug_conf.name = 'Debug'
222
+ debug_conf.build_settings = common_build_settings(:debug, platform, deployment_target, target_product_type, language)
223
+
224
+ cl.build_configurations << release_conf
225
+ cl.build_configurations << debug_conf
226
+
227
+ existing_configurations = cl.build_configurations.map(&:name)
228
+ project.build_configurations.each do |configuration|
229
+ next if existing_configurations.include?(configuration.name)
230
+
231
+ new_config = project.new(XCBuildConfiguration)
232
+ new_config.name = configuration.name
233
+ new_config.build_settings = common_build_settings(configuration.type, platform, deployment_target, target_product_type, language)
234
+ cl.build_configurations << new_config
235
+ end
236
+
237
+ cl
238
+ end
239
+
240
+ # Returns the common build settings for a given platform and configuration
241
+ # name.
242
+ #
243
+ # @param [Symbol] type
244
+ # the type of the build configuration, can be `:release` or
245
+ # `:debug`.
246
+ #
247
+ # @param [Symbol] platform
248
+ # the platform for the build settings, can be `:ios` or `:osx`.
249
+ #
250
+ # @param [String] deployment_target
251
+ # the deployment target for the platform.
252
+ #
253
+ # @param [Symbol] target_product_type
254
+ # the product type of the target, can be any of
255
+ # `Constants::PRODUCT_TYPE_UTI.values`
256
+ # or `Constants::PRODUCT_TYPE_UTI.keys`. Default is :application.
257
+ #
258
+ # @param [Symbol] language
259
+ # the primary language of the target, can be `:objc` or `:swift`.
260
+ #
261
+ # @return [Hash] The common build settings
262
+ #
263
+ def self.common_build_settings(type, platform = nil, deployment_target = nil, target_product_type = nil, language = :objc)
264
+ target_product_type = (Constants::PRODUCT_TYPE_UTI.find { |_, v| v == target_product_type } || [target_product_type || :application])[0]
265
+ common_settings = Constants::COMMON_BUILD_SETTINGS
266
+
267
+ # Use intersecting settings for all key sets as base
268
+ settings = deep_dup(common_settings[:all])
269
+
270
+ # Match further common settings by key sets
271
+ keys = [type, platform, target_product_type, language].compact
272
+ key_combinations = (1..keys.length).flat_map { |n| keys.combination(n).to_a }
273
+ key_combinations.each do |key_combination|
274
+ settings.merge!(deep_dup(common_settings[key_combination] || {}))
275
+ end
276
+
277
+ if deployment_target
278
+ case platform
279
+ when :ios
280
+ settings['IPHONEOS_DEPLOYMENT_TARGET'] = deployment_target
281
+ settings['CLANG_ENABLE_OBJC_WEAK'] = 'NO' if deployment_target < '5'
282
+ when :osx
283
+ settings['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
284
+ settings['CLANG_ENABLE_OBJC_WEAK'] = 'NO' if deployment_target < '10.7'
285
+ when :tvos
286
+ settings['TVOS_DEPLOYMENT_TARGET'] = deployment_target
287
+ when :watchos
288
+ settings['WATCHOS_DEPLOYMENT_TARGET'] = deployment_target
289
+ end
290
+ end
291
+
292
+ settings
293
+ end
294
+
295
+ # Creates a deep copy of the given object
296
+ #
297
+ # @param [Object] object
298
+ # the object to copy.
299
+ #
300
+ # @return [Object] The deep copy of the object.
301
+ #
302
+ def self.deep_dup(object)
303
+ case object
304
+ when Hash
305
+ new_hash = {}
306
+ object.each do |key, value|
307
+ new_hash[key] = deep_dup(value)
308
+ end
309
+ new_hash
310
+ when Array
311
+ object.map { |value| deep_dup(value) }
312
+ else
313
+ object.dup
314
+ end
315
+ end
316
+
317
+ # Returns the build phases, in order, that appear by default
318
+ # on a target of the given type.
319
+ #
320
+ # @param [Symbol] type
321
+ # the name of the target type.
322
+ #
323
+ # @return [Array<String>] The list of build phase class names for the target type.
324
+ #
325
+ def self.build_phases_for_target_type(type)
326
+ case type
327
+ when :static_library, :dynamic_library
328
+ %w(Headers Sources Frameworks)
329
+ when :framework
330
+ %w(Headers Sources Frameworks Resources)
331
+ when :command_line_tool
332
+ %w(Sources Frameworks)
333
+ else
334
+ %w(Sources Frameworks Resources)
335
+ end.map { |phase| "PBX#{phase}BuildPhase" }
336
+ end
337
+
338
+ #-----------------------------------------------------------------------#
339
+ end
340
+ end
341
+ end
@@ -0,0 +1,132 @@
1
+ module Xcodeproj
2
+ class Project
3
+ class UUIDGenerator
4
+ require 'digest'
5
+
6
+ def initialize(projects)
7
+ @projects = Array(projects)
8
+ @paths_by_object = {}
9
+ end
10
+
11
+ def generate!
12
+ generate_all_paths_by_objects(@projects)
13
+
14
+ new_objects_by_project = Hash[@projects.map do |project|
15
+ [project, switch_uuids(project)]
16
+ end]
17
+ all_new_objects_by_project = new_objects_by_project.values.flat_map(&:values)
18
+ all_objects_by_uuid = @projects.map(&:objects_by_uuid).inject(:merge)
19
+ all_objects = @projects.flat_map(&:objects)
20
+ verify_no_duplicates!(all_objects, all_new_objects_by_project)
21
+ @projects.each { |project| fixup_uuid_references(project, all_objects_by_uuid) }
22
+ new_objects_by_project.each do |project, new_objects_by_uuid|
23
+ project.instance_variable_set(:@generated_uuids, project.instance_variable_get(:@available_uuids))
24
+ project.instance_variable_set(:@objects_by_uuid, new_objects_by_uuid)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ UUID_ATTRIBUTES = [:remote_global_id_string, :container_portal, :target_proxy].freeze
31
+
32
+ def verify_no_duplicates!(all_objects, all_new_objects)
33
+ duplicates = all_objects - all_new_objects
34
+ UserInterface.warn "[Xcodeproj] Generated duplicate UUIDs:\n\n" <<
35
+ duplicates.map { |d| "#{d.isa} -- #{@paths_by_object[d]}" }.join("\n") unless duplicates.empty?
36
+ end
37
+
38
+ def fixup_uuid_references(target_project, all_objects_by_uuid)
39
+ fixup = ->(object, attr) do
40
+ if object.respond_to?(attr) && link = all_objects_by_uuid[object.send(attr)]
41
+ object.send(:"#{attr}=", link.uuid)
42
+ end
43
+ end
44
+ target_project.objects.each do |object|
45
+ UUID_ATTRIBUTES.each do |attr|
46
+ fixup[object, attr]
47
+ end
48
+ end
49
+
50
+ if (project_attributes = target_project.root_object.attributes) && project_attributes['TargetAttributes']
51
+ project_attributes['TargetAttributes'] = Hash[project_attributes['TargetAttributes'].map do |target_uuid, attributes|
52
+ if test_target_id = attributes['TestTargetID']
53
+ attributes = attributes.merge('TestTargetID' => all_objects_by_uuid[test_target_id].uuid)
54
+ end
55
+ if target_object = all_objects_by_uuid[target_uuid]
56
+ target_uuid = target_object.uuid
57
+ end
58
+ [target_uuid, attributes]
59
+ end]
60
+ end
61
+ end
62
+
63
+ def generate_all_paths_by_objects(projects)
64
+ projects.each { |project| generate_paths(project.root_object, project.path.basename.to_s) }
65
+ end
66
+
67
+ def generate_paths(object, path = '')
68
+ existing = @paths_by_object[object] || path
69
+ return existing if @paths_by_object.key?(object)
70
+ @paths_by_object[object] = path.size > existing.size ? path : existing
71
+
72
+ object.to_one_attributes.each do |attrb|
73
+ obj = attrb.get_value(object)
74
+ generate_paths(obj, path + '/' << attrb.plist_name) if obj
75
+ end
76
+
77
+ object.to_many_attributes.each do |attrb|
78
+ attrb.get_value(object).each do |o|
79
+ generate_paths(o, path + '/' << attrb.plist_name << "/#{path_component_for_object(o)}")
80
+ end
81
+ end
82
+
83
+ object.references_by_keys_attributes.each do |attrb|
84
+ attrb.get_value(object).each do |dictionary|
85
+ dictionary.each do |key, value|
86
+ generate_paths(value, path + '/' << attrb.plist_name << "/k:#{key}/#{path_component_for_object(value)}")
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ def switch_uuids(project)
93
+ project.mark_dirty!
94
+ project.objects.each_with_object({}) do |object, hash|
95
+ next unless path = @paths_by_object[object]
96
+ uuid = uuid_for_path(path)
97
+ object.instance_variable_set(:@uuid, uuid)
98
+ hash[uuid] = object
99
+ end
100
+ end
101
+
102
+ def uuid_for_path(path)
103
+ Digest::MD5.hexdigest(path).upcase
104
+ end
105
+
106
+ def path_component_for_object(object)
107
+ @path_component_for_object ||= Hash.new do |cache, key|
108
+ component = tree_hash_to_path(key.to_tree_hash)
109
+ component << key.hierarchy_path.to_s if key.respond_to?(:hierarchy_path)
110
+ cache[key] = component
111
+ end
112
+ @path_component_for_object[object]
113
+ end
114
+
115
+ def tree_hash_to_path(object, depth = 4)
116
+ return '|' if depth.zero?
117
+ case object
118
+ when Hash
119
+ object.sort.each_with_object('') do |(key, value), string|
120
+ string << key << ':' << tree_hash_to_path(value, depth - 1) << ','
121
+ end
122
+ when Array
123
+ object.map do |value|
124
+ tree_hash_to_path(value, depth - 1)
125
+ end.join(',')
126
+ else
127
+ object.to_s
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end