xcodeproj 1.14.0 → 1.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/xcodeproj/command/sort.rb +12 -1
  4. data/lib/xcodeproj/config/other_linker_flags_parser.rb +5 -0
  5. data/lib/xcodeproj/config.rb +12 -2
  6. data/lib/xcodeproj/constants.rb +63 -49
  7. data/lib/xcodeproj/gem_version.rb +1 -1
  8. data/lib/xcodeproj/project/object/build_configuration.rb +33 -8
  9. data/lib/xcodeproj/project/object/build_file.rb +7 -1
  10. data/lib/xcodeproj/project/object/build_phase.rb +31 -0
  11. data/lib/xcodeproj/project/object/group.rb +11 -9
  12. data/lib/xcodeproj/project/object/helpers/file_references_factory.rb +8 -6
  13. data/lib/xcodeproj/project/object/helpers/groupable_helper.rb +2 -2
  14. data/lib/xcodeproj/project/object/native_target.rb +43 -0
  15. data/lib/xcodeproj/project/object/swift_package_product_dependency.rb +10 -0
  16. data/lib/xcodeproj/project/object/swift_package_remote_reference.rb +14 -0
  17. data/lib/xcodeproj/project/object/target_dependency.rb +1 -0
  18. data/lib/xcodeproj/project/project_helper.rb +6 -6
  19. data/lib/xcodeproj/project.rb +9 -6
  20. data/lib/xcodeproj/scheme/abstract_scheme_action.rb +72 -0
  21. data/lib/xcodeproj/scheme/build_action.rb +108 -1
  22. data/lib/xcodeproj/scheme/execution_action.rb +86 -0
  23. data/lib/xcodeproj/scheme/launch_action.rb +33 -2
  24. data/lib/xcodeproj/scheme/location_scenario_reference.rb +49 -0
  25. data/lib/xcodeproj/scheme/profile_action.rb +5 -5
  26. data/lib/xcodeproj/scheme/send_email_action_content.rb +84 -0
  27. data/lib/xcodeproj/scheme/shell_script_action_content.rb +77 -0
  28. data/lib/xcodeproj/scheme/test_action.rb +26 -3
  29. data/lib/xcodeproj/scheme.rb +5 -1
  30. data/lib/xcodeproj/workspace/file_reference.rb +1 -1
  31. data/lib/xcodeproj/workspace.rb +3 -2
  32. metadata +26 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3af9cb46ce94c2bb3e0bff2b7b28e82f5a037788378fa512274f685d41c2910b
4
- data.tar.gz: 4047b7ac654f2aaeaba3363e56362249c2ce4456cea8e73eb27cd731648d4792
3
+ metadata.gz: 7bab98461310ae1a7572bae0b8dd9025cdf12ee53a64c7d457e8d4982d71982d
4
+ data.tar.gz: 59d1ddc2130ee7f88eb646a1c98dbf14e45da612448a12425df004d416f93961
5
5
  SHA512:
6
- metadata.gz: c47d7f26b3c3078f7cf2094aa81fd809cf938d9741530d09c166a37b3bc0a98e9e4e59e2b51222d1c43b64f9620ff35c0c83077ca6331b49bebed117fa6891f8
7
- data.tar.gz: 65a27789a94d192a1d7c25c851d3ab36fab276f70145432c5a1ca3ecd398ca6f571206aee498d59c05dc688542ca2facd4bac7de08845a936e8cb54452c3073e
6
+ metadata.gz: 4e2431ba9cbf960b7e1ef53ff3dae65565b51fbba1cbb0c6a096d29251ca49c751403575c46fdae6252e176b8ada16ac5aa659d6b015f142eb338e21718a7a38
7
+ data.tar.gz: dfe1895012ba35e32dd44b15b4b2cb5e8ab2957eb7919f39a514c7675b8a261a4f4688006ace24e6eae0dcfc07be70392cf047f0cb66bd8f1036bc3fe817f366
data/README.md CHANGED
@@ -10,7 +10,7 @@ support for Xcode workspaces (`.xcworkspace`), configuration files (`.xcconfig`)
10
10
  Xcode Scheme files (`.xcscheme`).
11
11
 
