xcodeproj 1.17.1 → 1.21.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,17 @@ 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
- path = "#{prefix}#{target_name}"
55
+ path = "#{prefix}#{product_basename}"
56
56
  path += ".#{extension}" if extension
57
57
  ref = new_reference(group, path, :built_products)
58
58
  ref.include_in_index = '0'
@@ -66,13 +66,13 @@ module Xcodeproj
66
66
  # @param [PBXGroup] group
67
67
  # The group to which to add the reference.
68
68
  #
69
- # @param [#to_s] product_name
69
+ # @param [#to_s] product_basename
70
70
  # The name of the bundle.
71
71
  #
72
72
  # @return [PBXFileReference] The new file reference.
73
73
  #
74
- def new_bundle(group, product_name)
75
- 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)
76
76
  ref.include_in_index = '0'
77
77
  ref.set_explicit_file_type('wrapper.cfbundle')
78
78
  ref
@@ -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
 
@@ -552,6 +552,49 @@ module Xcodeproj
552
552
  end
553
553
  end
554
554
 
555
+ # Adds on demand resources to the resources build phase of the target.
556
+ #
557
+ # @param {String => [Array<PBXFileReference>]} on_demand_resource_tag_files
558
+ # the files references of the on demand resources to add to the target keyed by the tag.
559
+ #
560
+ # @return [void]
561
+ #
562
+ def add_on_demand_resources(on_demand_resource_tag_files)
563
+ on_demand_resource_tag_files.each do |tag, file_refs|
564
+ file_refs.each do |file_ref|
565
+ if resources_build_phase.include?(file_ref)
566
+ existing_build_file = resources_build_phase.build_file(file_ref)
567
+ existing_build_file.settings ||= {}
568
+ existing_build_file.settings['ASSET_TAGS'] ||= []
569
+ existing_build_file.settings['ASSET_TAGS'] << tag
570
+ existing_build_file.settings['ASSET_TAGS'].uniq!
571
+ next
572
+ end
573
+ build_file = resources_build_phase.add_file_reference(file_ref, true)
574
+ build_file.settings = (build_file.settings ||= {}).merge('ASSET_TAGS' => [tag])
575
+ end
576
+ end
577
+ end
578
+
579
+ # Remove on demand resources from the resources build phase of the target.
580
+ #
581
+ # @param {String => [Array<PBXFileReference>]} on_demand_resource_tag_files
582
+ # the files references of the on demand resources to add to the target keyed by the tag.
583
+ #
584
+ # @return [void]
585
+ #
586
+ def remove_on_demand_resources(on_demand_resource_tag_files)
587
+ on_demand_resource_tag_files.each do |tag, file_refs|
588
+ file_refs.each do |file_ref|
589
+ build_file = resources_build_phase.build_file(file_ref)
590
+ next if build_file.nil?
591
+ asset_tags = build_file.settings['ASSET_TAGS']
592
+ asset_tags.delete(tag)
593
+ resources_build_phase.remove_file_reference(file_ref) if asset_tags.empty?
594
+ end
595
+ end
596
+ end
597
+
555
598
  # Finds or creates the headers build phase of the target.
556
599
  #
557
600
  # @note A target should have only one headers build phase.
@@ -13,6 +13,16 @@ module Xcodeproj
13
13
  # @return [String] the product name of this Swift package.
14
14
  #
15
15
  attribute :product_name, String
16
+
17
+ # @!group AbstractObject Hooks
18
+ #--------------------------------------#
19
+
20
+ # @return [String] the name of the Swift package.
21
+ #
22
+ def display_name
23
+ return product_name if product_name
24
+ super
25
+ end
16
26
  end
17
27
  end
18
28
  end
@@ -13,6 +13,20 @@ module Xcodeproj
13
13
  # @return [Hash] the version requirements for this Swift package.
14
14
  #
15
15
  attribute :requirement, Hash
16
+
17
+ # @!group AbstractObject Hooks
18
+ #--------------------------------------#
19
+
20
+ def ascii_plist_annotation
21
+ " #{isa} \"#{File.basename(display_name)}\" "
22
+ end
23
+
24
+ # @return [String] the name of the Swift package repository.
25
+ #
26
+ def display_name
27
+ return repositoryURL if repositoryURL
28
+ super
29
+ end
16
30
  end
17
31
  end
18
32
  end
@@ -41,17 +41,17 @@ module Xcodeproj
41
41
  #
42
42
  # @return [PBXNativeTarget] the target.
43
43
  #
44
- def self.new_target(project, type, name, platform, deployment_target, product_group, language)
44
+ def self.new_target(project, type, name, platform, deployment_target, product_group, language, product_basename)
45
45
  # Target
