xcodeproj 1.7.0 → 1.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/xcodeproj/command/config_dump.rb +5 -1
- data/lib/xcodeproj/config.rb +3 -1
- data/lib/xcodeproj/config/other_linker_flags_parser.rb +2 -2
- data/lib/xcodeproj/constants.rb +70 -44
- data/lib/xcodeproj/gem_version.rb +1 -1
- data/lib/xcodeproj/project.rb +23 -2
- data/lib/xcodeproj/project/object.rb +3 -1
- data/lib/xcodeproj/project/object/build_configuration.rb +96 -35
- data/lib/xcodeproj/project/object/build_file.rb +9 -1
- data/lib/xcodeproj/project/object/build_phase.rb +45 -4
- data/lib/xcodeproj/project/object/build_rule.rb +12 -0
- data/lib/xcodeproj/project/object/helpers/file_references_factory.rb +11 -4
- data/lib/xcodeproj/project/object/helpers/groupable_helper.rb +13 -6
- data/lib/xcodeproj/project/object/native_target.rb +52 -9
- data/lib/xcodeproj/project/object/root_object.rb +15 -2
- data/lib/xcodeproj/project/object/swift_package_product_dependency.rb +19 -0
- data/lib/xcodeproj/project/object/swift_package_remote_reference.rb +19 -0
- data/lib/xcodeproj/project/object/target_dependency.rb +9 -0
- data/lib/xcodeproj/project/project_helper.rb +2 -1
- data/lib/xcodeproj/project/uuid_generator.rb +41 -19
- data/lib/xcodeproj/scheme.rb +6 -4
- data/lib/xcodeproj/scheme/build_action.rb +21 -0
- data/lib/xcodeproj/scheme/buildable_reference.rb +3 -1
- data/lib/xcodeproj/scheme/launch_action.rb +50 -0
- data/lib/xcodeproj/scheme/test_action.rb +36 -1
- data/lib/xcodeproj/workspace.rb +16 -7
- data/lib/xcodeproj/workspace/file_reference.rb +7 -12
- data/lib/xcodeproj/workspace/group_reference.rb +18 -15
- data/lib/xcodeproj/workspace/reference.rb +40 -0
- metadata +11 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72f6eb6645b557dea09ae4be0fd400e48b0d4f1e42c31b7b61af87fd3c31a9cd
|
4
|
+
data.tar.gz: 0c0bcfa7abc28721f61f48e295198da53576e90d62161c50a6cc7333c1e94455
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f856d8cbee5b9b7b6bcbe7acce4034e8277fd05ac7caf0d2c317f75d622bb5c518dd2ddee67dac1c6a7fb2773aebb5a5de2cf2232af3fffc2353323fd08623d
|
7
|
+
data.tar.gz: 9cf088a34dea380b56716f005c35fc601d9b193a0a4908556d4f8ccc80408ee328755ccb767dc0ed50adc0bc3e822cc9bcdcdeac405c97fc514f6dd429f746ac
|
@@ -76,7 +76,11 @@ module Xcodeproj
|
|
76
76
|
|
77
77
|
def dump_config_to_file(settings, file_path, includes = [])
|
78
78
|
dir = @output_path + file_path + '..'
|
79
|
-
dir.
|
79
|
+
dir.mkpath
|
80
|
+
|
81
|
+
settings = Hash[settings.map do |k, v|
|
82
|
+
[k, Array(v).join(' ')]
|
83
|
+
end]
|
80
84
|
|
81
85
|
config = Config.new(settings)
|
82
86
|
config.includes = includes
|
data/lib/xcodeproj/config.rb
CHANGED
@@ -157,6 +157,8 @@ module Xcodeproj
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
+
alias_method :to_h, :to_hash
|
161
|
+
|
160
162
|
# @return [Set<String>] The list of the frameworks required by this
|
161
163
|
# settings file.
|
162
164
|
#
|
@@ -275,7 +277,7 @@ module Xcodeproj
|
|
275
277
|
string.split("\n").each do |line|
|
276
278
|
uncommented_line = strip_comment(line)
|
277
279
|
if include = extract_include(uncommented_line)
|
278
|
-
@includes.push include
|
280
|
+
@includes.push normalized_xcconfig_path(include)
|
279
281
|
else
|
280
282
|
key, value = extract_key_value(uncommented_line)
|
281
283
|
next unless key
|
@@ -55,13 +55,13 @@ module Xcodeproj
|
|
55
55
|
# The other linker flags value.
|
56
56
|
#
|
57
57
|
def self.split(flags)
|
58
|
-
flags.strip.shellsplit.
|
58
|
+
flags.strip.shellsplit.flat_map do |string|
|
59
59
|
if string =~ /\A-l.+/
|
60
60
|
['-l', string[2..-1]]
|
61
61
|
else
|
62
62
|
string
|
63
63
|
end
|
64
|
-
end
|
64
|
+
end
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
data/lib/xcodeproj/constants.rb
CHANGED
@@ -4,17 +4,19 @@ module Xcodeproj
|
|
4
4
|
module Constants
|
5
5
|
# @return [String] The last known iOS SDK (stable).
|
6
6
|
#
|
7
|
-
LAST_KNOWN_IOS_SDK = '
|
7
|
+
LAST_KNOWN_IOS_SDK = '14.0'
|
8
8
|
|
9
9
|
# @return [String] The last known OS X SDK (stable).
|
10
10
|
#
|
11
|
-
LAST_KNOWN_OSX_SDK = '10.
|
11
|
+
LAST_KNOWN_OSX_SDK = '10.15'
|
12
12
|
|
13
13
|
# @return [String] The last known tvOS SDK (stable).
|
14
|
-
|
14
|
+
#
|
15
|
+
LAST_KNOWN_TVOS_SDK = '14.0'
|
15
16
|
|
16
17
|
# @return [String] The last known watchOS SDK (stable).
|
17
|
-
|
18
|
+
#
|
19
|
+
LAST_KNOWN_WATCHOS_SDK = '7.0'
|
18
20
|
|
19
21
|
# @return [String] The last known archive version to Xcodeproj.
|
20
22
|
#
|
@@ -22,22 +24,23 @@ module Xcodeproj
|
|
22
24
|
|
23
25
|
# @return [String] The last known Swift version (stable).
|
24
26
|
#
|
25
|
-
LAST_KNOWN_SWIFT_VERSION = '
|
27
|
+
LAST_KNOWN_SWIFT_VERSION = '5.0'
|
26
28
|
|
27
29
|
# @return [String] The default object version for Xcodeproj.
|
30
|
+
#
|
28
31
|
DEFAULT_OBJECT_VERSION = 46
|
29
32
|
|
30
33
|
# @return [String] The last known object version to Xcodeproj.
|
31
34
|
#
|
32
|
-
LAST_KNOWN_OBJECT_VERSION =
|
35
|
+
LAST_KNOWN_OBJECT_VERSION = 54
|
33
36
|
|
34
37
|
# @return [String] The last known object version to Xcodeproj.
|
35
38
|
#
|
36
|
-
LAST_UPGRADE_CHECK = '
|
39
|
+
LAST_UPGRADE_CHECK = '1100'
|
37
40
|
|
38
41
|
# @return [String] The last known object version to Xcodeproj.
|
39
42
|
#
|
40
|
-
LAST_SWIFT_UPGRADE_CHECK = '
|
43
|
+
LAST_SWIFT_UPGRADE_CHECK = '1100'
|
41
44
|
|
42
45
|
# @return [String] The version of `.xcscheme` files supported by Xcodeproj
|
43
46
|
#
|
@@ -90,12 +93,14 @@ module Xcodeproj
|
|
90
93
|
'app' => 'wrapper.application',
|
91
94
|
'appex' => 'wrapper.app-extension',
|
92
95
|
'bundle' => 'wrapper.plug-in',
|
96
|
+
'cpp' => 'sourcecode.cpp.cpp',
|
93
97
|
'dylib' => 'compiled.mach-o.dylib',
|
94
98
|
'entitlements' => 'text.plist.entitlements',
|
95
99
|
'framework' => 'wrapper.framework',
|
96
100
|
'gif' => 'image.gif',
|
97
101
|
'gpx' => 'text.xml',
|
98
102
|
'h' => 'sourcecode.c.h',
|
103
|
+
'hpp' => 'sourcecode.cpp.h',
|
99
104
|
'm' => 'sourcecode.c.objc',
|
100
105
|
'markdown' => 'text',
|
101
106
|
'mdimporter' => 'wrapper.cfbundle',
|
@@ -120,44 +125,65 @@ module Xcodeproj
|
|
120
125
|
'zip' => 'archive.zip',
|
121
126
|
}.freeze
|
122
127
|
|
128
|
+
# @return [Hash] The compatibility version string for different object versions.
|
129
|
+
#
|
130
|
+
COMPATIBILITY_VERSION_BY_OBJECT_VERSION = {
|
131
|
+
54 => 'Xcode 12.0',
|
132
|
+
53 => 'Xcode 11.4',
|
133
|
+
52 => 'Xcode 11.0',
|
134
|
+
51 => 'Xcode 10.0',
|
135
|
+
50 => 'Xcode 9.3',
|
136
|
+
48 => 'Xcode 8.0',
|
137
|
+
47 => 'Xcode 6.3',
|
138
|
+
46 => 'Xcode 3.2',
|
139
|
+
45 => 'Xcode 3.1',
|
140
|
+
}.freeze
|
141
|
+
|
123
142
|
# @return [Hash] The uniform type identifier of various product types.
|
124
143
|
#
|
125
144
|
PRODUCT_TYPE_UTI = {
|
126
|
-
:application
|
127
|
-
:
|
128
|
-
:
|
129
|
-
:
|
130
|
-
:
|
131
|
-
:
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
135
|
-
:
|
136
|
-
:
|
137
|
-
:
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
143
|
-
:
|
144
|
-
:
|
145
|
+
:application => 'com.apple.product-type.application',
|
146
|
+
:application_on_demand_install_capable => 'com.apple.product-type.application.on-demand-install-capable',
|
147
|
+
:framework => 'com.apple.product-type.framework',
|
148
|
+
:dynamic_library => 'com.apple.product-type.library.dynamic',
|
149
|
+
:static_library => 'com.apple.product-type.library.static',
|
150
|
+
:bundle => 'com.apple.product-type.bundle',
|
151
|
+
:octest_bundle => 'com.apple.product-type.bundle',
|
152
|
+
:unit_test_bundle => 'com.apple.product-type.bundle.unit-test',
|
153
|
+
:ui_test_bundle => 'com.apple.product-type.bundle.ui-testing',
|
154
|
+
:app_extension => 'com.apple.product-type.app-extension',
|
155
|
+
:command_line_tool => 'com.apple.product-type.tool',
|
156
|
+
:watch_app => 'com.apple.product-type.application.watchapp',
|
157
|
+
:watch2_app => 'com.apple.product-type.application.watchapp2',
|
158
|
+
:watch2_app_container => 'com.apple.product-type.application.watchapp2-container',
|
159
|
+
:watch_extension => 'com.apple.product-type.watchkit-extension',
|
160
|
+
:watch2_extension => 'com.apple.product-type.watchkit2-extension',
|
161
|
+
:tv_extension => 'com.apple.product-type.tv-app-extension',
|
162
|
+
:messages_application => 'com.apple.product-type.application.messages',
|
163
|
+
:messages_extension => 'com.apple.product-type.app-extension.messages',
|
164
|
+
:sticker_pack => 'com.apple.product-type.app-extension.messages-sticker-pack',
|
165
|
+
:xpc_service => 'com.apple.product-type.xpc-service',
|
145
166
|
}.freeze
|
146
167
|
|
147
168
|
# @return [Hash] The extensions or the various product UTIs.
|
148
169
|
#
|
149
170
|
PRODUCT_UTI_EXTENSIONS = {
|
150
|
-
:application
|
151
|
-
:
|
152
|
-
:
|
153
|
-
:
|
154
|
-
:
|
155
|
-
:
|
156
|
-
:
|
157
|
-
:
|
158
|
-
:
|
159
|
-
:
|
160
|
-
:
|
171
|
+
:application => 'app',
|
172
|
+
:application_on_demand_install_capable => 'app',
|
173
|
+
:framework => 'framework',
|
174
|
+
:dynamic_library => 'dylib',
|
175
|
+
:static_library => 'a',
|
176
|
+
:bundle => 'bundle',
|
177
|
+
:octest_bundle => 'octest',
|
178
|
+
:unit_test_bundle => 'xctest',
|
179
|
+
:ui_test_bundle => 'xctest',
|
180
|
+
:app_extension => 'appex',
|
181
|
+
:messages_application => 'app',
|
182
|
+
:messages_extension => 'appex',
|
183
|
+
:sticker_pack => 'appex',
|
184
|
+
:watch2_extension => 'appex',
|
185
|
+
:watch2_app => 'app',
|
186
|
+
:watch2_app_container => 'app',
|
161
187
|
}.freeze
|
162
188
|
|
163
189
|
# @return [Hash] The common build settings grouped by platform, and build
|
@@ -178,11 +204,9 @@ module Xcodeproj
|
|
178
204
|
}.freeze,
|
179
205
|
[:ios] => {
|
180
206
|
'SDKROOT' => 'iphoneos',
|
181
|
-
'CODE_SIGN_IDENTITY' => 'iPhone Developer',
|
182
207
|
}.freeze,
|
183
208
|
[:osx] => {
|
184
209
|
'SDKROOT' => 'macosx',
|
185
|
-
'CODE_SIGN_IDENTITY' => '-',
|
186
210
|
}.freeze,
|
187
211
|
[:tvos] => {
|
188
212
|
'SDKROOT' => 'appletvos',
|
@@ -231,7 +255,6 @@ module Xcodeproj
|
|
231
255
|
[:debug, :static_library, :swift] => {
|
232
256
|
}.freeze,
|
233
257
|
[:framework] => {
|
234
|
-
'CODE_SIGN_IDENTITY' => '',
|
235
258
|
'CURRENT_PROJECT_VERSION' => '1',
|
236
259
|
'DEFINES_MODULE' => 'YES',
|
237
260
|
'DYLIB_COMPATIBILITY_VERSION' => '1',
|
@@ -249,7 +272,6 @@ module Xcodeproj
|
|
249
272
|
}.freeze,
|
250
273
|
[:osx, :framework] => {
|
251
274
|
'COMBINE_HIDPI_IMAGES' => 'YES',
|
252
|
-
'FRAMEWORK_VERSION' => 'A',
|
253
275
|
'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) @executable_path/../Frameworks @loader_path/Frameworks',
|
254
276
|
}.freeze,
|
255
277
|
[:watchos, :framework] => {
|
@@ -291,6 +313,7 @@ module Xcodeproj
|
|
291
313
|
}.freeze,
|
292
314
|
[:application] => {
|
293
315
|
'ASSETCATALOG_COMPILER_APPICON_NAME' => 'AppIcon',
|
316
|
+
'ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME' => 'AccentColor',
|
294
317
|
}.freeze,
|
295
318
|
[:ios, :application] => {
|
296
319
|
'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) @executable_path/Frameworks',
|
@@ -306,10 +329,12 @@ module Xcodeproj
|
|
306
329
|
}.freeze,
|
307
330
|
[:tvos, :application] => {
|
308
331
|
'ASSETCATALOG_COMPILER_APPICON_NAME' => 'App Icon & Top Shelf Image',
|
309
|
-
'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME' => 'LaunchImage',
|
310
332
|
'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) @executable_path/Frameworks',
|
311
333
|
'TARGETED_DEVICE_FAMILY' => '3',
|
312
334
|
}.freeze,
|
335
|
+
[:tvos, :application, :swift] => {
|
336
|
+
'ENABLE_PREVIEWS' => 'YES',
|
337
|
+
}.freeze,
|
313
338
|
[:watchos, :application, :swift] => {
|
314
339
|
'ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES' => 'YES',
|
315
340
|
}.freeze,
|
@@ -355,6 +380,7 @@ module Xcodeproj
|
|
355
380
|
'CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF' => 'YES',
|
356
381
|
'CLANG_WARN_OBJC_LITERAL_CONVERSION' => 'YES',
|
357
382
|
'CLANG_WARN_OBJC_ROOT_CLASS' => 'YES_ERROR',
|
383
|
+
'CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER' => 'YES',
|
358
384
|
'CLANG_WARN_RANGE_LOOP_ANALYSIS' => 'YES',
|
359
385
|
'CLANG_WARN_STRICT_PROTOTYPES' => 'YES',
|
360
386
|
'CLANG_WARN_SUSPICIOUS_MOVE' => 'YES',
|
@@ -372,7 +398,7 @@ module Xcodeproj
|
|
372
398
|
'GCC_WARN_UNUSED_VARIABLE' => 'YES',
|
373
399
|
'MTL_FAST_MATH' => 'YES',
|
374
400
|
'PRODUCT_NAME' => '$(TARGET_NAME)',
|
375
|
-
'SWIFT_VERSION' => '
|
401
|
+
'SWIFT_VERSION' => '5.0',
|
376
402
|
},
|
377
403
|
:release => {
|
378
404
|
'DEBUG_INFORMATION_FORMAT' => 'dwarf-with-dsym',
|
data/lib/xcodeproj/project.rb
CHANGED
@@ -80,6 +80,10 @@ module Xcodeproj
|
|
80
80
|
unless skip_initialization
|
81
81
|
initialize_from_scratch
|
82
82
|
@object_version = object_version.to_s
|
83
|
+
unless Constants::COMPATIBILITY_VERSION_BY_OBJECT_VERSION.key?(object_version)
|
84
|
+
raise ArgumentError, "[Xcodeproj] Unable to find compatibility version string for object version `#{object_version}`."
|
85
|
+
end
|
86
|
+
root_object.compatibility_version = Constants::COMPATIBILITY_VERSION_BY_OBJECT_VERSION[object_version]
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
@@ -388,7 +392,24 @@ module Xcodeproj
|
|
388
392
|
# @return [void]
|
389
393
|
#
|
390
394
|
def predictabilize_uuids
|
391
|
-
UUIDGenerator.new(self).generate!
|
395
|
+
UUIDGenerator.new([self]).generate!
|
396
|
+
end
|
397
|
+
|
398
|
+
# Replaces all the UUIDs in the list of provided projects with deterministic MD5 checksums.
|
399
|
+
#
|
400
|
+
# @param [Array<Project>] projects
|
401
|
+
#
|
402
|
+
# @note The current sorting of the project is taken into account when
|
403
|
+
# generating the new UUIDs.
|
404
|
+
#
|
405
|
+
# @note This method should only be used for entirely machine-generated
|
406
|
+
# projects, as true UUIDs are useful for tracking changes in the
|
407
|
+
# project.
|
408
|
+
#
|
409
|
+
# @return [void]
|
410
|
+
#
|
411
|
+
def self.predictabilize_uuids(projects)
|
412
|
+
UUIDGenerator.new(projects).generate!
|
392
413
|
end
|
393
414
|
|
394
415
|
public
|
@@ -568,7 +589,7 @@ module Xcodeproj
|
|
568
589
|
#
|
569
590
|
def embedded_targets_in_native_target(native_target)
|
570
591
|
native_targets.select do |target|
|
571
|
-
host_targets_for_embedded_target(target).
|
592
|
+
host_targets_for_embedded_target(target).any? { |host| host.uuid == native_target.uuid }
|
572
593
|
end
|
573
594
|
end
|
574
595
|
|
@@ -350,7 +350,7 @@ module Xcodeproj
|
|
350
350
|
unless object = project.objects_by_uuid[uuid] || project.new_from_plist(uuid, objects_by_uuid_plist)
|
351
351
|
UI.warn "`#{inspect}` attempted to initialize an object with " \
|
352
352
|
"an unknown UUID. `#{uuid}` for attribute: " \
|
353
|
-
"`#{attribute.name}`. This can be the result of a merge and
|
353
|
+
"`#{attribute.name}`. This can be the result of a merge and " \
|
354
354
|
'the unknown UUID is being discarded.'
|
355
355
|
end
|
356
356
|
object
|
@@ -518,6 +518,8 @@ Xcodeproj::Constants::KNOWN_ISAS.each do |superclass_name, isas|
|
|
518
518
|
end
|
519
519
|
|
520
520
|
# Now load the concrete subclasses.
|
521
|
+
require 'xcodeproj/project/object/swift_package_remote_reference'
|
522
|
+
require 'xcodeproj/project/object/swift_package_product_dependency'
|
521
523
|
require 'xcodeproj/project/object/build_configuration'
|
522
524
|
require 'xcodeproj/project/object/build_file'
|
523
525
|
require 'xcodeproj/project/object/build_phase'
|
@@ -6,6 +6,10 @@ module Xcodeproj
|
|
6
6
|
# {PBXProject} or a {PBXNativeTarget}.
|
7
7
|
#
|
8
8
|
class XCBuildConfiguration < AbstractObject
|
9
|
+
MUTUAL_RECURSION_SENTINEL = 'xcodeproj.mutual_recursion_sentinel'.freeze
|
10
|
+
|
11
|
+
private_constant :MUTUAL_RECURSION_SENTINEL
|
12
|
+
|
9
13
|
# @!group Attributes
|
10
14
|
|
11
15
|
# @return [String] the name of the Target.
|
@@ -79,21 +83,36 @@ module Xcodeproj
|
|
79
83
|
# the key of the build setting.
|
80
84
|
#
|
81
85
|
# @param [PBXNativeTarget] root_target
|
82
|
-
# use this to resolve complete recursion between project and targets
|
86
|
+
# use this to resolve complete recursion between project and targets.
|
87
|
+
#
|
88
|
+
# @param [String] previous_key
|
89
|
+
# use this to resolve complete recursion between different build settings.
|
83
90
|
#
|
84
91
|
# @return [String] The value of the build setting
|
85
92
|
#
|
86
|
-
def resolve_build_setting(key, root_target = nil)
|
93
|
+
def resolve_build_setting(key, root_target = nil, previous_key = nil)
|
87
94
|
setting = build_settings[key]
|
88
|
-
setting = resolve_variable_substitution(key, setting, root_target
|
89
|
-
|
90
|
-
config_setting =
|
95
|
+
setting = resolve_variable_substitution(key, setting, root_target, previous_key)
|
96
|
+
|
97
|
+
config_setting = config[key]
|
98
|
+
config_setting = resolve_variable_substitution(key, config_setting, root_target, previous_key)
|
91
99
|
|
92
100
|
project_setting = project.build_configuration_list[name]
|
93
|
-
project_setting = nil if project_setting
|
101
|
+
project_setting = nil if equal?(project_setting)
|
94
102
|
project_setting &&= project_setting.resolve_build_setting(key, root_target)
|
95
103
|
|
96
|
-
|
104
|
+
defaults = {
|
105
|
+
'CONFIGURATION' => name,
|
106
|
+
'SRCROOT' => project.project_dir.to_s,
|
107
|
+
}
|
108
|
+
|
109
|
+
# if previous_key is nil, it means that we're back at the first call, so we can replace our sentinel string
|
110
|
+
# used to prevent recursion with nil
|
111
|
+
if previous_key.nil? && setting == MUTUAL_RECURSION_SENTINEL
|
112
|
+
setting = nil
|
113
|
+
end
|
114
|
+
|
115
|
+
[defaults[key], project_setting, config_setting, setting, ENV[key]].compact.reduce(nil) do |inherited, value|
|
97
116
|
expand_build_setting(value, inherited)
|
98
117
|
end
|
99
118
|
end
|
@@ -102,15 +121,25 @@ module Xcodeproj
|
|
102
121
|
|
103
122
|
private
|
104
123
|
|
124
|
+
VARIABLE_NAME_PATTERN =
|
125
|
+
'( # capture block
|
126
|
+
[_a-zA-Z0-9]+? # non-greedy lookup for everything contained in this list
|
127
|
+
)'.freeze
|
128
|
+
private_constant :VARIABLE_NAME_PATTERN
|
129
|
+
|
105
130
|
CAPTURE_VARIABLE_IN_BUILD_CONFIG = /
|
106
131
|
\$ # matches dollar sign literally
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
[
|
111
|
-
|
112
|
-
|
132
|
+
(?: # non-capturing group
|
133
|
+
[{] # matches a single character on this list
|
134
|
+
#{VARIABLE_NAME_PATTERN}
|
135
|
+
[}] # matches a single character on this list
|
136
|
+
| # or
|
137
|
+
[(] # matches a single character on this list
|
138
|
+
#{VARIABLE_NAME_PATTERN}
|
139
|
+
[)] # matches a single character on this list
|
140
|
+
)
|
113
141
|
/x
|
142
|
+
private_constant :CAPTURE_VARIABLE_IN_BUILD_CONFIG
|
114
143
|
|
115
144
|
def expand_build_setting(build_setting_value, config_value)
|
116
145
|
if build_setting_value.is_a?(Array) && config_value.is_a?(String)
|
@@ -123,27 +152,52 @@ module Xcodeproj
|
|
123
152
|
inherited = config_value || default
|
124
153
|
|
125
154
|
return build_setting_value.gsub(Regexp.union(Constants::INHERITED_KEYWORDS), inherited) if build_setting_value.is_a? String
|
126
|
-
build_setting_value.
|
155
|
+
build_setting_value.flat_map { |value| Constants::INHERITED_KEYWORDS.include?(value) ? inherited : value }
|
127
156
|
end
|
128
157
|
|
129
|
-
def resolve_variable_substitution(key, value, root_target)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
158
|
+
def resolve_variable_substitution(key, value, root_target, previous_key = nil)
|
159
|
+
case value
|
160
|
+
when Array
|
161
|
+
return value.map { |v| resolve_variable_substitution(key, v, root_target) }
|
162
|
+
when nil
|
163
|
+
return
|
164
|
+
when String
|
165
|
+
# we know how to resolve strings!
|
166
|
+
nil
|
167
|
+
else
|
168
|
+
raise ArgumentError, "Settings values can only be nil, string, or array, got #{value.inspect} for #{key}"
|
139
169
|
end
|
140
|
-
resolve_variable_substitution(key, value.sub(CAPTURE_VARIABLE_IN_BUILD_CONFIG, resolve_variable_substitution(key, variable, root_target)), root_target)
|
141
|
-
end
|
142
170
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
171
|
+
unless variable_match_data = value.match(CAPTURE_VARIABLE_IN_BUILD_CONFIG)
|
172
|
+
# no variables left, return the value unchanged
|
173
|
+
return value
|
174
|
+
end
|
175
|
+
variable_reference, variable = *variable_match_data.values_at(0, 1, 2).compact
|
176
|
+
|
177
|
+
case variable
|
178
|
+
when 'inherited'
|
179
|
+
# this is handled separately, after resolving all other variable references
|
180
|
+
value
|
181
|
+
when key
|
182
|
+
# to prevent infinite recursion
|
183
|
+
nil
|
184
|
+
when previous_key
|
185
|
+
# to prevent infinite recursion; we don't return nil as for the self recursion because it needs to be
|
186
|
+
# distinguished outside this method too
|
187
|
+
MUTUAL_RECURSION_SENTINEL
|
188
|
+
else
|
189
|
+
configuration_to_resolve_against = root_target ? root_target.build_configuration_list[name] : self
|
190
|
+
resolved_value_for_variable = configuration_to_resolve_against.resolve_build_setting(variable, root_target, key) || ''
|
191
|
+
|
192
|
+
# we use this sentinel string instead of nil, because, otherwise, it would be swallowed by the default empty
|
193
|
+
# string from the preceding line, and we want to distinguish between mutual recursion and other cases
|
194
|
+
if resolved_value_for_variable == MUTUAL_RECURSION_SENTINEL
|
195
|
+
return MUTUAL_RECURSION_SENTINEL
|
196
|
+
end
|
197
|
+
|
198
|
+
value = value.gsub(variable_reference, resolved_value_for_variable)
|
199
|
+
resolve_variable_substitution(key, value, root_target)
|
200
|
+
end
|
147
201
|
end
|
148
202
|
|
149
203
|
def sorted_build_settings
|
@@ -161,14 +215,15 @@ module Xcodeproj
|
|
161
215
|
|
162
216
|
settings.keys.each do |key|
|
163
217
|
next unless value = settings[key]
|
218
|
+
stripped_key = key.sub(/\[[^\]]+\]$/, '')
|
164
219
|
case value
|
165
220
|
when String
|
166
|
-
next unless array_settings.include?(
|
221
|
+
next unless array_settings.include?(stripped_key)
|
167
222
|
array_value = split_build_setting_array_to_string(value)
|
168
223
|
next unless array_value.size > 1
|
169
224
|
settings[key] = array_value
|
170
225
|
when Array
|
171
|
-
next if value.size > 1 && array_settings.include?(
|
226
|
+
next if value.size > 1 && array_settings.include?(stripped_key)
|
172
227
|
settings[key] = value.join(' ')
|
173
228
|
end
|
174
229
|
end
|
@@ -180,9 +235,15 @@ module Xcodeproj
|
|
180
235
|
end
|
181
236
|
|
182
237
|
def config
|
183
|
-
|
184
|
-
|
185
|
-
|
238
|
+
return {} unless base_configuration_reference
|
239
|
+
@config ||=
|
240
|
+
if base_configuration_reference.real_path.exist?
|
241
|
+
Xcodeproj::Config.new(base_configuration_reference.real_path).to_hash.tap do |hash|
|
242
|
+
normalize_array_settings(hash)
|
243
|
+
end
|
244
|
+
else
|
245
|
+
{}
|
246
|
+
end
|
186
247
|
end
|
187
248
|
|
188
249
|
#---------------------------------------------------------------------#
|