rant 0.3.0 → 0.3.2

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 (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