plasmo_xcodeproj 1.21.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +95 -0
- data/bin/xcodeproj +10 -0
- data/lib/xcodeproj/command/config_dump.rb +91 -0
- data/lib/xcodeproj/command/project_diff.rb +56 -0
- data/lib/xcodeproj/command/show.rb +60 -0
- data/lib/xcodeproj/command/sort.rb +44 -0
- data/lib/xcodeproj/command/target_diff.rb +43 -0
- data/lib/xcodeproj/command.rb +63 -0
- data/lib/xcodeproj/config/other_linker_flags_parser.rb +73 -0
- data/lib/xcodeproj/config.rb +386 -0
- data/lib/xcodeproj/constants.rb +465 -0
- data/lib/xcodeproj/differ.rb +239 -0
- data/lib/xcodeproj/gem_version.rb +5 -0
- data/lib/xcodeproj/helper.rb +30 -0
- data/lib/xcodeproj/plist.rb +94 -0
- data/lib/xcodeproj/project/case_converter.rb +90 -0
- data/lib/xcodeproj/project/object/build_configuration.rb +255 -0
- data/lib/xcodeproj/project/object/build_file.rb +84 -0
- data/lib/xcodeproj/project/object/build_phase.rb +369 -0
- data/lib/xcodeproj/project/object/build_rule.rb +109 -0
- data/lib/xcodeproj/project/object/configuration_list.rb +117 -0
- data/lib/xcodeproj/project/object/container_item_proxy.rb +116 -0
- data/lib/xcodeproj/project/object/file_reference.rb +338 -0
- data/lib/xcodeproj/project/object/group.rb +506 -0
- data/lib/xcodeproj/project/object/helpers/build_settings_array_settings_by_object_version.rb +72 -0
- data/lib/xcodeproj/project/object/helpers/file_references_factory.rb +245 -0
- data/lib/xcodeproj/project/object/helpers/groupable_helper.rb +260 -0
- data/lib/xcodeproj/project/object/native_target.rb +751 -0
- data/lib/xcodeproj/project/object/reference_proxy.rb +86 -0
- data/lib/xcodeproj/project/object/root_object.rb +100 -0
- data/lib/xcodeproj/project/object/swift_package_product_dependency.rb +29 -0
- data/lib/xcodeproj/project/object/swift_package_remote_reference.rb +33 -0
- data/lib/xcodeproj/project/object/target_dependency.rb +94 -0
- data/lib/xcodeproj/project/object.rb +534 -0
- data/lib/xcodeproj/project/object_attributes.rb +522 -0
- data/lib/xcodeproj/project/object_dictionary.rb +210 -0
- data/lib/xcodeproj/project/object_list.rb +223 -0
- data/lib/xcodeproj/project/project_helper.rb +341 -0
- data/lib/xcodeproj/project/uuid_generator.rb +132 -0
- data/lib/xcodeproj/project.rb +874 -0
- data/lib/xcodeproj/scheme/abstract_scheme_action.rb +100 -0
- data/lib/xcodeproj/scheme/analyze_action.rb +19 -0
- data/lib/xcodeproj/scheme/archive_action.rb +59 -0
- data/lib/xcodeproj/scheme/build_action.rb +298 -0
- data/lib/xcodeproj/scheme/buildable_product_runnable.rb +55 -0
- data/lib/xcodeproj/scheme/buildable_reference.rb +129 -0
- data/lib/xcodeproj/scheme/command_line_arguments.rb +162 -0
- data/lib/xcodeproj/scheme/environment_variables.rb +170 -0
- data/lib/xcodeproj/scheme/execution_action.rb +86 -0
- data/lib/xcodeproj/scheme/launch_action.rb +179 -0
- data/lib/xcodeproj/scheme/location_scenario_reference.rb +49 -0
- data/lib/xcodeproj/scheme/macro_expansion.rb +34 -0
- data/lib/xcodeproj/scheme/profile_action.rb +57 -0
- data/lib/xcodeproj/scheme/remote_runnable.rb +92 -0
- data/lib/xcodeproj/scheme/send_email_action_content.rb +84 -0
- data/lib/xcodeproj/scheme/shell_script_action_content.rb +77 -0
- data/lib/xcodeproj/scheme/test_action.rb +394 -0
- data/lib/xcodeproj/scheme/xml_element_wrapper.rb +82 -0
- data/lib/xcodeproj/scheme.rb +375 -0
- data/lib/xcodeproj/user_interface.rb +22 -0
- data/lib/xcodeproj/workspace/file_reference.rb +79 -0
- data/lib/xcodeproj/workspace/group_reference.rb +67 -0
- data/lib/xcodeproj/workspace/reference.rb +40 -0
- data/lib/xcodeproj/workspace.rb +277 -0
- data/lib/xcodeproj/xcodebuild_helper.rb +108 -0
- data/lib/xcodeproj.rb +29 -0
- metadata +208 -0
@@ -0,0 +1,386 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'shellwords'
|
3
|
+
require 'xcodeproj/config/other_linker_flags_parser'
|
4
|
+
|
5
|
+
module Xcodeproj
|
6
|
+
# This class holds the data for a Xcode build settings file (xcconfig) and
|
7
|
+
# provides support for serialization.
|
8
|
+
#
|
9
|
+
class Config
|
10
|
+
require 'set'
|
11
|
+
|
12
|
+
KEY_VALUE_PATTERN = /
|
13
|
+
(
|
14
|
+
[^=\[]+ # Any char, but not an assignment operator
|
15
|
+
# or subscript (non-greedy)
|
16
|
+
(?: # One or multiple conditional subscripts
|
17
|
+
\[
|
18
|
+
[^\]]* # The subscript key
|
19
|
+
(?:
|
20
|
+
= # The subscript comparison operator
|
21
|
+
[^\]]* # The subscript value
|
22
|
+
)?
|
23
|
+
\]
|
24
|
+
)*
|
25
|
+
)
|
26
|
+
\s* # Whitespaces after the key (needed because subscripts
|
27
|
+
# always end with ']')
|
28
|
+
= # The assignment operator
|
29
|
+
(.*) # The value
|
30
|
+
/x
|
31
|
+
private_constant :KEY_VALUE_PATTERN
|
32
|
+
|
33
|
+
INHERITED = %w($(inherited) ${inherited}).freeze
|
34
|
+
private_constant :INHERITED
|
35
|
+
|
36
|
+
INHERITED_REGEXP = Regexp.union(INHERITED)
|
37
|
+
private_constant :INHERITED_REGEXP
|
38
|
+
|
39
|
+
# @return [Hash{String => String}] The attributes of the settings file
|
40
|
+
# excluding frameworks, weak_framework and libraries.
|
41
|
+
#
|
42
|
+
attr_accessor :attributes
|
43
|
+
|
44
|
+
# @return [Hash{Symbol => Set<String>}] The other linker flags by key.
|
45
|
+
# Xcodeproj handles them in a dedicated way to prevent duplication
|
46
|
+
# of the libraries and of the frameworks.
|
47
|
+
#
|
48
|
+
attr_accessor :other_linker_flags
|
49
|
+
|
50
|
+
# @return [Array] The list of the configuration files included by this
|
51
|
+
# configuration file (`#include "SomeConfig"`).
|
52
|
+
#
|
53
|
+
attr_accessor :includes
|
54
|
+
|
55
|
+
# @param [Hash, File, String] xcconfig_hash_or_file
|
56
|
+
# The initial data.
|
57
|
+
#
|
58
|
+
def initialize(xcconfig_hash_or_file = {})
|
59
|
+
@attributes = {}
|
60
|
+
@includes = []
|
61
|
+
@other_linker_flags = {}
|
62
|
+
[:simple, :frameworks, :weak_frameworks, :libraries, :arg_files, :force_load].each do |key|
|
63
|
+
@other_linker_flags[key] = Set.new
|
64
|
+
end
|
65
|
+
merge!(extract_hash(xcconfig_hash_or_file))
|
66
|
+
end
|
67
|
+
|
68
|
+
def inspect
|
69
|
+
to_hash.inspect
|
70
|
+
end
|
71
|
+
|
72
|
+
def ==(other)
|
73
|
+
other.attributes == attributes && other.other_linker_flags == other_linker_flags && other.includes == includes
|
74
|
+
end
|
75
|
+
|
76
|
+
public
|
77
|
+
|
78
|
+
# @!group Serialization
|
79
|
+
#-------------------------------------------------------------------------#
|
80
|
+
|
81
|
+
# Sorts the internal data by setting name and serializes it in the xcconfig
|
82
|
+
# format.
|
83
|
+
#
|
84
|
+
# @example
|
85
|
+
#
|
86
|
+
# config = Config.new('PODS_ROOT' => '"$(SRCROOT)/Pods"', 'OTHER_LDFLAGS' => '-lxml2')
|
87
|
+
# config.to_s # => "OTHER_LDFLAGS = -lxml2\nPODS_ROOT = \"$(SRCROOT)/Pods\""
|
88
|
+
#
|
89
|
+
# @return [String] The serialized internal data.
|
90
|
+
#
|
91
|
+
def to_s(prefix = nil)
|
92
|
+
include_lines = includes.map { |path| "#include \"#{normalized_xcconfig_path(path)}\"" }
|
93
|
+
settings = to_hash(prefix).sort_by(&:first).map { |k, v| "#{k} = #{v}".strip }
|
94
|
+
(include_lines + settings).join("\n") << "\n"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Writes the serialized representation of the internal data to the given
|
98
|
+
# path.
|
99
|
+
#
|
100
|
+
# @param [Pathname] pathname
|
101
|
+
# The file where the data should be written to.
|
102
|
+
#
|
103
|
+
# @return [void]
|
104
|
+
#
|
105
|
+
def save_as(pathname, prefix = nil)
|
106
|
+
if File.exist?(pathname)
|
107
|
+
return if Config.new(pathname) == self
|
108
|
+
end
|
109
|
+
|
110
|
+
pathname.open('w') { |file| file << to_s(prefix) }
|
111
|
+
end
|
112
|
+
|
113
|
+
# The hash representation of the xcconfig. The hash includes the
|
114
|
+
# frameworks, the weak frameworks, the libraries and the simple other
|
115
|
+
# linker flags in the `Other Linker Flags` (`OTHER_LDFLAGS`).
|
116
|
+
#
|
117
|
+
# @note All the values are sorted to have a consistent output in Ruby
|
118
|
+
# 1.8.7.
|
119
|
+
#
|
120
|
+
# @return [Hash] The hash representation
|
121
|
+
#
|
122
|
+
def to_hash(prefix = nil)
|
123
|
+
list = []
|
124
|
+
list += other_linker_flags[:simple].to_a.sort
|
125
|
+
modifiers = {
|
126
|
+
:frameworks => '-framework ',
|
127
|
+
:weak_frameworks => '-weak_framework ',
|
128
|
+
:libraries => '-l',
|
129
|
+
:arg_files => '@',
|
130
|
+
:force_load => '-force_load',
|
131
|
+
}
|
132
|
+
[:libraries, :frameworks, :weak_frameworks, :arg_files, :force_load].each do |key|
|
133
|
+
modifier = modifiers[key]
|
134
|
+
sorted = other_linker_flags[key].to_a.sort
|
135
|
+
if key == :force_load
|
136
|
+
list += sorted.map { |l| %(#{modifier} #{l}) }
|
137
|
+
else
|
138
|
+
list += sorted.map { |l| %(#{modifier}"#{l}") }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
result = attributes.dup
|
143
|
+
result['OTHER_LDFLAGS'] = list.join(' ') unless list.empty?
|
144
|
+
result.reject! { |_, v| INHERITED.any? { |i| i == v.to_s.strip } }
|
145
|
+
|
146
|
+
result = @includes.map do |incl|
|
147
|
+
path = File.expand_path(incl, @filepath.dirname)
|
148
|
+
if File.readable? path
|
149
|
+
Xcodeproj::Config.new(path).to_hash
|
150
|
+
else
|
151
|
+
{}
|
152
|
+
end
|
153
|
+
end.inject(&:merge).merge(result) unless @filepath.nil? || @includes.empty?
|
154
|
+
|
155
|
+
if prefix
|
156
|
+
Hash[result.map { |k, v| [prefix + k, v] }]
|
157
|
+
else
|
158
|
+
result
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
alias_method :to_h, :to_hash
|
163
|
+
|
164
|
+
# @return [Set<String>] The list of the frameworks required by this
|
165
|
+
# settings file.
|
166
|
+
#
|
167
|
+
def frameworks
|
168
|
+
other_linker_flags[:frameworks]
|
169
|
+
end
|
170
|
+
|
171
|
+
# @return [Set<String>] The list of the *weak* frameworks required by
|
172
|
+
# this settings file.
|
173
|
+
#
|
174
|
+
def weak_frameworks
|
175
|
+
other_linker_flags[:weak_frameworks]
|
176
|
+
end
|
177
|
+
|
178
|
+
# @return [Set<String>] The list of the libraries required by this
|
179
|
+
# settings file.
|
180
|
+
#
|
181
|
+
def libraries
|
182
|
+
other_linker_flags[:libraries]
|
183
|
+
end
|
184
|
+
|
185
|
+
# @return [Set<String>] The list of the arg files required by this
|
186
|
+
# settings file.
|
187
|
+
#
|
188
|
+
def arg_files
|
189
|
+
other_linker_flags[:arg_files]
|
190
|
+
end
|
191
|
+
|
192
|
+
public
|
193
|
+
|
194
|
+
# @!group Merging
|
195
|
+
#-------------------------------------------------------------------------#
|
196
|
+
|
197
|
+
# Merges the given xcconfig representation in the receiver.
|
198
|
+
#
|
199
|
+
# @example
|
200
|
+
#
|
201
|
+
# config = Config.new('PODS_ROOT' => '"$(SRCROOT)/Pods"', 'OTHER_LDFLAGS' => '-lxml2')
|
202
|
+
# config.merge!('OTHER_LDFLAGS' => '-lz', 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers"')
|
203
|
+
# config.to_hash # => { 'PODS_ROOT' => '"$(SRCROOT)/Pods"', 'OTHER_LDFLAGS' => '-lxml2 -lz', 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers"' }
|
204
|
+
#
|
205
|
+
# @note If a key in the given hash already exists in the internal data
|
206
|
+
# then its value is appended.
|
207
|
+
#
|
208
|
+
# @param [Hash, Config] config
|
209
|
+
# The xcconfig representation to merge.
|
210
|
+
#
|
211
|
+
# @todo The logic to normalize an hash should be extracted and the
|
212
|
+
# initializer should not call this method.
|
213
|
+
#
|
214
|
+
# @return [void]
|
215
|
+
#
|
216
|
+
def merge!(xcconfig)
|
217
|
+
if xcconfig.is_a? Config
|
218
|
+
merge_attributes!(xcconfig.attributes)
|
219
|
+
other_linker_flags.keys.each do |key|
|
220
|
+
other_linker_flags[key].merge(xcconfig.other_linker_flags[key])
|
221
|
+
end
|
222
|
+
else
|
223
|
+
merge_attributes!(xcconfig.to_hash)
|
224
|
+
if flags = attributes.delete('OTHER_LDFLAGS')
|
225
|
+
flags_by_key = OtherLinkerFlagsParser.parse(flags)
|
226
|
+
other_linker_flags.keys.each do |key|
|
227
|
+
other_linker_flags[key].merge(flags_by_key[key])
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
alias_method :<<, :merge!
|
233
|
+
|
234
|
+
# Creates a new #{Config} with the data of the receiver merged with the
|
235
|
+
# given xcconfig representation.
|
236
|
+
#
|
237
|
+
# @param [Hash, Config] config
|
238
|
+
# The xcconfig representation to merge.
|
239
|
+
#
|
240
|
+
# @return [Config] the new xcconfig.
|
241
|
+
#
|
242
|
+
def merge(config)
|
243
|
+
dup.tap { |x| x.merge!(config) }
|
244
|
+
end
|
245
|
+
|
246
|
+
# @return [Config] A copy of the receiver.
|
247
|
+
#
|
248
|
+
def dup
|
249
|
+
Xcodeproj::Config.new(to_hash.dup)
|
250
|
+
end
|
251
|
+
|
252
|
+
#-------------------------------------------------------------------------#
|
253
|
+
|
254
|
+
private
|
255
|
+
|
256
|
+
# @!group Private Helpers
|
257
|
+
|
258
|
+
# Returns a hash from the given argument reading it from disk if necessary.
|
259
|
+
#
|
260
|
+
# @param [String, Pathname, Hash] argument
|
261
|
+
# The source from where the hash should be extracted.
|
262
|
+
#
|
263
|
+
# @return [Hash]
|
264
|
+
#
|
265
|
+
def extract_hash(argument)
|
266
|
+
return argument if argument.is_a?(Hash)
|
267
|
+
if argument.respond_to? :read
|
268
|
+
@filepath = Pathname.new(argument.to_path)
|
269
|
+
hash_from_file_content(argument.read)
|
270
|
+
elsif File.readable?(argument.to_s)
|
271
|
+
@filepath = Pathname.new(argument.to_s)
|
272
|
+
hash_from_file_content(File.read(argument))
|
273
|
+
else
|
274
|
+
argument
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# Returns a hash from the string representation of an Xcconfig file.
|
279
|
+
#
|
280
|
+
# @param [String] string
|
281
|
+
# The string representation of an xcconfig file.
|
282
|
+
#
|
283
|
+
# @return [Hash] the hash containing the xcconfig data.
|
284
|
+
#
|
285
|
+
def hash_from_file_content(string)
|
286
|
+
hash = {}
|
287
|
+
string.split("\n").each do |line|
|
288
|
+
uncommented_line = strip_comment(line)
|
289
|
+
if include = extract_include(uncommented_line)
|
290
|
+
@includes.push normalized_xcconfig_path(include)
|
291
|
+
else
|
292
|
+
key, value = extract_key_value(uncommented_line)
|
293
|
+
next unless key
|
294
|
+
value.gsub!(INHERITED_REGEXP) { |m| hash.fetch(key, m) }
|
295
|
+
hash[key] = value
|
296
|
+
end
|
297
|
+
end
|
298
|
+
hash
|
299
|
+
end
|
300
|
+
|
301
|
+
# Merges the given attributes hash while ensuring values are not duplicated.
|
302
|
+
#
|
303
|
+
# @param [Hash] attributes
|
304
|
+
# The attributes hash to merge into @attributes.
|
305
|
+
#
|
306
|
+
# @return [void]
|
307
|
+
#
|
308
|
+
def merge_attributes!(attributes)
|
309
|
+
@attributes.merge!(attributes) do |_, v1, v2|
|
310
|
+
v1 = v1.strip
|
311
|
+
v2 = v2.strip
|
312
|
+
v1_split = v1.shellsplit
|
313
|
+
v2_split = v2.shellsplit
|
314
|
+
if (v2_split - v1_split).empty? || v1_split.first(v2_split.size) == v2_split
|
315
|
+
v1
|
316
|
+
elsif v2_split.first(v1_split.size) == v1_split
|
317
|
+
v2
|
318
|
+
else
|
319
|
+
"#{v1} #{v2}"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
# Strips the comments from a line of an xcconfig string.
|
325
|
+
#
|
326
|
+
# @param [String] line
|
327
|
+
# the line to process.
|
328
|
+
#
|
329
|
+
# @return [String] the uncommented line.
|
330
|
+
#
|
331
|
+
def strip_comment(line)
|
332
|
+
line.partition('//').first
|
333
|
+
end
|
334
|
+
|
335
|
+
# Returns the file included by a line of an xcconfig string if present.
|
336
|
+
#
|
337
|
+
# @param [String] line
|
338
|
+
# the line to process.
|
339
|
+
#
|
340
|
+
# @return [String] the included file.
|
341
|
+
# @return [Nil] if no include was found in the line.
|
342
|
+
#
|
343
|
+
def extract_include(line)
|
344
|
+
regexp = /#include\s*"(.+)"/
|
345
|
+
match = line.match(regexp)
|
346
|
+
match[1] if match
|
347
|
+
end
|
348
|
+
|
349
|
+
# Returns the key and the value described by the given line of an xcconfig.
|
350
|
+
#
|
351
|
+
# @param [String] line
|
352
|
+
# the line to process.
|
353
|
+
#
|
354
|
+
# @return [Array] A tuple where the first entry is the key and the second
|
355
|
+
# entry is the value.
|
356
|
+
#
|
357
|
+
def extract_key_value(line)
|
358
|
+
match = line.match(KEY_VALUE_PATTERN)
|
359
|
+
if match
|
360
|
+
key = match[1]
|
361
|
+
value = match[2]
|
362
|
+
[key.strip, value.strip]
|
363
|
+
else
|
364
|
+
[]
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
# Normalizes the given path to an xcconfing file to be used in includes,
|
369
|
+
# appending the extension if necessary.
|
370
|
+
#
|
371
|
+
# @param [String] path
|
372
|
+
# The path of the file which will be included in the xcconfig.
|
373
|
+
#
|
374
|
+
# @return [String] The normalized path.
|
375
|
+
#
|
376
|
+
def normalized_xcconfig_path(path)
|
377
|
+
if File.extname(path) == '.xcconfig'
|
378
|
+
path
|
379
|
+
else
|
380
|
+
"#{path}.xcconfig"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
#-------------------------------------------------------------------------#
|
385
|
+
end
|
386
|
+
end
|