xcoder 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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