basechip 0.0.1

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