46
46
  target = project.new(PBXNativeTarget)
47
47
  project.targets << target
48
48
  target.name = name
49
- target.product_name = name
49
+ target.product_name = product_basename
50
50
  target.product_type = Constants::PRODUCT_TYPE_UTI[type]
51
51
  target.build_configuration_list = configuration_list(project, platform, deployment_target, type, language)
52
52
 
53
53
  # Product
54
- product = product_group.new_product_ref_for_target(name, type)
54
+ product = product_group.new_product_ref_for_target(target.product_name, type)
55
55
  target.product_reference = product
56
56
 
57
57
  # Build phases
@@ -88,12 +88,12 @@ module Xcodeproj
88
88
  #
89
89
  # @return [PBXNativeTarget] the target.
90
90
  #
91
- def self.new_resources_bundle(project, name, platform, product_group)
91
+ def self.new_resources_bundle(project, name, platform, product_group, product_basename)
92
92
  # Target
93
93
  target = project.new(PBXNativeTarget)
94
94
  project.targets << target
95
95
  target.name = name
96
- target.product_name = name
96
+ target.product_name = product_basename
97
97
  target.product_type = Constants::PRODUCT_TYPE_UTI[:bundle]
98
98
 
99
99
  # Configuration List
@@ -111,7 +111,7 @@ module Xcodeproj
111
111
  target.build_configuration_list = cl
112
112
 
113
113
  # Product
114
- product = product_group.new_bundle(name)
114
+ product = product_group.new_bundle(target.product_name)
115
115
  target.product_reference = product
116
116
 
117
117
  # Build phases
@@ -9,8 +9,12 @@ require 'xcodeproj/scheme/archive_action'
9
9
 
10
10
  require 'xcodeproj/scheme/buildable_product_runnable'
11
11
  require 'xcodeproj/scheme/buildable_reference'
12
+ require 'xcodeproj/scheme/location_scenario_reference'
13
+ require 'xcodeproj/scheme/execution_action'
12
14
  require 'xcodeproj/scheme/macro_expansion'
13
15
  require 'xcodeproj/scheme/remote_runnable'
16
+ require 'xcodeproj/scheme/send_email_action_content'
17
+ require 'xcodeproj/scheme/shell_script_action_content'
14
18
 
15
19
  module Xcodeproj
16
20
  # This class represents a Scheme document represented by a ".xcscheme" file
@@ -221,7 +225,7 @@ module Xcodeproj
221
225
  launch_runnable = BuildableProductRunnable.new(build_target, 0)
222
226
  launch_action.buildable_product_runnable = launch_runnable
223
227
 
224
- profile_runnable = BuildableProductRunnable.new(build_target)
228
+ profile_runnable = BuildableProductRunnable.new(build_target, 0)
225
229
  profile_action.buildable_product_runnable = profile_runnable
226
230
 
227
231
  macro_exp = MacroExpansion.new(build_target)
@@ -23,6 +23,78 @@ module Xcodeproj
23
23
  def build_configuration=(config_name)
24
24
  @xml_element.attributes['buildConfiguration'] = config_name
25
25
  end
26
+
27
+ # @return [Array<ExecutionAction>]
28
+ # The list of actions to run before this scheme action.
29
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
30
+ #
31
+ def pre_actions
32
+ pre_actions = @xml_element.elements['PreActions']
33
+ return nil unless pre_actions
34
+ pre_actions.get_elements('ExecutionAction').map do |entry_node|
35
+ ExecutionAction.new(entry_node)
36
+ end
37
+ end
38
+
39
+ # @param [Array<ExecutionAction>] pre_actions
40
+ # Set the list of actions to run before this scheme action.
41
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
42
+ #
43
+ def pre_actions=(pre_actions)
44
+ @xml_element.delete_element('PreActions')
45
+ unless pre_actions.empty?
46
+ pre_actions_element = @xml_element.add_element('PreActions')
47
+ pre_actions.each do |entry_node|
48
+ pre_actions_element.add_element(entry_node.xml_element)
49
+ end
50
+ end
51
+ pre_actions
52
+ end
53
+
54
+ # @param [ExecutionAction] pre_action
55
+ # Add an action to the list of actions to run before this scheme action.
56
+ # It can be either a 'Run Script' or a 'Send Email' action.
57
+ #
58
+ def add_pre_action(pre_action)
59
+ pre_actions = @xml_element.elements['PreActions'] || @xml_element.add_element('PreActions')
60
+ pre_actions.add_element(pre_action.xml_element)
61
+ end
62
+
63
+ # @return [Array<ExecutionAction>]
64
+ # The list of actions to run after this scheme action.
65
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
66
+ #
67
+ def post_actions
68
+ post_actions = @xml_element.elements['PostActions']
69
+ return nil unless post_actions
70
+ post_actions.get_elements('ExecutionAction').map do |entry_node|
71
+ ExecutionAction.new(entry_node)
72
+ end
73
+ end
74
+
75
+ # @param [Array<ExecutionAction>] post_actions
76
+ # Set the list of actions to run after this scheme action.
77
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
78
+ #
79
+ def post_actions=(post_actions)
80
+ @xml_element.delete_element('PostActions')
81
+ unless post_actions.empty?
82
+ post_actions_element = @xml_element.add_element('PostActions')
83
+ post_actions.each do |entry_node|
84
+ post_actions_element.add_element(entry_node.xml_element)
85
+ end
86
+ end
87
+ post_actions
88
+ end
89
+
90
+ # @param [ExecutionAction] post_action
91
+ # Add an action to the list of actions to run after this scheme action.
92
+ # It can be either a 'Run Script' or a 'Send Email' action.
93
+ #
94
+ def add_post_action(post_action)
95
+ post_actions = @xml_element.elements['PostActions'] || @xml_element.add_element('PostActions')
96
+ post_actions.add_element(post_action.xml_element)
97
+ end
26
98
  end