12
12
  It is used in [CocoaPods](https://github.com/CocoaPods/CocoaPods) to create a
13
- a collection of supplemental libraries or frameworks, for all platforms Xcode supports.
13
+ collection of supplemental libraries or frameworks, for all platforms Xcode supports.
14
14
 
15
15
  The API reference can be found [here](http://www.rubydoc.info/gems/xcodeproj).
16
16
 
@@ -9,22 +9,33 @@ module Xcodeproj
9
9
 
10
10
  self.summary = 'Sorts the given project.'
11
11
 
12
+ def self.options
13
+ [
14
+ ['--group-option=[above|below]', 'The position of the groups when sorting. If no option is specified, sorting will interleave groups and files.'],
15
+ ].concat(super)
16
+ end
17
+
12
18
  self.arguments = [
13
19
  CLAide::Argument.new('PROJECT', false),
14
20
  ]
15
21
 
16
22
  def initialize(argv)
17
23
  self.xcodeproj_path = argv.shift_argument
24
+ @group_option = argv.option('group-option')
25
+ @group_option &&= @group_option.to_sym
18
26
  super
19
27
  end
20
28
 
21
29
  def validate!
22
30
  super
31
+ unless [nil, :above, :below].include?(@group_option)
32
+ help! "Unknown format `#{@group_option}`"
33
+ end
23
34
  open_project!
24
35
  end
25
36
 
26
37
  def run
27
- xcodeproj.sort
38
+ xcodeproj.sort(:groups_position => @group_option)
28
39
  xcodeproj.save
29
40
  puts "The `#{File.basename(xcodeproj_path)}` project was sorted"
30
41
  end
@@ -16,6 +16,7 @@ module Xcodeproj
16
16
  :frameworks => [],
17
17
  :weak_frameworks => [],
18
18
  :libraries => [],
19
+ :arg_files => [],
19
20
  :simple => [],
20
21
  :force_load => [],
21
22
  }
@@ -32,6 +33,8 @@ module Xcodeproj
32
33
  key = :weak_frameworks
33
34
  when '-l'
34
35
  key = :libraries
36
+ when '@'
37
+ key = :arg_files
35
38
  when '-force_load'
36
39
  key = :force_load
37
40
  else
@@ -58,6 +61,8 @@ module Xcodeproj
58
61
  flags.strip.shellsplit.flat_map do |string|
59
62
  if string =~ /\A-l.+/
60
63
  ['-l', string[2..-1]]
64
+ elsif string =~ /\A@.+/
65
+ ['@', string[1..-1]]
61
66
  else
62
67
  string
63
68
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'shellwords'
2
3
  require 'xcodeproj/config/other_linker_flags_parser'
3
4
 
@@ -58,7 +59,7 @@ module Xcodeproj
58
59
  @attributes = {}
59
60
  @includes = []
60
61
  @other_linker_flags = {}
61
- [:simple, :frameworks, :weak_frameworks, :libraries, :force_load].each do |key|
62
+ [:simple, :frameworks, :weak_frameworks, :libraries, :arg_files, :force_load].each do |key|
62
63
  @other_linker_flags[key] = Set.new
63
64
  end
64
65
  merge!(extract_hash(xcconfig_hash_or_file))
@@ -125,9 +126,10 @@ module Xcodeproj
125
126
  :frameworks => '-framework ',
126
127
  :weak_frameworks => '-weak_framework ',
127
128
  :libraries => '-l',
129
+ :arg_files => '@',
128
130
  :force_load => '-force_load',
129
131
  }
130
- [:libraries, :frameworks, :weak_frameworks, :force_load].each do |key|
132
+ [:libraries, :frameworks, :weak_frameworks, :arg_files, :force_load].each do |key|
131
133
  modifier = modifiers[key]
132
134
  sorted = other_linker_flags[key].to_a.sort
133
135
  if key == :force_load
@@ -180,6 +182,13 @@ module Xcodeproj
180
182
  other_linker_flags[:libraries]
181
183
  end
182
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
+
183
192
  public
184
193
 
185
194
  # @!group Merging
@@ -254,6 +263,7 @@ module Xcodeproj
254
263
  # @return [Hash]
255
264
  #
256
265
  def extract_hash(argument)
266
+ return argument if argument.is_a?(Hash)
257
267
  if argument.respond_to? :read
258
268
  @filepath = Pathname.new(argument.to_path)
259
269
  hash_from_file_content(argument.read)
