rant 0.3.0

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 (64) hide show
  1. data/COPYING +504 -0
  2. data/README +203 -0
  3. data/Rantfile +104 -0
  4. data/TODO +19 -0
  5. data/bin/rant +12 -0
  6. data/bin/rant-import +12 -0
  7. data/devel-notes +50 -0
  8. data/doc/configure.rdoc +40 -0
  9. data/doc/csharp.rdoc +74 -0
  10. data/doc/rant-import.rdoc +32 -0
  11. data/doc/rant.rdoc +24 -0
  12. data/doc/rantfile.rdoc +227 -0
  13. data/doc/rubyproject.rdoc +210 -0
  14. data/lib/rant.rb +9 -0
  15. data/lib/rant/cs_compiler.rb +334 -0
  16. data/lib/rant/import.rb +291 -0
  17. data/lib/rant/import/rubydoc.rb +125 -0
  18. data/lib/rant/import/rubypackage.rb +417 -0
  19. data/lib/rant/import/rubytest.rb +97 -0
  20. data/lib/rant/plugin/README +50 -0
  21. data/lib/rant/plugin/configure.rb +345 -0
  22. data/lib/rant/plugin/csharp.rb +275 -0
  23. data/lib/rant/plugin_methods.rb +41 -0
  24. data/lib/rant/rantenv.rb +217 -0
  25. data/lib/rant/rantfile.rb +664 -0
  26. data/lib/rant/rantlib.rb +1118 -0
  27. data/lib/rant/rantsys.rb +258 -0
  28. data/lib/rant/rantvar.rb +82 -0
  29. data/rantmethods.rb +79 -0
  30. data/run_import +7 -0
  31. data/run_rant +7 -0
  32. data/setup.rb +1360 -0
  33. data/test/Rantfile +2 -0
  34. data/test/plugin/configure/Rantfile +47 -0
  35. data/test/plugin/configure/test_configure.rb +58 -0
  36. data/test/plugin/csharp/Hello.cs +10 -0
  37. data/test/plugin/csharp/Rantfile +30 -0
  38. data/test/plugin/csharp/src/A.cs +8 -0
  39. data/test/plugin/csharp/src/B.cs +8 -0
  40. data/test/plugin/csharp/test_csharp.rb +99 -0
  41. data/test/project1/Rantfile +127 -0
  42. data/test/project1/test_project.rb +203 -0
  43. data/test/project2/buildfile +14 -0
  44. data/test/project2/rantfile.rb +20 -0
  45. data/test/project2/sub1/Rantfile +12 -0
  46. data/test/project2/test_project.rb +87 -0
  47. data/test/project_rb1/README +14 -0
  48. data/test/project_rb1/bin/wgrep +5 -0
  49. data/test/project_rb1/lib/wgrep.rb +56 -0
  50. data/test/project_rb1/rantfile.rb +30 -0
  51. data/test/project_rb1/test/tc_wgrep.rb +21 -0
  52. data/test/project_rb1/test/text +3 -0
  53. data/test/project_rb1/test_project_rb1.rb +153 -0
  54. data/test/test_env.rb +47 -0
  55. data/test/test_filetask.rb +57 -0
  56. data/test/test_lighttask.rb +49 -0
  57. data/test/test_metatask.rb +29 -0
  58. data/test/test_rant_interface.rb +65 -0
  59. data/test/test_sys.rb +61 -0
  60. data/test/test_task.rb +115 -0
  61. data/test/toplevel.rf +11 -0
  62. data/test/ts_all.rb +4 -0
  63. data/test/tutil.rb +95 -0
  64. metadata +133 -0
