rant 0.3.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/NEWS +21 -0
  2. data/README +8 -0
  3. data/Rantfile +30 -16
  4. data/TODO +3 -4
  5. data/devel-notes +16 -0
  6. data/doc/csharp.rdoc +2 -3
  7. data/doc/examples/myprog/README +2 -0
  8. data/doc/examples/myprog/Rantfile +13 -0
  9. data/doc/examples/myprog/src/Rantfile +15 -0
  10. data/doc/examples/myprog/src/lib.c +6 -0
  11. data/doc/examples/myprog/src/lib.h +4 -0
  12. data/doc/examples/myprog/src/main.c +7 -0
  13. data/doc/rantfile.rdoc +108 -3
  14. data/lib/rant/cs_compiler.rb +6 -4
  15. data/lib/rant/import.rb +13 -0
  16. data/lib/rant/import/rubypackage.rb +43 -20
  17. data/lib/rant/plugin/configure.rb +21 -7
  18. data/lib/rant/plugin/csharp.rb +8 -9
  19. data/lib/rant/rantenv.rb +3 -0
  20. data/lib/rant/rantfile.rb +66 -33
  21. data/lib/rant/rantlib.rb +133 -27
  22. data/lib/rant/rantsys.rb +197 -42
  23. data/rantmethods.rb +46 -0
  24. data/setup.rb +18 -4
  25. data/test/plugin/configure/Rantfile +0 -6
  26. data/test/plugin/configure/test_configure.rb +2 -2
  27. data/test/plugin/csharp/test_csharp.rb +7 -2
  28. data/test/plugin/rantfile +45 -0
  29. data/test/plugin/test_conf_csharp.rb +53 -0
  30. data/test/project1/Rantfile +4 -0
  31. data/test/project1/test_project.rb +33 -8
  32. data/test/project2/buildfile +3 -3
  33. data/test/project2/sub1/Rantfile +3 -3
  34. data/test/project2/test_project.rb +6 -4
  35. data/test/project_rb1/test_project_rb1.rb +2 -2
  36. data/test/standalone.rf +10 -0
  37. data/test/subdirs/Rantfile +26 -0
  38. data/test/subdirs/sub1/Rantfile +15 -0
  39. data/test/subdirs/sub2/rantfile.rb +14 -0
  40. data/test/subdirs/sub2/sub/rantfile +15 -0
  41. data/test/subdirs/test_subdirs.rb +96 -0
  42. data/test/test_env.rb +3 -3
  43. data/test/test_filelist.rb +143 -0
  44. data/test/test_lighttask.rb +21 -0
  45. data/test/test_metatask.rb +1 -1
  46. data/test/test_rant_interface.rb +5 -5
  47. data/test/test_sys.rb +7 -1
  48. data/test/test_task.rb +25 -0
  49. data/test/toplevel.rf +0 -1
  50. data/test/tutil.rb +26 -1
  51. metadata +39 -14
@@ -267,11 +267,24 @@ EOF
267
267
  # code by directly inserting the code.
268
268
  def resolve_requires script
269
269
  rs = ""