@@ -4,19 +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 = '12.2'
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.14'
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 = '12.2'
15
+ LAST_KNOWN_TVOS_SDK = '14.0'
16
16
 
17
17
  # @return [String] The last known watchOS SDK (stable).
18
18
  #
19
- LAST_KNOWN_WATCHOS_SDK = '5.2'
19
+ LAST_KNOWN_WATCHOS_SDK = '7.0'
20
20
 
21
21
  # @return [String] The last known archive version to Xcodeproj.
22
22
  #
@@ -32,15 +32,15 @@ module Xcodeproj
32
32
 
33
33
  # @return [String] The last known object version to Xcodeproj.
34
34
  #
35
- LAST_KNOWN_OBJECT_VERSION = 52
35
+ LAST_KNOWN_OBJECT_VERSION = 55
36
36
 
37
- # @return [String] The last known object version to Xcodeproj.
37
+ # @return [String] The last known Xcode version to Xcodeproj.
38
38
  #
39
- LAST_UPGRADE_CHECK = '1100'
39
+ LAST_UPGRADE_CHECK = '1240'
40
40
 
41
- # @return [String] The last known object version to Xcodeproj.
41
+ # @return [String] The last known Xcode version to Xcodeproj.
42
42
  #
43
- LAST_SWIFT_UPGRADE_CHECK = '1100'
43
+ LAST_SWIFT_UPGRADE_CHECK = '1240'
44
44
 
45
45
  # @return [String] The version of `.xcscheme` files supported by Xcodeproj
46
46
  #
@@ -93,12 +93,14 @@ module Xcodeproj
93
93
  'app' => 'wrapper.application',
94
94
  'appex' => 'wrapper.app-extension',
95
95
  'bundle' => 'wrapper.plug-in',
96
+ 'cpp' => 'sourcecode.cpp.cpp',
96
97
  'dylib' => 'compiled.mach-o.dylib',
97
98
  'entitlements' => 'text.plist.entitlements',
98
99
  'framework' => 'wrapper.framework',
99
100
  'gif' => 'image.gif',
100
101
  'gpx' => 'text.xml',
101
102
  'h' => 'sourcecode.c.h',
103
+ 'hpp' => 'sourcecode.cpp.h',
102
104
  'm' => 'sourcecode.c.objc',
103
105
  'markdown' => 'text',
104
106
  'mdimporter' => 'wrapper.cfbundle',
@@ -126,6 +128,9 @@ module Xcodeproj
126
128
  # @return [Hash] The compatibility version string for different object versions.
127
129
  #