@@ -0,0 +1,275 @@
1
+
2
+ # C# plugin for Rant.
3
+
4
+ require 'rant/plugin_methods'
5
+ require 'rant/cs_compiler'
6
+
7
+ module Rant
8
+
9
+ class Generators::Assembly < CsCompiler
10
+ class << self
11
+
12
+ def rant_generate(app, clr, args, &block)
13
+ assembly = self.new(&block)
14
+ if args.size == 1
15
+ targ = args.first
16
+ # embed caller information for correct resolving
17
+ # of source Rantfile
18
+ if targ.is_a? Hash
19
+ targ[:__caller__] = clr
20
+ else
21
+ targ = { :__caller__ => clr, targ => [] }
22
+ end
23
+ app.prepare_task(targ, nil) { |name,pre,blk|
24
+ assembly.out = name
25
+ t = AssemblyTask.new(app, assembly, &block)
26
+ # TODO: optimize
27
+ pre.each { |e| t << e }
28
+ t
29
+ }
30
+ else
31
+ cinf = ::Rant::Lib.parse_caller_elem(clr)
32
+ app.abort(app.pos_text(cinf[:file], cinf[:ln]),
33
+ "Assembly takes one argument, " +
34
+ "which should be like one given to the `task' command.")
35
+ end
36
+ end
37
+
38
+ def csc
39
+ @csc
40
+ end
41
+ def csc= new_csc
42
+ case new_csc
43
+ when CsCompiler
44
+ @csc = new_csc
45
+ when String
46
+ @csc = CsCompiler.new(
47
+ CsCompiler.cs_compiler_name(new_csc))
48
+ @csc.csc_bin = new_csc
49
+ when nil
50
+ @csc = nil
51
+ else
52
+ self.csc = new_csc.to_s
53
+ end
54
+ @csc
55
+ end
56
+ end
57
+ @csc = nil
58
+
59
+ # Maybe:
60
+ # ["object"]
61
+ # Compile to object code. Not *that* usual for .NET.
62
+ # ["dll"]
63
+ # Create a shared library (also called DLL).
64
+ # ["exe"]
65
+ # Create an executable.
66
+ attr_accessor :target
67
+
68
+ def initialize(comp = nil, &init_block)
69
+ super()
70
+ @target = nil
71
+ @init_block = init_block
72
+ take_common_attrs comp if comp
73
+ end
74
+
75
+ # Synonym for +out+.
76
+ def name
77
+ out
78
+ end
79
+
80
+ # Synonym for +out=+.
81
+ def name=(new_name)
82
+ out = new_name
83
+ end
84
+
85
+ # Take common attributes like +optimize+, +csc+ and similar
86
+ # from the compiler object +comp+.
87
+ def take_common_attrs comp
88
+ @csc_name = comp.csc_name
89
+ @long_name = comp.long_name
90
+ @csc = comp.csc
91
+ @debug = comp.debug
92
+ comp.defines.each { |e|
93
+ @defines << e unless @defines.include? e
94
+ }
95
+ comp.lib_link_pathes.each { |e|
96
+ @lib_link_pathes << e unless @lib_link_pathes.include? e
97
+ }
98
+ @optimize = comp.optimize
99
+ @warnings = comp.warnings
100
+ # TODO: we currently take unconditionally all misc- and
101
+ # compiler specific args
102
+ comp.misc_args.each { |e|
103
+ @misc_args << e unless @misc_args.include? e
104
+ }
105
+ comp.specific_args.each_pair { |k,v|
106
+ # k is a compiler name, v is a list of arguments
107
+ # specific to this compiler type.
108
+ cst = @specific_args[k]
109
+ unless cst
110
+ @specific_args[k] = v
111
+ next
112
+ end
113
+ v.each { |e|
114
+ cst << e unless cst.include? e
115
+ }
116
+ }
117
+ end
118
+
119
+ # Call the initialization block and intialize compiler
120
+ # interface.
121
+ def init
122
+ # setup compiler interface
123
+ comp = Plugin::Csharp.csc_for_assembly(self) || self.class.csc
124
+ take_common_attrs comp if comp
125
+
126
+ # call initialization block
127
+ @init_block[self] if @init_block
128
+
129
+ # set target type
130
+ unless @target
131
+ @target = case @out
132
+ when /\.exe$/i: "exe"
133
+ when /\.dll$/i: "dll"
134
+ when /\.obj$/i: "object"
135
+ else "exe"
136
+ end
137
+ end
138
+ # TODO: verify some attributes like @target
139
+ end
140
+
141
+ def compile
142
+ ::Rant::Sys.sh(self.send("cmd_" + @target))
143
+ end
144
+
145
+ end # class Generators::Assembly
146
+
147
+ class AssemblyTask < FileTask
148
+ def initialize(app, assembly)
149
+ @assembly = assembly
150
+ super(app, @assembly.out) { |t|
151
+ app.context.instance_eval {
152
+ sys.sh assembly.send("cmd_" + assembly.target)
153
+ }
154
+ }
155
+ end
156
+ def resolve_prerequisites
157
+ @assembly.init
158
+ @pre.concat(@assembly.sources)
159
+ @pre.concat(@assembly.resources) if @assembly.resources
160
+ super
161
+ end
162
+ ### experimental ###
163
+ def invoke(force = false)
164
+ @assembly.init
165
+ @pre.concat(@assembly.sources)
166
+ @pre.concat(@assembly.resources) if @assembly.resources
167
+ super
168
+ end
169
+ ####################
170
+ end
171
+ end # module Rant
172
+
173
+ module Rant::Plugin
174
+
175
+ # This plugin class is currently designed to be instantiated only
176
+ # once with +rant_plugin_new+.
177
+ class Csharp
178
+ include ::Rant::PluginMethods
179
+
180
+ @plugin_object = nil
181
+ class << self
182
+
183
+ def rant_plugin_new(app, cinf, *args, &block)
184
+ if args.size > 1
185
+ app.abort(app.pos_text(cinf[:file], cinf[:ln]),
186
+ "Csharp plugin takes only one argument.")
187
+ end
188
+ self.new(app, args.first, &block)
189
+ end
190
+
191
+ attr_accessor :plugin_object
192
+
193
+ def csc_for_assembly(task)
194
+ if @plugin_object
195
+ @plugin_object.csc_for_assembly(task)
196
+ else
197
+ nil
198
+ end
199
+ end
200
+ end
201
+
202
+ # Shortcut for rant_plugin_name.
203
+ attr_reader :name
204
+ # A "configure" plugin.
205
+ attr_accessor :config
206
+ # A compiler interface with settings resulting from config.
207
+ attr_reader :config_csc
208
+
209
+ def initialize(app, name = nil)
210
+ @name = name || rant_plugin_type
211
+ @app = app or raise ArgumentError, "no application given"
212
+ @config_csc = nil
213
+ @config = nil
214
+
215
+ self.class.plugin_object = self
216
+
217
+ yield self if block_given?
218
+
219
+ define_config_checks
220
+ end
221
+
222
+ def csc_for_assembly(assembly)
223
+ @config_csc ||= csc_from_config
224
+ @config_csc.nil? ? nil : @config_csc.dup
225
+ end
226
+
227
+ def define_config_checks
228
+ return unless @config
229
+ @config.check "csc" do |c|
230
+ c.default "cscc"
231
+ c.guess {
232
+ Rant::CsCompiler.look_for_cs_compiler
233
+ }
234
+ c.interact {
235
+ c.prompt "Command to invoke your C# Compiler: "
236
+ }
237
+ c.react {
238
+ c.msg "Using `#{c.value}' as C# compiler."
239
+ }
240
+ end
241
+ @config.check "csc-optimize" do |c|
242
+ c.default true
243
+ c.interact {
244
+ c.ask_yes_no "Optimize C# compilation?"
245
+ }
246
+ end
247
+ @config.check "csc-debug" do |c|
248
+ c.default false
249
+ c.interact {
250
+ c.ask_yes_no "Compile C# sources for debugging?"
251
+ }
252
+ end
253
+ end
254
+
255
+ def csc_from_config
256
+ return nil unless @config
257
+ return nil unless @config.configured?
258
+ csc_bin = @config["csc"]
259
+ csc = Rant::CsCompiler.new
260
+ csc.csc = csc_bin
261
+ csc.optimize = @config["csc-optimize"]
262
+ csc.debug = @config["csc-debug"]
263
+ csc
264
+ end
265
+
266
+ ###### methods override from PluginMethods ###################
267
+ def rant_plugin_type
268
+ "csharp"
269
+ end
270
+ def rant_plugin_name
271
+ @name
272
+ end
273
+ ##############################################################
274
+ end # class Csharp
275
+ end # module Rant::Plugin
@@ -0,0 +1,41 @@
1
+
2
+ require 'rant/rantlib'
3
+
4
+ # This module defines all instance methods required for an Rant
5
+ # plugin. Additionally, each plugin class has to define the class
6
+ # method +plugin_create+.
7
+ #
8
+ # Include this module in your plugin class to ensure your plugin won't
9
+ # break when Rant requires new methods.
10
+ module Rant::PluginMethods
11
+ # The type of your plugin as string.
12
+ def rant_plugin_type
13
+ "rant plugin"
14
+ end
15
+ # Please override this method. This is used as a name for your
16
+ # plugin instance.
17
+ def rant_plugin_name
18
+ "rant plugin object"
19
+ end
20
+ # This is used for verification. Usually you don't want to change
21
+ # this for your plugin :-)
22
+ def rant_plugin?
23
+ true
24
+ end
25
+ # Called immediately after registration.
26
+ def rant_plugin_init
27
+ end
28
+ # Called before rant runs the first task.
29
+ def rant_start
30
+ end
31
+ # Called when rant *successfully* processed all required tasks.
32
+ def rant_done
33
+ end
34
+ # You should "shut down" your plugin as response to this method.
35
+ def rant_plugin_stop
36
+ end
37
+ # Called immediately before the rant application return control to
38
+ # the caller.
39
+ def rant_quit
40
+ end
41
+ end # module Rant::PluginMethods
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'rbconfig'
4
+
5
+ module Rant end
6
+
7
+ class Rant::Path
8
+ attr_reader :path
9
+ def initialize path, abs_path = nil
10
+ @path = path or raise ArgumentError, "path not given"
11
+ @abs_path = abs_path
12
+ end
13
+ def to_s
14
+ @path.dup
15
+ end
16
+ def to_str
17
+ @path.dup
18
+ end
19
+ def exist?
20
+ File.exist? @path
21
+ end
22
+ def file?
23
+ test ?f, @path
24
+ end
25
+ def dir?
26
+ test ?d, @path
27
+ end
28
+ def mtime
29
+ File.mtime @path
30
+ end
31
+ def absolute_path
32
+ @abs_path ||= File.expand_path(@path)
33
+ end
34
+ end
35
+
36
+ # This module provides some platform indenpendant
37
+ # (let's hope) environment information.
38
+ module Rant::Env
39
+ OS = ::Config::CONFIG['target']
40
+ RUBY = ::Config::CONFIG['ruby_install_name']
41
+
42
+ @@zip_bin = false
43
+ @@tar_bin = false
44
+
45
+ def on_windows?
46
+ OS =~ /mswin/i
47
+ end
48
+
49
+ def have_zip?
50
+ if @@zip_bin == false
51
+ @@zip_bin = find_bin "zip"
52
+ end
53
+ !@@zip_bin.nil?
54
+ end
55
+
56
+ def have_tar?
57
+ if @@tar_bin == false
58
+ @@tar_bin = find_bin "tar"
59
+ end
60
+ !@@tar_bin.nil?
61
+ end
62
+
63
+ # Get an array with all pathes in the PATH
64
+ # environment variable.
65
+ def pathes
66
+ # Windows doesn't care about case in environment variables,
67
+ # but the ENV hash does!
68
+ path = on_windows? ? ENV["Path"] : ENV["PATH"]
69
+ return [] unless path
70
+ if on_windows?
71
+ path.split(";")
72
+ else
73
+ path.split(":")
74
+ end
75
+ end
76
+
77
+ # Searches for bin_name on path and returns
78
+ # an absolute path if successfull or nil
79
+ # if an executable called bin_name couldn't be found.
80
+ def find_bin bin_name
81
+ if on_windows?
82
+ bin_name_exe = nil
83
+ if bin_name !~ /\.[^\.]{1,3}$/i
84
+ bin_name_exe = bin_name + ".exe"
85
+ end
86
+ pathes.each { |dir|
87
+ file = File.join(dir, bin_name)
88
+ return file if test(?f, file)
89
+ if bin_name_exe
90
+ file = File.join(dir, bin_name_exe)
91
+ return file if test(?f, file)
92
+ end
93
+ }
94
+ else
95
+ pathes.each { |dir|
96
+ file = File.join(dir, bin_name)
97
+ return file if test(?x, file)
98
+ }
99
+ end
100
+ nil
101
+ end
102
+
103
+ # Add quotes to a path and replace File::Separators if necessary.
104
+ def shell_path path
105
+ # TODO: check for more characters when deciding wheter to use
106
+ # quotes.
107
+ if on_windows?
108
+ path = path.tr("/", "\\")
109
+ if path.include? ' '
110
+ '"' + path + '"'
111
+ else
112
+ path
113
+ end
114
+ else
115
+ if path.include? ' '
116
+ "'" + path + "'"
117
+ else
118
+ path
119
+ end
120
+ end
121
+ end
122
+
123
+ extend self
124
+ end # module Rant::Env
125
+
126
+ module Rant::Console
127
+ RANT_PREFIX = "rant: "
128
+ ERROR_PREFIX = "[ERROR] "
129
+ WARN_PREFIX = "[WARNING] "
130
+ def msg_prefix
131
+ if defined? @msg_prefix and @msg_prefix
132
+ @msg_prefix
133
+ else
134
+ RANT_PREFIX
135
+ end
136
+ end
137
+ def msg *text
138
+ pre = msg_prefix
139
+ text = text.join("\n" + ' ' * pre.length)
140
+ $stderr.puts(pre + text)
141
+ end
142
+ def err_msg *text
143
+ pre = msg_prefix + ERROR_PREFIX
144
+ text = text.join("\n" + ' ' * pre.length)
145
+ $stderr.puts(pre + text)
146
+ end
147
+ def warn_msg *text
148
+ pre = msg_prefix + WARN_PREFIX
149
+ text = text.join("\n" + ' ' * pre.length)
150
+ $stderr.puts(pre + text)
151
+ end
152
+ def ask_yes_no text
153
+ $stderr.print msg_prefix + text + " [y|n] "
154
+ case $stdin.readline
155
+ when /y|yes/i: true
156
+ when /n|no/i: false
157
+ else
158
+ $stderr.puts(' ' * msg_prefix.length +
159
+ "Please answer with `yes' or `no'")
160
+ ask_yes_no text
161
+ end
162
+ end
163
+ def prompt text
164
+ $stderr.print msg_prefix + text
165
+ input = $stdin.readline
166
+ input ? input.chomp : input
167
+ end
168
+ def option_listing opts
169
+ rs = ""
170
+ opts.each { |lopt, *opt_a|
171
+ if opt_a.size == 2
172
+ # no short option
173
+ mode, desc = opt_a
174
+ else
175
+ sopt, mode, desc = opt_a
176
+ end
177
+ next unless desc # "private" option
178
+ optstr = ""
179
+ arg = nil
180
+ if mode == GetoptLong::REQUIRED_ARGUMENT
181
+ if desc =~ /(\b[A-Z_]{2,}\b)/
182
+ arg = $1
183
+ end
184
+ end
185
+ if lopt
186
+ optstr << lopt
187
+ if arg
188
+ optstr << " " << arg
189
+ end
190
+ optstr = optstr.ljust(30)
191
+ end
192
+ if sopt
193
+ optstr << " " unless optstr.empty?
194
+ optstr << sopt
195
+ if arg
196
+ optstr << " " << arg
197
+ end
198
+ end
199
+ rs << " #{optstr}\n"
200
+ rs << " #{desc.split("\n").join("\n ")}\n"
201
+ }
202
+ rs
203
+ end
204
+
205
+ extend self
206
+ end
207
+
208
+ class Rant::CustomConsole
209
+ include Rant::Console
210
+
211
+ def initialize msg_prefix = RANT_PREFIX
212
+ @msg_prefix = msg_prefix || ""
213
+ end
214
+ def msg_prefix=(str)
215
+ @msg_prefix = str || ""
216
+ end
217
+ end