basechip 0.0.1

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.
Files changed (61) hide show
  1. data/.document +5 -0
  2. data/Gemfile +20 -0
  3. data/Gemfile.lock +32 -0
  4. data/LICENSE.txt +14 -0
  5. data/README.rdoc +19 -0
  6. data/VERSION +1 -0
  7. data/bin/basechip +25 -0
  8. data/collateral/block/block.rb.erb +20 -0
  9. data/collateral/configuration/configuration.rb.erb +19 -0
  10. data/collateral/project/Gemfile +19 -0
  11. data/collateral/project/gitignore +6 -0
  12. data/collateral/project/project.rb.erb +76 -0
  13. data/collateral/project/settings.rb.erb +26 -0
  14. data/collateral/recipes/icarus.rb +73 -0
  15. data/collateral/recipes/icarus.rb.erb +88 -0
  16. data/collateral/recipes/local_cluster.rb +27 -0
  17. data/lib/array.rb +26 -0
  18. data/lib/base_chip/action.rb +309 -0
  19. data/lib/base_chip/base.rb +105 -0
  20. data/lib/base_chip/block.rb +75 -0
  21. data/lib/base_chip/bom.rb +75 -0
  22. data/lib/base_chip/bom_file.rb +45 -0
  23. data/lib/base_chip/cli.rb +371 -0
  24. data/lib/base_chip/cluster.rb +93 -0
  25. data/lib/base_chip/cluster_type.rb +45 -0
  26. data/lib/base_chip/code_area.rb +30 -0
  27. data/lib/base_chip/configuration.rb +257 -0
  28. data/lib/base_chip/dsl.rb +593 -0
  29. data/lib/base_chip/exit_error.rb +20 -0
  30. data/lib/base_chip/generator_menu.rb +64 -0
  31. data/lib/base_chip/git.rb +32 -0
  32. data/lib/base_chip/hierarchy.rb +84 -0
  33. data/lib/base_chip/install_menu.rb +89 -0
  34. data/lib/base_chip/ipc.rb +50 -0
  35. data/lib/base_chip/list_menu.rb +134 -0
  36. data/lib/base_chip/menu.rb +70 -0
  37. data/lib/base_chip/out_file.rb +68 -0
  38. data/lib/base_chip/permutation.rb +26 -0
  39. data/lib/base_chip/permute.rb +25 -0
  40. data/lib/base_chip/post.rb +26 -0
  41. data/lib/base_chip/problem.rb +33 -0
  42. data/lib/base_chip/project.rb +472 -0
  43. data/lib/base_chip/requirement.rb +26 -0
  44. data/lib/base_chip/runable.rb +36 -0
  45. data/lib/base_chip/source_language.rb +40 -0
  46. data/lib/base_chip/source_type.rb +24 -0
  47. data/lib/base_chip/statistic.rb +27 -0
  48. data/lib/base_chip/task.rb +21 -0
  49. data/lib/base_chip/task_master.rb +50 -0
  50. data/lib/base_chip/taskable.rb +77 -0
  51. data/lib/base_chip/tasker.rb +260 -0
  52. data/lib/base_chip/test.rb +202 -0
  53. data/lib/base_chip/test_list.rb +120 -0
  54. data/lib/base_chip/tool.rb +51 -0
  55. data/lib/base_chip/tool_version.rb +34 -0
  56. data/lib/base_chip/top_menu.rb +203 -0
  57. data/lib/base_chip/track_state.rb +61 -0
  58. data/lib/base_chip.rb +215 -0
  59. data/lib/dir.rb +30 -0
  60. data/lib/reporting.rb +97 -0
  61. metadata +215 -0