128
130
  COMPATIBILITY_VERSION_BY_OBJECT_VERSION = {
131
+ 55 => 'Xcode 13.0',
132
+ 54 => 'Xcode 12.0',
133
+ 53 => 'Xcode 11.4',
129
134
  52 => 'Xcode 11.0',
130
135
  51 => 'Xcode 10.0',
131
136
  50 => 'Xcode 9.3',
@@ -138,46 +143,48 @@ module Xcodeproj
138
143
  # @return [Hash] The uniform type identifier of various product types.
139
144
  #
140
145
  PRODUCT_TYPE_UTI = {
141
- :application => 'com.apple.product-type.application',
142
- :framework => 'com.apple.product-type.framework',
143
- :dynamic_library => 'com.apple.product-type.library.dynamic',
144
- :static_library => 'com.apple.product-type.library.static',
145
- :bundle => 'com.apple.product-type.bundle',
146
- :octest_bundle => 'com.apple.product-type.bundle',
147
- :unit_test_bundle => 'com.apple.product-type.bundle.unit-test',
148
- :ui_test_bundle => 'com.apple.product-type.bundle.ui-testing',
149
- :app_extension => 'com.apple.product-type.app-extension',
150
- :command_line_tool => 'com.apple.product-type.tool',
151
- :watch_app => 'com.apple.product-type.application.watchapp',
152
- :watch2_app => 'com.apple.product-type.application.watchapp2',
153
- :watch2_app_container => 'com.apple.product-type.application.watchapp2-container',
154
- :watch_extension => 'com.apple.product-type.watchkit-extension',
155
- :watch2_extension => 'com.apple.product-type.watchkit2-extension',
156
- :tv_extension => 'com.apple.product-type.tv-app-extension',
157
- :messages_application => 'com.apple.product-type.application.messages',
158
- :messages_extension => 'com.apple.product-type.app-extension.messages',
159
- :sticker_pack => 'com.apple.product-type.app-extension.messages-sticker-pack',
160
- :xpc_service => 'com.apple.product-type.xpc-service',
146
+ :application => 'com.apple.product-type.application',
147
+ :application_on_demand_install_capable => 'com.apple.product-type.application.on-demand-install-capable',
148
+ :framework => 'com.apple.product-type.framework',
149
+ :dynamic_library => 'com.apple.product-type.library.dynamic',
150
+ :static_library => 'com.apple.product-type.library.static',
151
+ :bundle => 'com.apple.product-type.bundle',
152
+ :octest_bundle => 'com.apple.product-type.bundle',
153
+ :unit_test_bundle => 'com.apple.product-type.bundle.unit-test',
154
+ :ui_test_bundle => 'com.apple.product-type.bundle.ui-testing',
155
+ :app_extension => 'com.apple.product-type.app-extension',
156
+ :command_line_tool => 'com.apple.product-type.tool',
157
+ :watch_app => 'com.apple.product-type.application.watchapp',
158
+ :watch2_app => 'com.apple.product-type.application.watchapp2',
159
+ :watch2_app_container => 'com.apple.product-type.application.watchapp2-container',
160
+ :watch_extension => 'com.apple.product-type.watchkit-extension',
161
+ :watch2_extension => 'com.apple.product-type.watchkit2-extension',
162
+ :tv_extension => 'com.apple.product-type.tv-app-extension',
163
+ :messages_application => 'com.apple.product-type.application.messages',
164
+ :messages_extension => 'com.apple.product-type.app-extension.messages',
165
+ :sticker_pack => 'com.apple.product-type.app-extension.messages-sticker-pack',
166
+ :xpc_service => 'com.apple.product-type.xpc-service',
161
167
  }.freeze
162
168
 
163
169
  # @return [Hash] The extensions or the various product UTIs.
164
170
  #
165
171
  PRODUCT_UTI_EXTENSIONS = {
166
- :application => 'app',
167
- :framework => 'framework',
168
- :dynamic_library => 'dylib',
169
- :static_library => 'a',
170
- :bundle => 'bundle',
171
- :octest_bundle => 'octest',
172
- :unit_test_bundle => 'xctest',
173
- :ui_test_bundle => 'xctest',
174
- :app_extension => 'appex',
175
- :messages_application => 'app',
176
- :messages_extension => 'appex',
177
- :sticker_pack => 'appex',
178
- :watch2_extension => 'appex',
179
- :watch2_app => 'app',
180
- :watch2_app_container => 'app',
172
+ :application => 'app',
173
+ :application_on_demand_install_capable => 'app',
174
+ :framework => 'framework',
175
+ :dynamic_library => 'dylib',
176
+ :static_library => 'a',
177
+ :bundle => 'bundle',
178
+ :octest_bundle => 'octest',
179
+ :unit_test_bundle => 'xctest',
180
+ :ui_test_bundle => 'xctest',
181
+ :app_extension => 'appex',
182
+ :messages_application => 'app',
183
+ :messages_extension => 'appex',
184
+ :sticker_pack => 'appex',
185
+ :watch2_extension => 'appex',
186
+ :watch2_app => 'app',
187
+ :watch2_app_container => 'app',
181
188
  }.freeze
182
189
 
183
190
  # @return [Hash] The common build settings grouped by platform, and build
@@ -198,11 +205,9 @@ module Xcodeproj
198
205
  }.freeze,
199
206
  [:ios] => {
200
207
  'SDKROOT' => 'iphoneos',
201
- 'CODE_SIGN_IDENTITY' => 'iPhone Developer',
202
208
  }.freeze,
203
209
  [:osx] => {
204
210
  'SDKROOT' => 'macosx',
205
- 'CODE_SIGN_IDENTITY' => '-',
206
211
  }.freeze,