270
+ # TODO: skip multiline comments (=begin, =end) only of
271
+ # @skip_comments is true
272
+ in_ml_comment = false
270
273
  script.each { |line|
274
+ if in_ml_comment
275
+ if line =~ /^=end/
276
+ in_ml_comment = false
277
+ end
278
+ next if @skip_comments
279
+ end
271
280
  # skip shebang line
272
281
  next if line =~ /^#! ?(\/|\\)?\w/
273
282
  # skip pure comment lines
274
283
  next if line =~ /^\s*#/ if @skip_comments
284
+ if line =~ /^=begin\s/
285
+ in_ml_comment = true
286
+ next if @skip_comments
287
+ end
275
288
  if line =~ /\s*(require|load)\s+('|")rant\/(\w+)(\.rb)?('|")/
276
289
  name = $3
277
290
  next if @core_imports.include? name
@@ -1,23 +1,6 @@
1
1
 
2
2
  require 'rant/rantlib'
3
3
 
4
- =begin
5
- class Rant::MethodRecorder
6
- ACCEPT_ALL_BLOCK = lambda { true }
7
- def intialize(&accept)
8
- @ml = []
9
- @accept = &accept || ACCEPT_ALL_BLOCK
10
- end
11
- def method_missing(sym, *args)
12
- if @accept.call(sym, args)
13
- @ml << [sym, args]
14
- else
15
- super
16
- end
17
- end
18
- end
19
- =end
20
-
21
4
  class Rant::RubyPackage
22
5
 
23
6
  class << self
@@ -29,14 +12,14 @@ class Rant::RubyPackage
29
12
  when String: args.first
30
13
  when Symbol: args.first.to_s
31
14
  else
32
- app.abort("RubyDoc takes only one additional " +
15
+ app.abort("RubyPackage takes only one additional " +
33
16
  "argument, which should be a string or symbol.")
34
17
  end
35
18
  self.new(:app => app, :__caller__ => ch,
36
19
  :name => pkg_name, &block)
37
20
  else
38
21
  app.abort(app.pos_text(file, ln),
39
- "RubyDoc takes only one additional argument, " +
22
+ "RubyPackage takes only one additional argument, " +
40
23
  "which should be a string or symbol.")
41
24
  end
42
25
  end
@@ -105,7 +88,11 @@ class Rant::RubyPackage
105
88
  end
106
89
  def #{a}=(val)
107
90
  unless val.nil? || Array === val
108
- val = [val]
91
+ if val.respond_to? :to_ary
92
+ val = val.to_ary
93
+ else
94
+ val = [val]
95
+ end
109
96
  end
110
97
  @data["#{a}"] = val
111
98
  end
@@ -129,6 +116,9 @@ class Rant::RubyPackage
129
116
  name = opts[:name]
130
117
  @ch = opts[:__caller__] || Rant::Lib.parse_caller_elem(caller[0])
131
118
  unless name
119
+ # TODO: pos_text
120
+ @app.warn_msg(@app.pos_text(@ch[:file], @ch[:ln]),
121
+ "No package name given, using directory name.")
132
122
  # use directory name as project name
133
123
  name = File.split(Dir.pwd)[1]
134
124
  # reset name if it contains a slash or a backslash
@@ -149,6 +139,35 @@ class Rant::RubyPackage
149
139
  end
150
140
  end
151
141
 
142
+ def validate_attrs(pkg_type = :general)
143
+ %w(name files).each { |a|
144
+ pkg_requires_attr a
145
+ }
146
+ case pkg_type
147
+ when :gem
148
+ %w(version summary).each { |a|
149
+ gem_requires_attr a
150
+ }
151
+ end
152
+ end
153
+ private :validate_attrs
154
+
155
+ def gem_requires_attr(attr_name)
156
+ unless @data[attr_name] || @data["gem-#{attr_name}"]
157
+ @app.abort("RubyPackaged defined: " +
158
+ @app.pos_text(@ch[:file], @ch[:ln]),
159
+ "gem specification requires `#{attr_name}' attribute")
160
+ end
161
+ end
162
+
163
+ def pkg_requires_attr(attr_name)
164
+ unless @data[attr_name]
165
+ @app.abort("RubyPackaged defined: " +
166
+ @app.pos_text(@ch[:file], @ch[:ln]),
167
+ "`#{attr_name}' attribute required")
168
+ end
169
+ end
170
+
152
171
  def map_to_gemspec spec
153
172
  mapped_attrs = []
154
173
  # Map attributes from data to the gem spec as explicitely
@@ -174,6 +193,7 @@ class Rant::RubyPackage
174
193
  end
175
194
  }
176
195
  end
196
+ private :map_to_gemspec
177
197
 
178
198
  def pkg_dir_task
179
199
  return if @pkg_dir_task
@@ -224,6 +244,7 @@ class Rant::RubyPackage
224
244
  # Create task for gem building. If tname is a true value, a
225
245
  # shortcut-task will be created.
226
246
  def gem_task(tname = :gem)
247
+ validate_attrs(:gem)
227
248
  # We first define the task to create the gem, and afterwards
228
249
  # the task to create the pkg directory to ensure that a
229
250
  # pending description is used to describe the gem task.
@@ -273,6 +294,7 @@ class Rant::RubyPackage
273
294
  end
274
295
 
275
296
  def tar_task(tname = :tar)
297
+ validate_attrs
276
298
  # Create tar task first to ensure that a pending description
277
299
  # is used for the tar task and not for the dist dir task.
278
300
  pkg_name = tar_pkg_path
@@ -292,6 +314,7 @@ class Rant::RubyPackage
292
314
  end
293
315
 
294
316
  def zip_task(tname = :zip)
317
+ validate_attrs
295
318
  # Create zip task first to ensure that a pending description
296
319
  # is used for the zip task and not for the dist dir task.
297
320
  pkg_name = zip_pkg_path
@@ -11,8 +11,8 @@ module Rant::Plugin
11
11
  # The configuration file will be read and the data hash
12
12
  # set up accordingly.
13
13
  # ==== Config file doesn't exist
14
- # The configuration process is run with +startup_modes+ which
15
- # has to be one of CHECK_MODES. +startup_modes+ defaults to
14
+ # The configuration process is run with +init_modes+ which
15
+ # has to be one of CHECK_MODES. +init_modes+ defaults to
16
16
  # :default, which means if the configfile doesn't exist,
17
17
  # all values will be set to their defaults on startup.
18
18
  # === Access to configuration in Rantfile
@@ -78,6 +78,10 @@ module Rant::Plugin
78
78
  # Decide what the configure plugin does on startup if the
79
79
  # configuration file doesn't exist. Initialized to
80
80
  # <tt>[:guess]</tt>.
81
+ #
82
+ # If you want to control when the plugin should initialize the
83
+ # configuration values, set this to +[:explicit]+ and call the
84
+ # +init+ method with the init_modes you like as argument.
81
85
  attr_accessor :init_modes
82
86
 
83
87
  # Decide what the configure plugin does *after* reading the
@@ -199,6 +203,17 @@ module Rant::Plugin
199
203
  checklist << ConfigureCheck.new(key, val, &block)
200
204
  end
201
205
 
206
+ def init modes = @init_modes
207
+ if modes == [:explicit]
208
+ modes = [:guess]
209
+ end
210
+ @no_action = @no_action_list.include? @app.cmd_targets.first
211
+ unless @no_action
212
+ init_config modes
213
+ @configured = true
214
+ end
215
+ end
216
+
202
217
  # Run the configure process in the given modes.
203
218
  def run_checklist(modes = [:guess, :interact])
204
219
  @checklist.each { |c|
@@ -230,8 +245,7 @@ module Rant::Plugin
230
245
  end
231
246
 
232
247
  def rant_plugin_init
233
- @no_action = @no_action_list.include? @app.cmd_targets.first
234
- @no_action || init_config
248
+ init unless @init_modes == [:explicit]
235
249
  end
236
250
 
237
251
  def rant_plugin_stop
@@ -242,12 +256,12 @@ module Rant::Plugin
242
256
  private
243
257
 
244
258
  # Returns true on success, nil on failure.
245
- def init_config
259
+ def init_config modes
246
260
  if File.exist? @file
247
261
  read_yaml
248
262
  @configured = true
249
- elsif !@init_modes == [:default]
250
- run_checklist @init_modes
263
+ elsif modes != [:default]
264
+ run_checklist modes
251
265
  end
252
266
  if @override_modes && !@override_modes.empty?
253
267
  run_checklist @override_modes
@@ -87,7 +87,7 @@ module Rant
87
87
  def take_common_attrs comp
88
88
  @csc_name = comp.csc_name
89
89
  @long_name = comp.long_name
90
- @csc = comp.csc
90
+ @csc_bin = comp.csc_bin
91
91
  @debug = comp.debug
92
92
  comp.defines.each { |e|
93
93
  @defines << e unless @defines.include? e
@@ -148,25 +148,23 @@ module Rant
148
148
  def initialize(app, assembly)
149
149
  @assembly = assembly
150
150
  super(app, @assembly.out) { |t|
151
- app.context.instance_eval {
152
- sys.sh assembly.send("cmd_" + assembly.target)
153
- }
151
+ app.context.sys assembly.send("cmd_" + assembly.target)
154
152
  }
155
153
  end
154
+ =begin
156
155
  def resolve_prerequisites
157
156
  @assembly.init
158
157
  @pre.concat(@assembly.sources)
159
158
  @pre.concat(@assembly.resources) if @assembly.resources
160
159
  super
161
160
  end
162
- ### experimental ###
161
+ =end
163
162
  def invoke(force = false)
164
163
  @assembly.init
165
164
  @pre.concat(@assembly.sources)
166
165
  @pre.concat(@assembly.resources) if @assembly.resources
167
166
  super
168
167
  end
169
- ####################
170
168
  end
171
169
  end # module Rant
172
170
 
@@ -234,9 +232,9 @@ module Rant::Plugin
234
232
  c.interact {
235
233
  c.prompt "Command to invoke your C# Compiler: "
236
234
  }
237
- c.react {
238
- c.msg "Using `#{c.value}' as C# compiler."
239
- }
235
+ #c.react {
236
+ # c.msg "Using `#{c.value}' as C# compiler."
237
+ #}
240
238
  end
241
239
  @config.check "csc-optimize" do |c|
242
240
  c.default true
@@ -256,6 +254,7 @@ module Rant::Plugin
256
254
  return nil unless @config
257
255
  return nil unless @config.configured?
258
256
  csc_bin = @config["csc"]
257
+ #puts "using csc from config: " + csc_bin
259
258
  csc = Rant::CsCompiler.new
260
259
  csc.csc = csc_bin
261
260
  csc.optimize = @config["csc-optimize"]
@@ -31,6 +31,9 @@ class Rant::Path
31
31
  def absolute_path
32
32
  @abs_path ||= File.expand_path(@path)
33
33
  end
34
+ def dirname
35
+ File.dirname absolute_path
36
+ end
34
37
  end
35
38
 
36
39
  # This module provides some platform indenpendant
@@ -18,13 +18,17 @@ module Rant
18
18
  class Rantfile < Path
19
19
 
20
20
  attr_reader :tasks
21
+ attr_accessor :project_subdir
21
22
 
22
23
  def initialize(*args)
23
24
  super
24
25
  @tasks = []
26
+ @project_subdir = nil
25
27
  end
26
28
  end # class Rantfile
27
29
 
30
+ # Any +object+ is considered a _task_ if
31
+ # <tt>Rant::Worker === object</tt> is true.
28
32
  module Worker
29
33
 
30
34
  INVOKE_OPT = {}.freeze
@@ -52,6 +56,19 @@ module Rant
52
56
  name
53
57
  end
54
58
 
59
+ def project_subdir
60
+ @rantfile.nil? ? "" : @rantfile.project_subdir
61
+ end
62
+
63
+ def full_name
64
+ sd = project_subdir
65
+ sd.empty? ? name : File.join(sd, name)
66
+ end
67
+
68
+ def goto_task_home
69
+ @app.goto_project_dir project_subdir
70
+ end
71
+
55
72
  def done?
56
73
  @done
57
74
  end
@@ -60,8 +77,17 @@ module Rant
60
77
  !done?
61
78
  end
62
79
 
63
- # +opt+ shouldn't be modified
80
+ # +opt+ is a Hash and shouldn't be modified.
81
+ # All objects implementing the Rant::Worker protocol should
82
+ # know about the following +opt+ values:
83
+ # <tt>:needed?</tt>::
84
+ # Just check if this task is needed. Should do the same
85
+ # as calling Worker#needed?
86
+ # <tt>:force</tt>::
87
+ # Run task action even if needed? is false.
64
88
  def invoke(opt = INVOKE_OPT)
89
+ goto_task_home
90
+ return needed? if opt[:needed?]
65
91
  self.run if opt[:force] || self.needed?
66
92
  end
67
93
 
@@ -71,6 +97,7 @@ module Rant
71
97
 
72
98
  def run
73
99
  return unless @block
100
+ goto_task_home
74
101
  @block.arity == 0 ? @block.call : @block[self]
75
102
  end
76
103
  private :run
@@ -90,16 +117,16 @@ module Rant
90
117
 
91
118
  class << self
92
119
  def for_task t
93
- mt = self.new(t.name)
120
+ mt = self.new(t.full_name)
94
121
  mt << t
95
122
  end
96
123
  def for_tasks *tasks
97
- mt = self.new(tasks.first.name)
124
+ mt = self.new(tasks.first.full_name)
98
125
  mt.concat tasks
99
126
  mt
100
127
  end
101
128
  def for_task_list tasks
102
- mt = self.new(tasks.first.name)
129
+ mt = self.new(tasks.first.full_name)
103
130
  mt.concat tasks
104
131
  mt
105
132
  end
@@ -121,6 +148,7 @@ module Rant
121
148
  def invoke(opt = INVOKE_OPT)
122
149
  uf = false
123
150
  each { |t| t.invoke(opt) && uf = true }
151
+ uf
124
152
  end
125
153
 
126
154
  def description
@@ -166,8 +194,7 @@ module Rant
166
194
  block) { |name,pre,blk|
167
195
  # TODO: ensure pre is empty
168
196
  # TODO: earlier setting of app?
169
- t = self.new(app, name, &blk)
170
- t
197
+ self.new(app, name, &blk)
171
198
  }
172
199
  end
173
200
  end
@@ -190,7 +217,7 @@ module Rant
190
217
  end
191
218
 
192
219
  def app
193
- @app || Rant.rantapp
220
+ @app
194
221
  end
195
222
 
196
223
  def needed &block
@@ -210,6 +237,7 @@ module Rant
210
237
  def needed?
211
238
  return false if done?
212
239
  return true if @needed.nil?
240
+ goto_task_home
213
241
  if @needed.arity == 0
214
242
  @needed.call
215
243
  else
@@ -218,6 +246,8 @@ module Rant
218
246
  end
219
247
 
220
248
  def invoke(opt = INVOKE_OPT)
249
+ return needed? if opt[:needed?]
250
+ goto_task_home
221
251
  if opt[:force] && !@done
222
252
  self.run
223
253
  @done = true
@@ -247,14 +277,10 @@ module Rant
247
277
  class << self
248
278
  def rant_generate(app, ch, args, &block)
249
279
  if args.size == 1
250
- if Hash === args.first
251
- UserTask.rant_generate(app, ch, args, &block)
252
- else
253
- LightTask.rant_generate(app, ch, args, &block)
254
- end
280
+ UserTask.rant_generate(app, ch, args, &block)
255
281
  else
256
282
  app.abort("Task generator currently takes only one" +
257
- " argument. (Generates a LightTask or UserTask)")
283
+ " argument. (generates a UserTask)")
258
284
  end
259
285
  end
260
286
  end
@@ -306,17 +332,21 @@ module Rant
306
332
  end
307
333
 
308
334
  # Enhance this task with the given dependencies and blk.
309
- def enhance(deps = [], &blk)
335
+ def enhance(deps = nil, &blk)
310
336
  if deps
311
337
  @pre_resolved = false
312
338
  @pre.concat deps
313
339
  end
314
- if blk
315
- first_block = @block
316
- @block = lambda { |t|
317
- first_block[t]
318
- blk[t]
319
- }
340
+ if @block
341
+ if blk
342
+ first_block = @block
343
+ @block = lambda { |t|
344
+ first_block[t]
345
+ blk[t]
346
+ }
347
+ end
348
+ else
349
+ @block = blk
320
350
  end
321
351
  end
322
352
 
@@ -332,6 +362,7 @@ module Rant
332
362
  end
333
363
 
334
364
  def internal_invoke opt, ud_init = true
365
+ goto_task_home
335
366
  update = ud_init || opt[:force]
336
367
  dep = nil
337
368
  uf = false
@@ -414,10 +445,11 @@ module Rant
414
445
  if @pre_resolved
415
446
  return @pre.each { |t| yield(t) }
416
447
  end
448
+ my_full_name = full_name
417
449
  @pre.map! { |t|
418
450
  if Worker === t
419
451
  # Remove references to self from prerequisites!
420
- if t.name == @name
452
+ if t.full_name == my_full_name
421
453
  nil
422
454
  else
423
455
  yield(t)
@@ -425,15 +457,13 @@ module Rant
425
457
  end
426
458
  else
427
459
  t = t.to_s if Symbol === t
428
- if t == @name
460
+ if t == my_full_name
429
461
  nil
430
462
  else
431
- # Pre 0.2.6 task selection scheme ###########
432
- # Take care: selection is an array of tasks
433
- #selection = @app.select_tasks { |st| st.name == t }
434
- #############################################
435
-
436
- selection = @app.select_tasks_by_name t
463
+ #STDERR.puts "selecting `#{t}'"
464
+ selection = @app.select_tasks_by_name t,
465
+ project_subdir
466
+ #STDERR.puts selection.size
437
467
  if selection.empty?
438
468
  # use return value of yield
439
469
  yield(t)
@@ -496,6 +526,7 @@ module Rant
496
526
  private
497
527
  def ud_init_by_needed
498
528
  if @needed
529
+ goto_task_home
499
530
  @needed.arity == 0 ? @needed.call : @needed[self]
500
531
  end
501
532
  end
@@ -525,6 +556,7 @@ module Rant
525
556
 
526
557
  def invoke(opt = INVOKE_OPT)
527
558
  return if done?
559
+ goto_task_home
528
560
  if @path.exist?
529
561
  @ts = @path.mtime
530
562
  internal_invoke opt, false
@@ -558,6 +590,8 @@ module Rant
558
590
  # directory.
559
591
  class DirTask < Task
560
592
 
593
+ # TODO: subdir support
594
+
561
595
  class << self
562
596
 
563
597
  # Generate a task for making a directory path.
@@ -633,10 +667,9 @@ module Rant
633
667
  end
634
668
 
635
669
  def handle_filetask(dep, opt)
636
- return true if dep.invoke opt
670
+ return @block if dep.invoke opt
637
671
  if dep.path.exist?
638
- #puts "***`#{dep.name}' requires update" if dep.path.mtime > @ts
639
- dep.path.mtime > @ts
672
+ @block && dep.path.mtime > @ts
640
673
  end
641
674
  end
642
675
 
@@ -647,7 +680,7 @@ module Rant
647
680
  "in prerequisites: no such file or task: `#{dep}'"
648
681
  self.fail
649
682
  end
650
- [dep, dep.mtime > @ts]
683
+ [dep, @block && dep.mtime > @ts]
651
684
  end
652
685
 
653
686
  def run
@@ -657,7 +690,7 @@ module Rant
657
690
  @app.sys.touch @name
658
691
  end
659
692
  end
660
- end
693
+ end # class DirTask
661
694
  module Generators
662
695
  Directory = ::Rant::DirTask
663
696
  end