27
99
  end
28
100
  end
@@ -19,6 +19,20 @@ module Xcodeproj
19
19
  end
20
20
  end
21
21
 
22
+ # @return [Bool]
23
+ # Whether or not to run post actions on build failure
24
+ #
25
+ def run_post_actions_on_failure?
26
+ string_to_bool(@xml_element.attributes['runPostActionsOnFailure'])
27
+ end
28
+
29
+ # @param [Bool] flag
30
+ # Set whether or not to run post actions on build failure
31
+ #
32
+ def run_post_actions_on_failure=(flag)
33
+ @xml_element.attributes['runPostActionsOnFailure'] = bool_to_string(flag)
34
+ end
35
+
22
36
  # @return [Bool]
23
37
  # Whether or not to build the various targets in parallel
24
38
  #
@@ -47,6 +61,78 @@ module Xcodeproj
47
61
  @xml_element.attributes['buildImplicitDependencies'] = bool_to_string(flag)
48
62
  end
49
63
 
64
+ # @return [Array<ExecutionAction>]
65
+ # The list of actions to run before this scheme action.
66
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
67
+ #
68
+ def pre_actions
69
+ pre_actions = @xml_element.elements['PreActions']
70
+ return nil unless pre_actions
71
+ pre_actions.get_elements('ExecutionAction').map do |entry_node|
72
+ ExecutionAction.new(entry_node)
73
+ end
74
+ end
75
+
76
+ # @param [Array<ExecutionAction>] pre_actions
77
+ # Set the list of actions to run before this scheme action.
78
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
79
+ #
80
+ def pre_actions=(pre_actions)
81
+ @xml_element.delete_element('PreActions')
82
+ unless pre_actions.empty?
83
+ pre_actions_element = @xml_element.add_element('PreActions')
84
+ pre_actions.each do |entry_node|
85
+ pre_actions_element.add_element(entry_node.xml_element)
86
+ end
87
+ end
88
+ pre_actions
89
+ end
90
+
91
+ # @param [ExecutionAction] pre_action
92
+ # Add an action to the list of actions to run before this scheme action.
93
+ # It can be either a 'Run Script' or a 'Send Email' action.
94
+ #
95
+ def add_pre_action(pre_action)
96
+ pre_actions = @xml_element.elements['PreActions'] || @xml_element.add_element('PreActions')
97
+ pre_actions.add_element(pre_action.xml_element)
98
+ end
99
+
100
+ # @return [Array<ExecutionAction>]
101
+ # The list of actions to run after this scheme action.
102
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
103
+ #
104
+ def post_actions
105
+ post_actions = @xml_element.elements['PostActions']
106
+ return nil unless post_actions
107
+ post_actions.get_elements('ExecutionAction').map do |entry_node|
108
+ ExecutionAction.new(entry_node)
109
+ end
110
+ end
111
+
112
+ # @param [Array<ExecutionAction>] post_actions
113
+ # Set the list of actions to run after this scheme action.
114
+ # Each entry can be either a 'Run Script' or a 'Send Email' action.
115
+ #
116
+ def post_actions=(post_actions)
117
+ @xml_element.delete_element('PostActions')
118
+ unless post_actions.empty?
119
+ post_actions_element = @xml_element.add_element('PostActions')
120
+ post_actions.each do |entry_node|
121
+ post_actions_element.add_element(entry_node.xml_element)
122
+ end
123
+ end
124
+ post_actions
125
+ end
126
+
127
+ # @param [ExecutionAction] post_action
128
+ # Add an action to the list of actions to run after this scheme action.
129
+ # It can be either a 'Run Script' or a 'Send Email' action.
130
+ #
131
+ def add_post_action(post_action)
132
+ post_actions = @xml_element.elements['PostActions'] || @xml_element.add_element('PostActions')
133
+ post_actions.add_element(post_action.xml_element)
134
+ end
135
+
50
136
  # @return [Array<BuildAction::Entry>]