207
212
  [:tvos] => {
208
213
  'SDKROOT' => 'appletvos',
@@ -251,7 +256,6 @@ module Xcodeproj
251
256
  [:debug, :static_library, :swift] => {
252
257
  }.freeze,
253
258
  [:framework] => {
254
- 'CODE_SIGN_IDENTITY' => '',
255
259
  'CURRENT_PROJECT_VERSION' => '1',
256
260
  'DEFINES_MODULE' => 'YES',
257
261
  'DYLIB_COMPATIBILITY_VERSION' => '1',
@@ -269,7 +273,6 @@ module Xcodeproj
269
273
  }.freeze,
270
274
  [:osx, :framework] => {
271
275
  'COMBINE_HIDPI_IMAGES' => 'YES',
272
- 'FRAMEWORK_VERSION' => 'A',
273
276
  'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) @executable_path/../Frameworks @loader_path/Frameworks',
274
277
  }.freeze,
275
278
  [:watchos, :framework] => {
@@ -311,6 +314,7 @@ module Xcodeproj
311
314
  }.freeze,
312
315
  [:application] => {
313
316
  'ASSETCATALOG_COMPILER_APPICON_NAME' => 'AppIcon',
317
+ 'ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME' => 'AccentColor',
314
318
  }.freeze,
315
319
  [:ios, :application] => {
316
320
  'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) @executable_path/Frameworks',
@@ -326,10 +330,12 @@ module Xcodeproj
326
330
  }.freeze,
327
331
  [:tvos, :application] => {
328
332
  'ASSETCATALOG_COMPILER_APPICON_NAME' => 'App Icon & Top Shelf Image',
329
- 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME' => 'LaunchImage',
330
333
  'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) @executable_path/Frameworks',
331
334
  'TARGETED_DEVICE_FAMILY' => '3',
332
335
  }.freeze,
336
+ [:tvos, :application, :swift] => {
337
+ 'ENABLE_PREVIEWS' => 'YES',
338
+ }.freeze,
333
339
  [:watchos, :application, :swift] => {
334
340
  'ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES' => 'YES',
335
341
  }.freeze,
@@ -375,6 +381,7 @@ module Xcodeproj
375
381
  'CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF' => 'YES',
376
382
  'CLANG_WARN_OBJC_LITERAL_CONVERSION' => 'YES',
377
383
  'CLANG_WARN_OBJC_ROOT_CLASS' => 'YES_ERROR',
384
+ 'CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER' => 'YES',
378
385
  'CLANG_WARN_RANGE_LOOP_ANALYSIS' => 'YES',
379
386
  'CLANG_WARN_STRICT_PROTOTYPES' => 'YES',
380
387
  'CLANG_WARN_SUSPICIOUS_MOVE' => 'YES',
@@ -447,5 +454,12 @@ module Xcodeproj
447
454
  $(inherited)
448
455
  ${inherited}
449
456
  ).freeze
457
+
458
+ # @return [Hash] Possible types for a scheme's 'ExecutionAction' node
459
+ #
460
+ EXECUTION_ACTION_TYPE = {
461
+ :shell_script => 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction',
462
+ :send_email => 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.SendEmailAction',
463
+ }.freeze
450
464
  end
451
465
  end
@@ -1,5 +1,5 @@
1
1
  module Xcodeproj
2
2
  # The version of the xcodeproj gem.
3
3
  #
4
- VERSION = '1.14.0'.freeze unless defined? Xcodeproj::VERSION
4
+ VERSION = '1.21.0'.freeze unless defined? Xcodeproj::VERSION
5
5
  end
@@ -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,16 +83,19 @@ 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)
95
+ setting = resolve_variable_substitution(key, setting, root_target, previous_key)
89
96
 
90
97
  config_setting = config[key]
91
- config_setting = resolve_variable_substitution(key, config_setting, root_target)
98
+ config_setting = resolve_variable_substitution(key, config_setting, root_target, previous_key)
92
99
 
93
100
  project_setting = project.build_configuration_list[name]
94
101
  project_setting = nil if equal?(project_setting)
@@ -99,6 +106,12 @@ module Xcodeproj
99
106
  'SRCROOT' => project.project_dir.to_s,
100
107
  }
101
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
+
102
115
  [defaults[key], project_setting, config_setting, setting, ENV[key]].compact.reduce(nil) do |inherited, value|
103
116
  expand_build_setting(value, inherited)
104
117
  end
@@ -142,7 +155,7 @@ module Xcodeproj
142
155
  build_setting_value.flat_map { |value| Constants::INHERITED_KEYWORDS.include?(value) ? inherited : value }
143
156
  end
144
157
 