@@ -0,0 +1,472 @@
1
+ # Copyright 2011 Tommy Poulter
2
+ #
3
+ # This file is part of basechip.
4
+ #
5
+ # basechip is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 3 as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # basechip is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with basechip. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'base_chip/block'
18
+ require 'base_chip/cluster_type'
19
+
20
+ module BaseChip
21
+ class Project
22
+ include TaskMaster
23
+ include Dsl
24
+ include Base
25
+ include Hierarchy
26
+
27
+ # Sets/gets the shared directory for this project, which is a place to
28
+ # install tools and IP shared between workareas (usually because of size).
29
+ # Expects a full path
30
+ define_setting :shared_directory , [ String ]
31
+
32
+ # Sets/gets the order of preference for clusters. If the user specifies
33
+ # "-j 500" on the command line, it will be spread across multiple clusters
34
+ # according to their default submission setting. This setting sets the
35
+ # order to fill those clusters.
36
+ # Expects an array of cluster names
37
+ # @example use local cluster types first, then lsf cluster types
38
+ # cluster_order %w{ local lsf }
39
+ # @example use local cluster types first, then lsf medium cluster, then lsf low cluster
40
+ # cluster_order %w{ local lsf:medium lsf:low }
41
+ define_setting :cluster_order , [ Array ]
42
+ define_child :block , Block
43
+ define_child :subproject , Project
44
+ define_child :cluster_type , ClusterType
45
+
46
+ attr_accessor :workload
47
+
48
+ def initialize()
49
+ super
50
+ @project = self
51
+ @pwd = Dir.pwd
52
+ end
53
+ # def configure_blocks(block_names)
54
+ # block_names.each do |name|
55
+ # self.blocks[name.to_sym].configure
56
+ # end
57
+ # end
58
+ def figure_directory_prefix
59
+ # if @directory == @pwd
60
+ # return nil
61
+ # elsif @pwd.length > @directory.length
62
+ configure
63
+ if @blocks
64
+ @blocks.each do |bname,block|
65
+ block.configure
66
+ if @pwd =~ /^#{block.directory}\b/
67
+ block.configurations.each do |cname,configuration|
68
+ configuration.configure
69
+ return "#{bname}:#{cname}" if @pwd =~ /^#{configuration.directory}\b/
70
+ end
71
+ return bname.to_s
72
+ end
73
+ end
74
+ end
75
+ # end
76
+ nil
77
+ # fault "'base_chip' should be run from a block's work directory or the top level of the project."
78
+ end
79
+ def block_names
80
+ return @block_names if @block_names
81
+ # \@block_names = Dir.glob("#\{@directory}/*")
82
+ # \@block_names.map!{|path| path.split(/\//).pop}
83
+ # \@block_names.delete 'settings.yaml'
84
+ # \@block_names
85
+ end
86
+ DEFINED_SUBCOMMANDS = %W{all gate}
87
+ def ready(targets=nil) #,available_only=false)
88
+ configure
89
+ @orig_targets = targets
90
+ if @directory_prefix
91
+ # no map! here because @orig_targets needs to stay true to the original command
92
+ targets = targets.map { |t| "#{@directory_prefix}:#{t}" }
93
+ end
94
+ @workload = dereference_workload targets
95
+ @workload.delete_if {|w|w.nil?}
96
+ if @workload.empty?
97
+ if diffgate(targets)
98
+ puts "diffgate returned no targets needing to run"
99
+ exit
100
+ else
101
+ fault "Could not determine anything to run based on the targets #{targets}. Did you mean to run this from another directory?"
102
+ end
103
+ end
104
+
105
+ w_names = @workload.map{|w|w.name}
106
+ @workload.each do |w|
107
+ w.configure
108
+ if w.depends
109
+ w.deep_depends.each do |d|
110
+ if @workload.include? d
111
+ w.wait_count += 1
112
+ d.next_tasks << w
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ def diffgate(targets)
119
+ targets.each do |t|
120
+ return false unless t =~ /\bdiffgate$/
121
+ end
122
+ true
123
+ end
124
+ def run_all_readied
125
+ # @report_hash = {}
126
+ FileUtils.mkdir_p "#{@directory}/reports"
127
+ @report_name = "#{@directory}/reports/workload.#{BaseChip.random_string}"
128
+ @report_file = File.new(@report_name,'w')
129
+ if @tasker.clusters
130
+ @tasker.ready
131
+ else
132
+ @foreground = @workload.size == 1
133
+ end
134
+ begin
135
+ @tasker.submit_workload_chain workload_chain
136
+ @tasker.run
137
+ rescue Interrupt
138
+ @tasker.finish
139
+ end
140
+ end
141
+ def workload_chain
142
+ @workload.each do |w|
143
+ w.task = t = Task.new
144
+ t.task_name = w.full_name
145
+ t.foreground = @foreground
146
+ t.worker_command = if @tasker.clusters
147
+ lambda { |client_id|
148
+ # The "@drb_uri ||=" is necessary because Drb.uri can change for some reason, and a command compare happens later
149
+ "#{$0} #{@orig_targets.join(' ')} --client-of #{@drb_uri ||= DRb.uri} --client-id #{client_id} --work-dir #{@pwd} #{
150
+ '--modes ' + BaseChip.options.modes if BaseChip.options.modes } #{
151
+ (['--' ] + BaseChip.options. append_arguments).join(' ') if BaseChip.options. append_arguments } #{
152
+ (['---'] + BaseChip.options.replace_arguments).join(' ') if BaseChip.options.replace_arguments }" }
153
+ else
154
+ nil
155
+ end
156
+ end
157
+ @workload.map do |w|
158
+ t = w.task
159
+ t.next_tasks = w.next_tasks.map { |nt| nt.task }
160
+ t.wait_count = w.wait_count
161
+ w.next_tasks.uniq!
162
+ t
163
+ end
164
+ end
165
+
166
+ def block_dereference(name,names,passive)
167
+ if block = @blocks[name.to_sym]
168
+ block.configure
169
+ block.dereference_workload(names,passive)
170
+ else
171
+ fault "Could not find block #{name} in project #{@name}" # FIXME say who wanted it, and if shortcut occurred
172
+ end
173
+ end
174
+ def dereference_workload(targets)
175
+ configure
176
+ fault "project '#{name}' has no blocks defined" unless @blocks
177
+ targets ||= ['all']
178
+ out = []
179
+
180
+ workload_hash = Hash.new
181
+
182
+ targets.each do |t|
183
+ case t
184
+ when 'gate', 'diffgate', 'all'
185
+ self.block_names.each do |b|
186
+ out += block_dereference(b,[t],true)
187
+ end
188
+ when /^all:(.*)$/
189
+ self.block_names.each do |b|
190
+ out += block_dereference(b,[$1],true)
191
+ end
192
+ when /:/
193
+ tmp = t.split(/:/)
194
+ b = tmp.shift
195
+ out += block_dereference(b,[tmp.join(':')],true)
196
+ else
197
+ fault "Cannot determine block in order to run #{t}."
198
+ end
199
+ end
200
+ out.uniq!
201
+ out
202
+ end
203
+ def tasker_handle_results(task, result, problem_or_directory=nil, totals={})
204
+ action = @workload.select{|w|w.full_name == task.task_name}.first
205
+ # track_results(action, result, problem, totals)
206
+ if result == 'fail'
207
+ message = (problem_or_directory || "#{action.class_string} '#{action.name}' failed without an error signature").to_s
208
+ begin
209
+ error message
210
+ rescue
211
+ end
212
+ @failing ||= 0
213
+ @failing += 1
214
+ @first_error = {}
215
+ @first_error[action.class_string] ||= message
216
+ end
217
+ @results ||= {}
218
+ @results[action.class_string] ||= {}
219
+ @results[action.class_string][action.block.name] ||= {'pass' => [], 'fail' => [], :cancel =>[]}
220
+ @results[action.class_string][action.block.name][result] << action
221
+ @report_file.puts "#{result} #{action.class_string} #{task.task_name} #{problem_or_directory}"
222
+ end
223
+ def results_line(type,block,total)
224
+ blocks = block == 'all' ? @results[type].keys : [block]
225
+ if total
226
+ pass_fail_cancel = [0,0,0,0,0,0,0]
227
+ blocks.each do |b|
228
+ res_hash = @results[type][b]
229
+ pass_fail_cancel[0] += res_hash['pass'].size
230
+ pass_fail_cancel[2] += res_hash['fail'].size
231
+ pass_fail_cancel[4] += res_hash[:cancel].size
232
+ end
233
+ pass_fail_cancel[6] = pass_fail_cancel[0] + pass_fail_cancel[2] + pass_fail_cancel[4]
234
+ pass_fail_cancel[1] = (100 * pass_fail_cancel[0]/pass_fail_cancel[6]).round
235
+ pass_fail_cancel[3] = (100 * pass_fail_cancel[2]/pass_fail_cancel[6]).round
236
+ pass_fail_cancel[5] = (100 * pass_fail_cancel[4]/pass_fail_cancel[6]).round
237
+ str = pass_fail_cancel[0] > 0 ? ' %6d %3d |' : ' %6d %3d |'
238
+ str += pass_fail_cancel[3] > 0 ? ' %6d %3d |' : ' %6d %3d |'
239
+ str += pass_fail_cancel[5] > 0 ? ' %6d %3d |' : ' %6d %3d |'
240
+ return "#{str} %6d" % pass_fail_cancel
241
+ else
242
+ fault 'Internal error: detailed result reporting not yet supported'
243
+ end
244
+ end
245
+ def find_action(t_name)
246
+ address = t_name.split(/:/)
247
+
248
+ block_name = address.shift.to_sym
249
+ block = self.blocks[block_name] or fault("Couldn't find block '#{block_name}'")
250
+
251
+ config_name = address.shift.to_sym
252
+ config = block.configurations[config_name] or fault("Couldn't find configuration '#{config_name}' in block '#{block_name}")
253
+
254
+ thing = address.shift.to_sym
255
+ action = config.actions[thing]
256
+ return action if action
257
+
258
+ test_list = config.test_lists[thing] or fault("Could not find action or test list '#{thing}' in block:configuration '#{block_name}:#{config_name}'")
259
+ test_name = address.shift.to_sym
260
+ test = test_list.tests[test_name] or fault("Could not find test '#{test_name}' in block:configuration:list '#{block_name}:#{config_name}:#{thing}'")
261
+ return test
262
+ end
263
+ def banner_line(str)
264
+ @report_file.puts str.gsub(/\[\d+m/,'')
265
+ puts str
266
+ end
267
+ def banner
268
+
269
+ banner_line '--------------------------------- ------------ ------------ ------------ --------'
270
+ banner_line ' | PASS # % | FAIL # % | CNCL # % | TOTAL '
271
+ if @results['Action']
272
+ banner_line ( ' ACTIONS |' + results_line('Action','all',true))
273
+ @results['Action'].each_key do |block|
274
+ banner_line((' %-29s |' % block) + results_line('Action',block,true))
275
+ end
276
+ end
277
+ if @results['Test']
278
+ banner_line ( ' TESTS |' + results_line('Test','all',true))
279
+ @results['Test'].each_key do |block|
280
+ banner_line((' %-29s |' % block) + results_line('Test',block,true))
281
+ end
282
+ end
283
+ banner_line '--------------------------------- ------------ ------------ ------------ --------'
284
+ @report_file.close
285
+
286
+ puts "Full report available here: #{@report_name}"
287
+ if @first_error
288
+ fault("This workload had #{@failing} error(s).\n" +
289
+ (@first_error['Action'] ? " The first action related error encountered was:\n #{@first_error['Action']}" : '') +
290
+ (@first_error['Test' ] ? " The first test related error encountered was:\n #{ @first_error['Test' ]}" : '') ,
291
+ @first_error['Action'] || @first_error['Test']
292
+ )
293
+ end
294
+ end
295
+ def tasker_finish
296
+ banner
297
+ end
298
+ def tasker_run_task(t_obj)
299
+ t = find_action(t_obj.task_name)
300
+ begin
301
+ t.foreground = @foreground
302
+ t.run
303
+ rescue ReportingError => e
304
+ # FIXME reuse test error states here
305
+ t.state = 'fail'
306
+ rescue Exception => e
307
+ t.problem = Problem.new
308
+ t.problem.signature = "#{t.full_name} #{e.class} --- #{e.message}"
309
+ puts e.backtrace
310
+ # FIXME reuse test error states here
311
+ t.state = 'fail'
312
+ end
313
+ #track_results(t ,t.state,t.problem ,t.totals)
314
+ @tasker.register_results(t_obj,t.state,t.problem || t.directory,t.totals)
315
+ end
316
+ # def enable_tracking(opc,opi)
317
+ # # puts "enabled tracking(#{opc},#{opi})"
318
+ # init_results_sockets(:client)
319
+ # @opc = opc
320
+ # @opi = opi
321
+ # end
322
+ # def track_complete(state,first_error = nil)
323
+ # return unless @opc
324
+ # msg = Message.new
325
+ # msg.project = 'gandalf'
326
+ # msg.type = 'complete'
327
+ # msg.state = state
328
+ # msg.data = {
329
+ # 'opc' => @opc ,
330
+ # 'opi' => @opi ,
331
+ # 'first_error' => first_error
332
+ # }
333
+ # send_work_message(msg)
334
+ # end
335
+ # def track_results(test_action,state,problem,totals)
336
+ # return unless @opc
337
+ # msg = Message.new
338
+ # msg.project = 'gandalf'
339
+ # msg.type = 'test_action'
340
+ # msg.state = state
341
+ # msg.data = {
342
+ # 'name' => test_action.bundle_name,
343
+ # 'block' => test_action.block.name,
344
+ # 'opc' => @opc,
345
+ # 'opi' => @opi,
346
+ # 'first_error' => problem && problem.signature,
347
+ # 'file' => problem && problem.file,
348
+ # 'bundle' => problem && problem.bundle,
349
+ # 'totals' => totals
350
+ # }
351
+ # # puts "sending totals #{test_action.totals.inspect}"
352
+ # puts "sending message #{msg.data.inspect}"
353
+ # if test_action.class_string == 'Action'
354
+ # msg.data['action' ] = test_action.name
355
+ # else
356
+ # msg.data['test' ] = test_action.name
357
+ # msg.data['test_list'] = test_action.test_list.name
358
+ # end
359
+ # send_work_message(msg)
360
+ # end
361
+ def shortcut(name, array)
362
+ @shortcuts ||= {}
363
+ @shortcuts[name] = array
364
+ end
365
+
366
+ def discover_subprojects ; file_glob("#{@directory}/*/base_chip/project.rb" , /(\w+)\/base_chip\/project\.rb$/ , :subproject )
367
+ file_glob("#{@directory}/base_chip/subprojects/*.rb" , /base_chip\/subprojects\/(\w+)\.rb$/ , :subproject ) end
368
+ def discover_blocks ; file_glob("#{@directory}/*/base_chip/block.rb" , /(\w+)\/base_chip\/block\.rb$/ , :block )
369
+ file_glob("#{@directory}/base_chip/block/*.rb" , /base_chip\/blocks\/(\w+)\.rb$/ , :block ) end
370
+ def discover_configurations ; file_glob("#{@directory}/base_chip/configurations/*.rb", /base_chip\/configurations\/(\w+)\.rb$/, :configuration ) end
371
+ def discover_cluster_types ; file_glob("#{@directory}/base_chip/cluster_types/*.rb" , /base_chip\/cluster_types\/(\w+)\.rb$/ , :cluster_type ) end
372
+ def use_tool(name,version)
373
+ tool :name do |t|
374
+ t.select_version version
375
+ end
376
+ end
377
+ attr_reader :registered_modes
378
+ def register_mode(name)
379
+ @registered_modes ||= []
380
+ @registered_modes << name.to_s
381
+ end
382
+ def default_modes
383
+ %w{ coverage gates fast debug profiling }.each { |m| register_mode m }
384
+ end
385
+ def configure
386
+ return if @configured
387
+ @directory = BaseChip.root
388
+ @modes += BaseChip.options.modes.split(/,/) if BaseChip.options.modes
389
+ super
390
+ @modes.each do |name|
391
+ fault "Attempted to call mode '#{name}', which isn't registered with the project. Call register_mode(#{name}) in project.rb to allow. Valid modes are #{project.registered_modes}" unless project.registered_modes.include? name.to_s
392
+ end
393
+ if self.blocks
394
+ @directory_prefix = figure_directory_prefix
395
+ @block_names = self.blocks.keys
396
+ end
397
+ end
398
+ def dereference_clusters
399
+ return nil unless cluster_names = BaseChip.options.jobs
400
+ configure
401
+ fault "Cluster submission attempted, but no cluster types are configured." unless @cluster_types
402
+ @dereferenced = []
403
+ cluster_names = cluster_names.split(/,/)
404
+ cluster_names.each do |cn|
405
+ type = nil
406
+ cluster = nil
407
+ jobs = nil
408
+ cn_orig = cn
409
+ clusters = []
410
+
411
+ if cn.sub!(/^(\d+)(?::|$)/,'')
412
+ jobs = $1.to_i
413
+ end
414
+ if cn.sub!(/:(\d+)$/,'')
415
+ fault "Multiple counts found in '#{cn_orig}'. Separate multiple cluster specifiers with commas." if jobs
416
+ jobs = $1.to_i
417
+ end
418
+
419
+ case cn
420
+ when /^([^:]+):([^:]+)$/
421
+ cluster = $2
422
+ if $1 == 'all' || $1 == ''
423
+ cluster_types.each_value do |cluster_type|
424
+ clusters += cluster_type.dereference(cluster,jobs,true)
425
+ end
426
+ elsif cluster_type = @cluster_types[$1.to_sym]
427
+ clusters += cluster_type.dereference(cluster,jobs,false)
428
+ else
429
+ fault "Could not find cluster type '#{$1}' in cluster specifier '#{cn_orig}'." if jobs
430
+ end
431
+ when /^([^:]+)$/
432
+ if cluster_type = @cluster_types[$1.to_sym]
433
+ clusters += cluster_type.dereference('all',jobs,true)
434
+ else
435
+ cluster_types.each_value do |cluster_type|
436
+ clusters += cluster_type.dereference('all',jobs,true)
437
+ end
438
+ end
439
+ when ''
440
+ cluster_types.each_value do |cluster_type|
441
+ clusters += cluster_type.dereference('all',jobs,true)
442
+ end
443
+ else
444
+ fault "Could not parse the cluster specifier '#{cn_orig}'." if jobs
445
+ end
446
+ fault "No clusters could be determined for the cluster specifier '#{cn_orig}'." if clusters.empty?
447
+
448
+ if cluster_order
449
+ cluster_order.each do |name|
450
+ tmp = clusters.delete_if {|c| c.full_name == "#{@name}:#{name}"}
451
+ try_add_clusters tmp, jobs
452
+ end
453
+ end
454
+ try_add_clusters clusters, jobs
455
+ end
456
+ @dereferenced
457
+ end
458
+ def try_add_clusters(clusters, jobs)
459
+ clusters.each do |c|
460
+ next if @dereferenced.include? c
461
+ c.configure
462
+ fault "could not determine number of jobs to run in cluster '#{c.full_name}'. Consider setting a default for this cluster." unless (c.default_jobs || c.maximum_jobs || jobs)
463
+ if (c.default_jobs || c.maximum_jobs) == nil; c.slots = jobs
464
+ elsif jobs.nil? ; c.slots = c.default_jobs || c.maximum_jobs
465
+ elsif jobs > c.maximum_jobs ; c.slots = c.maximum_jobs
466
+ else c.slots = jobs
467
+ end
468
+ @dereferenced << c
469
+ end
470
+ end
471
+ end
472
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright 2011 Tommy Poulter
2
+ #
3
+ # This file is part of basechip.
4
+ #
5
+ # basechip is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 3 as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # basechip is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with basechip. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ module BaseChip
18
+ class Requirement
19
+ include Dsl
20
+ include Base
21
+
22
+ def configure
23
+ @configure = true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright 2011 Tommy Poulter
2
+ #
3
+ # This file is part of basechip.
4
+ #
5
+ # basechip is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 3 as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # basechip is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with basechip. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'base_chip/track_state'
18
+ require 'base_chip/taskable'
19
+
20
+ module BaseChip
21
+ module Runable
22
+ def self.included mod
23
+ mod.extend Runable::ClassMethods
24
+ mod.class_eval do
25
+ include Runable::InstanceMethods
26
+ include Taskable
27
+ include TrackState
28
+ attr_accessor :cl_args
29
+ end
30
+ end
31
+ module ClassMethods
32
+ end
33
+ module InstanceMethods
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ # Copyright 2011 Tommy Poulter
2
+ #
3
+ # This file is part of basechip.
4
+ #
5
+ # basechip is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 3 as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # basechip is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with basechip. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ module BaseChip
18
+ class SourceLanguage
19
+ include Dsl
20
+ include Base
21
+ define_settings({:directories => [ Array ],
22
+ :globs => [ Array ],
23
+ :files => [ Array ]})
24
+
25
+ def configure
26
+ return if @configured
27
+ super
28
+ if @globs and @directories and not @files
29
+ @files = []
30
+ @globs.each do |e|
31
+ @directories.each do |d|
32
+ d = absolute_path d
33
+ @files += Dir.glob("#{d}/#{e}")
34
+ end
35
+ end
36
+ # @files.uniq!
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+ # Copyright 2011 Tommy Poulter
2
+ #
3
+ # This file is part of basechip.
4
+ #
5
+ # basechip is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 3 as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # basechip is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with basechip. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'base_chip/source_language'
18
+ module BaseChip
19
+ class SourceType
20
+ include Dsl
21
+ include Base
22
+ define_children({:source_language => SourceLanguage })
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ # Copyright 2011 Tommy Poulter
2
+ #
3
+ # This file is part of basechip.
4
+ #
5
+ # basechip is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 3 as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # basechip is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with basechip. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ module BaseChip
18
+ class Statistic
19
+ include Dsl
20
+ include Base
21
+ define_settings({:regex => [Regexp , Array],
22
+ :error_if_missing => [Boolean ],
23
+ :per_state => [Boolean ],
24
+ :across_states => [Boolean ],
25
+ :for_states => [String , Array]})
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright 2011 Tommy Poulter
2
+ #
3
+ # This file is part of basechip.
4
+ #
5
+ # basechip is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License version 3 as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # basechip is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with basechip. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ module BaseChip
18
+ class Task
19
+ include Taskable
20
+ end
21
+ end