xcoder 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,8 +7,10 @@ require 'xcode/group'
7
7
  require 'xcode/resource'
8
8
  require 'xcode/scheme'
9
9
  require 'xcode/simple_identifier_generator'
10
+ require 'xcode/configuration_owner'
10
11
  require 'xcode/target'
11
12
  require 'xcode/variant_group'
13
+ require 'xcode/project_reference'
12
14
 
13
15
  module Xcode
14
16
 
@@ -59,15 +61,16 @@ module Xcode
59
61
  # @see Resource#initialize
60
62
  #
61
63
  # @param [String] isa the type of the object.
62
- # @return [Module] the module name mapped to the parameter. If the parameter
63
- # matches no module then a nil is returned.
64
+ # @return [Array<Module>] an array of modules that are mapped to the
65
+ # string name.
64
66
  #
65
67
  def self.isa_to_module isa
66
68
 
67
- { 'XCBuildConfiguration' => Configuration,
69
+ modules = { 'PBXProject' => [ProjectReference, ConfigurationOwner],
70
+ 'XCBuildConfiguration' => Configuration,
68
71
  'PBXFileReference' => FileReference,
69
72
  'PBXGroup' => Group,
70
- 'PBXNativeTarget' => Target,
73
+ 'PBXNativeTarget' => [Target, ConfigurationOwner],
71
74
  'PBXAggregateTarget' => Target,
72
75
  'PBXFrameworksBuildPhase' => BuildPhase,
73
76
  'PBXSourcesBuildPhase' => BuildPhase,
@@ -76,6 +79,8 @@ module Xcode
76
79
  'PBXVariantGroup' => VariantGroup,
77
80
  'XCConfigurationList' => ConfigurationList,
78
81
  'PBXVariantGroup' => VariantGroup }[isa]
82
+
83
+ Array(modules)
79
84
  end
80
85
 
81
86
  #
@@ -190,13 +190,15 @@ module Xcode
190
190
  end
191
191
 
192
192
  #
193
- # Based on the `isa` property find if there is a constant within
193
+ # Based on the `isa` property find if there are constants within
194
194
  # the Xcode module that matches and if it does, then we want to
195
- # automatically include module into the Resource object.
195
+ # automatically include those modules into the Resource object.
196
196
  #
197
- constant = Registry.isa_to_module(isa)
198
-
199
- self.extend(constant) if constant
197
+ constants = Registry.isa_to_module(isa)
198
+
199
+ constants.each do |constant|
200
+ self.extend(constant) if constant
201
+ end
200
202
 
201
203
  end
202
204
 
data/lib/xcode/target.rb CHANGED
@@ -52,70 +52,6 @@ module Xcode
52
52
  # @return [Project] the reference to the project for which these targets reside.
53
53
  attr_accessor :project
54
54
 
55
- #
56
- # @return [Array<BuildConfiguration>] the configurations that this target
57
- # supports. These are generally 'Debug' or 'Release' but may be custom
58
- # created configurations.
59
- #
60
- def configs
61
- build_configuration_list.build_configurations.map do |config|
62
- config.target = self
63
- config
64
- end
65
- end
66
-
67
- #
68
- # Return a specific build configuration.
69
- #
70
- # @note an exception is raised if no configuration matches the specified name.
71
- #
72
- #
73
- # @param [String] name of a configuration to return
74
- #
75
- # @return [BuildConfiguration] a specific build configuration that
76
- # matches the specified name.
77
- #
78
- def config(name)
79
- config = configs.select {|config| config.name == name.to_s }.first
80
- raise "No such config #{name}, available configs are #{configs.map {|c| c.name}.join(', ')}" if config.nil?
81
- yield config if block_given?
82
- config
83
- end
84
-
85
- #
86
- # Create a configuration for the target.
87
- #
88
- # @example debug configuration
89
- #
90
- # target.create_config 'Debug' do |config|
91
- # # configuration the new debug config.
92
- # end
93
- #
94
- # @param [String] name of the configuration to create
95
- # @return [BuildConfiguration] that is created
96
- #
97
- def create_configuration(name)
98
- # To create a configuration, we need to create or retrieve the configuration list
99
-
100
- created_config = build_configuration_list.create_config(name) do |config|
101
- yield config if block_given?
102
- end
103
-
104
- created_config
105
- end
106
-
107
- def create_configurations(*configuration_names)
108
-
109
- configuration_names.compact.flatten.map do |config_name|
110
- created_config = create_configuration config_name do |config|
111
- yield config if block_given?
112
- end
113
-
114
- created_config.save!
115
- end
116
-
117
- end
118
-
119
55
  #
120
56
  # @return [BuildPhase] the framework specific build phase of the target.
121
57
  #
@@ -11,7 +11,7 @@ module Xcode
11
11
 
12
12
  class OCUnitReportParser
13
13
 
14
- attr_reader :reports, :end_time, :start_time
14
+ attr_reader :reports, :end_time, :start_timel
15
15
  attr_accessor :debug, :formatters
16
16
 
17
17
  def initialize
@@ -22,13 +22,18 @@ module Xcode
22
22
  @failed = false
23
23
  @start_time = nil
24
24
  @end_time = nil
25
+ @unexpected = false
25
26
 
26
27
  add_formatter :junit, 'test-reports'
27
28
  add_formatter :stdout
28
29
  end
29
30
 
31
+ def unexpected?
32
+ @unexpected
33
+ end
34
+
30
35
  def failed?
31
- @failed
36
+ @failed or @unexpected
32
37
  end
33
38
 
34
39
  def finished?
@@ -36,6 +41,7 @@ module Xcode
36
41
  end
37
42
 
38
43
  def duration
44
+ return 0 if @start_time.nil?
39
45
  return Time.now - @start_time if @end_time.nil?
40
46
  @end_time - @start_time
41
47
  end
@@ -118,6 +124,9 @@ module Xcode
118
124
  when /BUILD FAILED/
119
125
  flush
120
126
 
127
+ when /Segmentation fault/
128
+ @unexpected=true
129
+
121
130
  when /Run test case (\w+)/
122
131
  # ignore
123
132
  when /Run test suite (\w+)/
data/lib/xcode/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Xcode
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
@@ -0,0 +1,218 @@
1
+ require 'xcoder'
2
+ require 'rake'
3
+ require 'rake/tasklib'
4
+
5
+
6
+ module Xcode
7
+ class RakeTask < ::Rake::TaskLib
8
+ include ::Rake::DSL if defined?(::Rake::DSL)
9
+
10
+ # The name of the prefixed namespace. By default this will by 'xcode'
11
+ attr_accessor :name
12
+
13
+ #
14
+ # @param [String,Array<String>] project_names names of the project and projects
15
+ # that are found in the specified directory.
16
+ #
17
+ def projects=(project_names)
18
+ @projects = Xcode.find_projects(directory).find_all{|project| Array(project_names).include? project.name }
19
+ end
20
+
21
+ #
22
+ # @return [Array<Projects>] all the projects found that match the filtering
23
+ # criteria at the specified directory or all projects at the specified
24
+ # directory.
25
+ #
26
+ def projects
27
+ @projects ||= Xcode.find_projects(directory)
28
+ end
29
+
30
+ #
31
+ # @param [String] value file path to search for Xcode projects. Xcoder attempts
32
+ # to find all the projects recursively from this specified path.
33
+ #
34
+ def directory=(value)
35
+ @directory = File.expand_path(value)
36
+ end
37
+
38
+ #
39
+ # The default directory is the current working directory. This can be
40
+ # overriden to search for projects within a specified folder path.
41
+ #
42
+ def directory
43
+ @directory ||= File.expand_path('.')
44
+ end
45
+
46
+ #
47
+ # @todo this should likely be generated from the Xcode::Builder object/class
48
+ # itself
49
+ #
50
+ # @return [Array] available actions of a Builder
51
+ def builder_actions
52
+ [ :build, :test, :clean, :package ]
53
+ end
54
+
55
+ #
56
+ # By default this will generate rake tasks within the 'xcode' namespace for
57
+ # all the projects (within the current working directory), all their targets,
58
+ # and all their configs. This will also generate tasks for all of a projects
59
+ # schemes as well.
60
+ #
61
+ # @example
62
+ #
63
+ # rake xcode:hackbook:hackbook:debug:build
64
+ # rake xcode:hackbook:hackbook:debug:clean
65
+ # rake xcode:hackbook:hackbook:debug:package
66
+ # rake xcode:hackbook:hackbook:debug:test
67
+ # rake xcode:hackbook:hackbook:release:build
68
+ # rake xcode:hackbook:hackbook:release:clean
69
+ # rake xcode:hackbook:hackbook:release:package
70
+ # rake xcode:hackbook:hackbook:release:test
71
+ #
72
+ # The task accepts a single parameter. This parameter allows you to change
73
+ # the root namespace that the tasks are generated within.
74
+ #
75
+ # @example
76
+ #
77
+ # Xcode::RakeTask.new :apple
78
+ #
79
+ # rake apple:hackbook:hackbook:debug:build
80
+ # # ...
81
+ #
82
+ # Additionally a block can be specified to provide additional configuration:
83
+ #
84
+ # @example specifying a directory parameter to search within a different folder
85
+ #
86
+ # Xcode::RakeTask.new :apple do |xcoder|
87
+ # xcoder.directory = "~/dayjobprojects"
88
+ # end
89
+ #
90
+ # rake apple:dayjobproject1:moneytarget:debug:build
91
+ # # ...
92
+ #
93
+ # Often you do not want to generate rake tasks for all the projects. So you
94
+ # can specify the names of the projects you do want to have appear.
95
+ #
96
+ # @example specifying projects to filter on by the name of a project
97
+ #
98
+ # Xcode::RakeTask.new :apple do |xcoder|
99
+ # xcoder.directory = "~/dayjobprojects"
100
+ # xcoder.projects = "Dayjobproject2"
101
+ # end
102
+ #
103
+ # rake apple:dayjobproject2:socialtarget:debug:build
104
+ # # ...
105
+ #
106
+ #
107
+ def initialize(name = :xcode)
108
+
109
+ @name = name
110
+
111
+ yield self if block_given?
112
+
113
+ define_all_projects_list_task
114
+ define_project_list_tasks
115
+ define_per_project_scheme_builder_tasks
116
+ define_per_project_config_builder_tasks
117
+
118
+ end
119
+
120
+ private
121
+
122
+ def define_all_projects_list_task
123
+ desc "List details for all the projects"
124
+ task "#{name}:list" do
125
+ projects.each {|project| project.describe }
126
+ end
127
+ end
128
+
129
+ def define_project_list_tasks
130
+ projects.each do |project|
131
+ desc "List details for all the projects"
132
+ task "#{name}:#{friendlyname(project.name)}:list" do
133
+ project.describe
134
+ end
135
+ end
136
+ end
137
+
138
+ #
139
+ # Generate all the Builder Tasks for all the matrix of all the Projects and
140
+ # Schemes
141
+ #
142
+ def define_per_project_scheme_builder_tasks
143
+
144
+ projects.each do |project|
145
+ project.schemes.each do |scheme|
146
+ builder_actions.each do |action|
147
+
148
+ description = "#{action.capitalize} #{project.name} #{scheme.name}"
149
+ task_name = friendlyname("#{name}:#{project.name}:scheme:#{scheme.name}:#{action}")
150
+
151
+ define_task_with description, task_name do
152
+ scheme.builder.send(action)
153
+ end
154
+
155
+ end
156
+ end
157
+ end
158
+
159
+ end
160
+
161
+ #
162
+ # Generate all the Builder Tasks for all the matrix of all the Projects,
163
+ # Targets, and Configs
164
+ #
165
+ def define_per_project_config_builder_tasks
166
+
167
+ projects.each do |project|
168
+ project.targets.each do |target|
169
+ target.configs.each do |config|
170
+
171
+ builder_actions.each do |action|
172
+
173
+ description = "#{action.capitalize} #{project.name} #{target.name} #{config.name}"
174
+ task_name = friendlyname("#{name}:#{project.name}:#{target.name}:#{config.name}:#{action}")
175
+
176
+ define_task_with description, task_name do
177
+ config.builder.send(action)
178
+ end
179
+
180
+ end
181
+
182
+ end
183
+ end
184
+ end
185
+
186
+
187
+ end
188
+
189
+
190
+ #
191
+ # @param [String] description the task decription
192
+ # @param [String] task_name the name of the task with namespace
193
+ #
194
+ def define_task_with(description,task_name,&block)
195
+
196
+ desc description
197
+ task task_name do
198
+ block.call
199
+ end
200
+
201
+ end
202
+
203
+
204
+ #
205
+ # @param [String,Symbol] name to convert that may contain camel-casing and
206
+ # spacing.
207
+ #
208
+ # @return [String] a name which is all lower-cased, spaces are replaced with
209
+ # underscores.
210
+ #
211
+ def friendlyname(name)
212
+ name.underscore.gsub(/\s/,'-')
213
+ end
214
+
215
+
216
+ end
217
+
218
+ end
@@ -56,35 +56,50 @@ describe Xcode::Configuration do
56
56
 
57
57
  it "should override existing settings" do
58
58
  linker_flags = settings['OTHER_LDFLAGS']
59
- subject.set 'OTHER_LDFLAGS', '-NONE'
59
+ subject.set 'OTHER_LDFLAGS', '-NONE -FOR -ME'
60
60
  settings['OTHER_LDFLAGS'].should_not == linker_flags
61
61
  end
62
+
63
+ end
64
+
65
+ describe "#append" do
66
+
67
+ let(:settings) { subject.build_settings }
62
68
 
69
+ it "should append to existing settings" do
70
+ subject.set 'OTHER_LDFLAGS', '-NONE'
71
+ subject.append 'OTHER_LDFLAGS', '-FOR -ME'
72
+ settings['OTHER_LDFLAGS'].should == "-NONE -FOR -ME"
73
+ end
74
+
63
75
  end
64
76
 
65
77
  describe "#get" do
66
78
 
67
79
  let(:settings) { subject.build_settings }
68
80
 
69
- it "should return the correct configuration value" do
70
- subject.get('OTHER_LDFLAGS').should == settings['OTHER_LDFLAGS']
81
+ it "should return the configuration value processed through their property" do
82
+
83
+ subject.get('OTHER_LDFLAGS').should_not == settings['OTHER_LDFLAGS']
84
+ subject.get('OTHER_LDFLAGS').should == settings['OTHER_LDFLAGS'].split(" ")
85
+
71
86
  end
72
87
 
73
88
  end
74
89
 
75
- describe "String Properties" do
76
-
77
- let(:string_properties) do
78
- [ :product_name,
79
- :prefix_header,
80
- :info_plist_location,
81
- :wrapper_extension,
82
- :sdkroot,
83
- :c_language_standard,
84
- :gcc_version,
85
- :code_sign_identity,
86
- :iphoneos_deployment_target ]
90
+ let(:string_properties) do
91
+ [ :product_name,
92
+ :prefix_header,
93
+ :info_plist_location,
94
+ :wrapper_extension,
95
+ :sdkroot,
96
+ :c_language_standard,
97
+ :gcc_version,
98
+ :code_sign_identity,
99
+ :iphoneos_deployment_target ]
87
100
  end
101
+
102
+ describe "String Properties" do
88
103
 
89
104
  it "should be able to correctly get the property" do
90
105
 
@@ -103,19 +118,29 @@ describe Xcode::Configuration do
103
118
 
104
119
  end
105
120
 
121
+ it "should be able to append to the property" do
122
+
123
+ string_properties.each do |property|
124
+ subject.send("#{property}=","new value")
125
+ subject.send("append_to_#{property}"," there")
126
+ subject.send(property).should eq("new value there"), "#{property} failed to be set correctly"
127
+ end
128
+
129
+ end
130
+
131
+ end
132
+
133
+ let(:boolean_properties) do
134
+ [ :precompile_prefix_headers,
135
+ :always_search_user_paths,
136
+ :warn_about_missing_prototypes,
137
+ :warn_about_return_type,
138
+ :validate_product,
139
+ :copy_phase_strip ]
106
140
  end
107
141
 
108
142
  describe "Boolean Properties" do
109
143
 
110
- let(:boolean_properties) do
111
- [ :precompile_prefix_headers,
112
- :always_search_user_paths,
113
- :warn_about_missing_prototypes,
114
- :warn_about_return_type,
115
- :validate_product,
116
- :copy_phase_strip ]
117
- end
118
-
119
144
  it "should be able to set to false with NO" do
120
145
 
121
146
  boolean_properties.each do |property|
@@ -151,16 +176,16 @@ describe Xcode::Configuration do
151
176
  end
152
177
 
153
178
  end
154
-
179
+ end
180
+
181
+ let(:space_delimited_string_properties) do
182
+ [ :architectures,
183
+ :supported_platforms,
184
+ :other_linker_flags ]
155
185
  end
156
186
 
157
187
  describe "Space Delimited String Properties" do
158
188
 
159
- let(:space_delimited_string_properties) do
160
- [ :architectures,
161
- :supported_platforms ]
162
- end
163
-
164
189
  it "should be able to correctly get the property" do
165
190
 
166
191
  space_delimited_string_properties.each do |property|
@@ -187,16 +212,41 @@ describe Xcode::Configuration do
187
212
 
188
213
  end
189
214
 
215
+ it "should be able to append to the property" do
216
+
217
+ space_delimited_string_properties.each do |property|
218
+ subject.send("#{property}=",["more", "value"])
219
+ subject.send("append_to_#{property}","there")
220
+ subject.send(property).should eq([ "more", "value", "there" ]), "#{property} failed to be appended correctly"
221
+ end
222
+
223
+ end
224
+
225
+ it "should not allow duplcate values" do
226
+
227
+ space_delimited_string_properties.each do |property|
228
+ subject.send("#{property}=",["more", "value"])
229
+ subject.send("append_to_#{property}","value")
230
+ subject.send(property).should eq([ "more", "value" ]), "#{property} failed to be appended correctly"
231
+ end
232
+
233
+ end
234
+
190
235
  end
191
236
 
237
+ let(:targeted_device_family_properties) { [ :targeted_device_family ] }
238
+
192
239
  describe "Targeted Device Family Properties" do
193
240
 
194
- let(:targeted_device_family_properties) { [ :targeted_device_family ] }
241
+ let(:expect_device_family_for_config) { [] }
195
242
 
196
- it "should be able to correctly get the property" do
243
+ let(:expect_device_family_for_global_config) { [ :iphone, :ipad ] }
244
+
245
+ it "should get the project's default property when it is not specified for the target configuration" do
197
246
 
198
247
  targeted_device_family_properties.each do |property|
199
- subject.send(property).should == [ ]
248
+
249
+ subject.send(property).should == expect_device_family_for_global_config
200
250
  end
201
251
 
202
252
  end
@@ -205,12 +255,80 @@ describe Xcode::Configuration do
205
255
 
206
256
  targeted_device_family_properties.each do |property|
207
257
  subject.send("#{property}=",[ 'IPHONE', :ipad ])
208
- subject.get("TARGETED_DEVICE_FAMILY").should == "1,2"
258
+ subject.build_settings["TARGETED_DEVICE_FAMILY"].should == "1,2"
209
259
  subject.send(property).should == [ :iphone, :ipad ]
210
260
  end
211
261
 
212
262
  end
213
263
 
264
+ it "should be able to append to the property" do
265
+
266
+ targeted_device_family_properties.each do |property|
267
+ subject.send("#{property}=",'IPHONE')
268
+ subject.send("append_to_#{property}","iPad")
269
+ subject.send(property).should == [ :iphone, :ipad ]
270
+ end
271
+
272
+ end
273
+
274
+ end
275
+
276
+ let(:key_value_array_properties) do
277
+ [ :other_c_flags ]
278
+ end
279
+
280
+ describe "Array Properties" do
281
+ it "should be able to correctly get the property" do
282
+ key_value_array_properties.each do |property|
283
+ subject.send(property).should be_kind_of(Array), "#{property} failed to return an Array"
284
+ end
285
+ end
286
+
287
+ it "should be able to correctly set the property" do
288
+ key_value_array_properties.each do |property|
289
+ subject.send("#{property}=","PARAMETER=1")
290
+ subject.send(property).should eq(["PARAMETER=1"]), "The property #{property} failed to set correctly"
291
+ end
292
+ end
293
+
294
+ it "should be able to correctly append the property" do
295
+ key_value_array_properties.each do |property|
296
+ subject.send("#{property}=","PARAMETER=1")
297
+ subject.send("append_to_#{property}",[ "PARAMETER=4", "PARAMETER2=2"])
298
+ subject.send(property).should eq([ "PARAMETER=4","PARAMETER2=2" ]), "The property #{property} failed to set correctly"
299
+ end
300
+ end
301
+ end
302
+
303
+
304
+ let(:all_properties) do
305
+ string_properties +
306
+ boolean_properties +
307
+ space_delimited_string_properties +
308
+ targeted_device_family_properties +
309
+ key_value_array_properties
310
+ end
311
+
312
+ describe "Property Environment Names" do
313
+ it "should have all property environment names available" do
314
+ all_properties.each do |property|
315
+ subject.send("env_#{property}").should_not be_nil, "The property #{property} does not have an env_#{property} method defined"
316
+ end
317
+ end
318
+ end
319
+
320
+ describe "Raw Getter and Setter" do
321
+ it "should have a raw getter method" do
322
+ all_properties.each do |property|
323
+ subject.should respond_to("raw_#{property}"), "The property #{property} does not have a raw_#{property} getter method defined"
324
+ end
325
+ end
326
+
327
+ it "should have a raw setter method" do
328
+ all_properties.each do |property|
329
+ subject.should respond_to("raw_#{property}="), "The property #{property} does not have a raw_#{property} setter method defined"
330
+ end
331
+ end
214
332
  end
215
333
 
216
334
  end
data/spec/project_spec.rb CHANGED
@@ -158,4 +158,18 @@ describe Xcode::Project do
158
158
  end
159
159
  end
160
160
 
161
+ describe "#global_configs" do
162
+ it "should return all the configurations global for the project" do
163
+ project.global_configs
164
+ end
165
+ end
166
+
167
+ describe "#global_config" do
168
+ it "should return the global configuration with the specified name" do
169
+ project.global_config('Debug')
170
+ end
171
+
172
+
173
+ end
174
+
161
175
  end