145
- def resolve_variable_substitution(key, value, root_target)
158
+ def resolve_variable_substitution(key, value, root_target, previous_key = nil)
146
159
  case value
147
160
  when Array
148
161
  return value.map { |v| resolve_variable_substitution(key, v, root_target) }
@@ -168,9 +181,20 @@ module Xcodeproj
168
181
  when key
169
182
  # to prevent infinite recursion
170
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
171
188
  else
172
189
  configuration_to_resolve_against = root_target ? root_target.build_configuration_list[name] : self
173
- resolved_value_for_variable = configuration_to_resolve_against.resolve_build_setting(variable, root_target) || ''
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
+
174
198
  value = value.gsub(variable_reference, resolved_value_for_variable)
175
199
  resolve_variable_substitution(key, value, root_target)
176
200
  end
@@ -191,14 +215,15 @@ module Xcodeproj
191
215
 
192
216
  settings.keys.each do |key|
193
217
  next unless value = settings[key]
218
+ stripped_key = key.sub(/\[[^\]]+\]$/, '')
194
219
  case value
195
220
  when String
196
- next unless array_settings.include?(key)
221
+ next unless array_settings.include?(stripped_key)
197
222
  array_value = split_build_setting_array_to_string(value)
198
223
  next unless array_value.size > 1
199
224
  settings[key] = array_value
200
225
  when Array
201
- next if value.size > 1 && array_settings.include?(key)
226
+ next if value.size > 1 && array_settings.include?(stripped_key)
202
227
  settings[key] = value.join(' ')
203
228
  end
204
229
  end
@@ -39,6 +39,10 @@ module Xcodeproj
39
39
  #
40
40
  attribute :platform_filter, String
41
41
 
42
+ # @return [Array<String>] the platform filters for this build file.
43
+ #
44
+ attribute :platform_filters, Array
45
+
42
46
  #---------------------------------------------------------------------#
43
47
 
44
48
  public
@@ -49,7 +53,9 @@ module Xcodeproj
49
53
  # user.
50
54
  #
51
55
  def display_name
52
- if file_ref
56
+ if product_ref
57
+ product_ref.display_name
58
+ elsif file_ref
53
59
  file_ref.display_name
54
60
  else
55
61
  super
@@ -30,6 +30,16 @@ module Xcodeproj
30
30
  #
31
31
  attribute :run_only_for_deployment_postprocessing, String, '0'
32
32
 
33
+ # @return [String] whether or not this run script will be forced to
34
+ # run even on incremental builds. Can be either '1', or
35
+ # missing. By default this option is disabled in Xcode.
36
+ #
37
+ # @note This setting is exposed in Xcode in the UI of
38
+ # PBXShellScriptBuildPhase as `Based on
39
+ # dependency analysis` (selected by default).
40
+ #
41
+ attribute :always_out_of_date, String
42
+
33
43
  # @return [String] Comments associated with this build phase.
34
44
  #
35
45
  # @note This is apparently no longer used by Xcode.
@@ -135,6 +145,27 @@ module Xcodeproj
135
145
  def ascii_plist_annotation
136
146
  " #{display_name} "
137
147
  end
148
+
149
+ # Sorts the build files of the phase according to the display
150
+ # name or the path.
151
+ #
152
+ # @param [Hash] _options
153
+ # Not used.
154
+ #
155
+ # @return [void]
156
+ #
157
+ def sort(_options = nil)
158
+ files.sort! do |x, y|
159
+ result = File.basename(x.display_name.downcase, '.*') <=> File.basename(y.display_name.downcase, '.*')
160
+ if result.zero?
161
+ result = File.extname(x.display_name.downcase) <=> File.extname(y.display_name.downcase)
162
+ if result.zero? && x.file_ref.respond_to?(:full_path) && y.file_ref.respond_to?(:full_path)
163
+ result = x.file_ref.full_path.to_s.downcase <=> y.file_ref.full_path.to_s.downcase
164
+ end
165
+ end
166
+ result
167
+ end
168
+ end
138
169
  end
139
170
 
140
171
  #-----------------------------------------------------------------------#
@@ -226,24 +226,24 @@ module Xcodeproj
226
226
  # Creates a file reference to a static library and adds it to the
227
227
  # group.
228
228
  #
229
- # @param [#to_s] product_name
229
+ # @param [#to_s] product_basename
230
230
  # The name of the static library.