51
137
  # The list of BuildActionEntry nodes associated with this Build Action.
52
138
  # Each entry represent a target to build and tells for which action it's needed to be built.
@@ -103,11 +189,11 @@ module Xcodeproj
103
189
  is_app_target = app_types.include?(target_or_node.product_type)
104
190
  end
105
191
 
106
- self.build_for_analyzing = true
107
192
  self.build_for_testing = is_test_target
108
193
  self.build_for_running = is_app_target
109
194
  self.build_for_profiling = is_app_target
110
195
  self.build_for_archiving = is_app_target
196
+ self.build_for_analyzing = true
111
197
 
112
198
  add_buildable_reference BuildableReference.new(target_or_node) if target_or_node
113
199
  end
@@ -0,0 +1,86 @@
1
+ module Xcodeproj
2
+ class XCScheme
3
+ # This class wraps the ExecutionAction node of a .xcscheme XML file
4
+ #
5
+ class ExecutionAction < XMLElementWrapper
6
+ # @param [REXML::Element] node
7
+ # The 'ExecutionAction' XML node that this object will wrap.
8
+ # If nil, will create an empty one
9
+ #
10
+ # @param [Symbol] action_type
11
+ # One of `EXECUTION_ACTION_TYPE.keys`
12
+ #
13
+ def initialize(node = nil, action_type = nil)
14
+ create_xml_element_with_fallback(node, 'ExecutionAction') do
15
+ type = action_type || node.action_type
16
+ raise "[Xcodeproj] Invalid ActionType `#{type}`" unless Constants::EXECUTION_ACTION_TYPE.keys.include?(type)
17
+ @xml_element.attributes['ActionType'] = Constants::EXECUTION_ACTION_TYPE[type]
18
+ end
19
+ end
20
+
21
+ # @return [String]
22
+ # The ActionType of this ExecutionAction. One of two values:
23
+ #
24
+ # Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction,
25
+ # Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.SendEmailAction
26
+ #
27
+ def action_type
28
+ @xml_element.attributes['ActionType']
29
+ end
30
+
31
+ # @return [ShellScriptActionContent]
32
+ # If action_type is 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction'
33
+ # returns the contents of the shell script to run pre/post action.
34
+ #
35
+ # @return [SendEmailActionContent]
36
+ # If action_type is 'Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.SendEmailAction'
37
+ # returns the contents of the email to send pre/post action.
38
+ #
39
+ def action_content
40
+ case action_type
41
+ when Constants::EXECUTION_ACTION_TYPE[:shell_script]
42
+ ShellScriptActionContent.new(@xml_element.elements['ActionContent'])
43
+ when Constants::EXECUTION_ACTION_TYPE[:send_email]
44
+ SendEmailActionContent.new(@xml_element.elements['ActionContent'])
45
+ else
46
+ raise "[Xcodeproj] Invalid ActionType `#{action_type}`"
47
+ end
48
+ end
49
+
50
+ # @param [ShellScriptActionContent, SendEmailActionContent] value
51
+ # Set either the contents of the shell script to run pre/post action
52
+ # or the contents of the email to send pre/post action.
53
+ #
54
+ def action_content=(value)
55
+ raise "[Xcodeproj] Invalid ActionContent `#{value.class}` for " \
56
+ "ActionType `#{action_type}`" unless valid_action_content?(value)
57
+
58
+ @xml_element.delete_element('ActionContent')
59
+ @xml_element.add_element(value.xml_element)
60
+ end
61
+
62
+ #-------------------------------------------------------------------------#
63
+
64
+ private
65
+
66
+ # @!group Private helpers
67
+
68
+ # @return [Bool]
69
+ # True if value (ActionContent) is valid for current action_type
70
+ #
71
+ # @param [ShellScriptActionContent, SendEmailActionContent] value
72
+ # Checks if value matches the expected action_type if present.
73
+ #
74
+ def valid_action_content?(value)
75
+ case action_type
76
+ when Constants::EXECUTION_ACTION_TYPE[:shell_script]
77
+ value.is_a?(ShellScriptActionContent)
78
+ when Constants::EXECUTION_ACTION_TYPE[:send_email]
79
+ value.is_a?(SendEmailActionContent)
80
+ else
81
+ false
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end