231
231
  #
232
232
  # @return [PBXFileReference] The new file reference.
233
233
  #
234
- def new_product_ref_for_target(target_name, product_type)
235
- FileReferencesFactory.new_product_ref_for_target(self, target_name, product_type)
234
+ def new_product_ref_for_target(product_basename, product_type)
235
+ FileReferencesFactory.new_product_ref_for_target(self, product_basename, product_type)
236
236
  end
237
237
 
238
238
  # Creates a file reference to a new bundle.
239
239
  #
240
- # @param [#to_s] product_name
240
+ # @param [#to_s] product_basename
241
241
  # The name of the bundle.
242
242
  #
243
243
  # @return [PBXFileReference] The new file reference.
244
244
  #
245
- def new_bundle(product_name)
246
- FileReferencesFactory.new_bundle(self, product_name)
245
+ def new_bundle(product_basename)
246
+ FileReferencesFactory.new_bundle(self, product_basename)
247
247
  end
248
248
 
249
249
  # Creates a file reference to a new bundle and adds it to the group.
@@ -440,10 +440,12 @@ module Xcodeproj
440
440
 
441
441
  result = File.basename(x.display_name.downcase, '.*') <=> File.basename(y.display_name.downcase, '.*')
442
442
  if result.zero?
443
- File.extname(x.display_name.downcase) <=> File.extname(y.display_name.downcase)
444
- else
445
- result
443
+ result = File.extname(x.display_name.downcase) <=> File.extname(y.display_name.downcase)
444
+ if result.zero?
445
+ result = x.path.downcase <=> y.path.downcase
446
+ end
446
447
  end
448
+ result
447
449
  end
448
450
  end
449
451
  end
@@ -42,17 +42,19 @@ module Xcodeproj
42
42
  # @param [PBXGroup] group
43
43
  # The group to which to add the reference.
44
44
  #
45
- # @param [#to_s] product_name
45
+ # @param [#to_s] product_basename
46
46
  # The name of the static library.
47
47
  #
48
48
  # @return [PBXFileReference] The new file reference.
49
49
  #
50
- def new_product_ref_for_target(group, target_name, product_type)
50
+ def new_product_ref_for_target(group, product_basename, product_type)
51
51
  if product_type == :static_library
52
52
  prefix = 'lib'
53
53
  end
54
54
  extension = Constants::PRODUCT_UTI_EXTENSIONS[product_type]
55
- ref = new_reference(group, "#{prefix}#{target_name}.#{extension}", :built_products)
55
+ path = "#{prefix}#{product_basename}"
56
+ path += ".#{extension}" if extension
57
+ ref = new_reference(group, path, :built_products)
56
58
  ref.include_in_index = '0'
57
59
  ref.set_explicit_file_type
58
60
  ref
@@ -64,13 +66,13 @@ module Xcodeproj
64
66
  # @param [PBXGroup] group
65
67
  # The group to which to add the reference.
66
68
  #
67
- # @param [#to_s] product_name
69
+ # @param [#to_s] product_basename
68
70
  # The name of the bundle.
69
71
  #
70
72
  # @return [PBXFileReference] The new file reference.
71
73
  #
72
- def new_bundle(group, product_name)
73
- ref = new_reference(group, "#{product_name}.bundle", :built_products)
74
+ def new_bundle(group, product_basename)
75
+ ref = new_reference(group, "#{product_basename}.bundle", :built_products)
74
76
  ref.include_in_index = '0'
75
77
  ref.set_explicit_file_type('wrapper.cfbundle')
76
78
  ref
@@ -148,7 +148,7 @@ module Xcodeproj
148
148
  when '<group>'
149
149
  object_parent = parent(object)
150
150
  if object_parent.isa == 'PBXProject'.freeze
151
- object.project.project_dir
151
+ object.project.project_dir + object.project.root_object.project_dir_path
152
152
  else
153
153
  real_path(object_parent)
154
154
  end
@@ -205,7 +205,7 @@ module Xcodeproj
205
205
  # @return [void]
206
206
  #
207
207
  def set_path_with_source_tree(object, path, source_tree)
208
- path = Pathname.new(path)
208
+ path = Pathname(path)
209
209
  source_tree = normalize_source_tree(source_tree)
210
210
  object.source_tree = source_tree
211
211