elliottcable-echoe 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. data/CHANGELOG +69 -0
  2. data/LICENSE +184 -0
  3. data/MIT-LICENSE +21 -0
  4. data/Manifest +113 -0
  5. data/README +114 -0
  6. data/Rakefile +15 -0
  7. data/TODO +4 -0
  8. data/echoe.gemspec +37 -0
  9. data/lib/echoe/client.rb +25 -0
  10. data/lib/echoe/extensions.rb +57 -0
  11. data/lib/echoe/platform.rb +36 -0
  12. data/lib/echoe/rubygems.rb +41 -0
  13. data/lib/echoe.rb +717 -0
  14. data/vendor/rake/CHANGES +400 -0
  15. data/vendor/rake/MIT-LICENSE +21 -0
  16. data/vendor/rake/README +285 -0
  17. data/vendor/rake/Rakefile +418 -0
  18. data/vendor/rake/TODO +20 -0
  19. data/vendor/rake/bin/rake +31 -0
  20. data/vendor/rake/doc/example/Rakefile1 +38 -0
  21. data/vendor/rake/doc/example/Rakefile2 +35 -0
  22. data/vendor/rake/doc/example/a.c +6 -0
  23. data/vendor/rake/doc/example/b.c +6 -0
  24. data/vendor/rake/doc/example/main.c +11 -0
  25. data/vendor/rake/doc/glossary.rdoc +51 -0
  26. data/vendor/rake/doc/jamis.rb +591 -0
  27. data/vendor/rake/doc/proto_rake.rdoc +127 -0
  28. data/vendor/rake/doc/rake.1.gz +0 -0
  29. data/vendor/rake/doc/rakefile.rdoc +534 -0
  30. data/vendor/rake/doc/rational.rdoc +151 -0
  31. data/vendor/rake/doc/release_notes/rake-0.4.14.rdoc +23 -0
  32. data/vendor/rake/doc/release_notes/rake-0.4.15.rdoc +35 -0
  33. data/vendor/rake/doc/release_notes/rake-0.5.0.rdoc +53 -0
  34. data/vendor/rake/doc/release_notes/rake-0.5.3.rdoc +78 -0
  35. data/vendor/rake/doc/release_notes/rake-0.5.4.rdoc +46 -0
  36. data/vendor/rake/doc/release_notes/rake-0.6.0.rdoc +141 -0
  37. data/vendor/rake/doc/release_notes/rake-0.7.0.rdoc +119 -0
  38. data/vendor/rake/doc/release_notes/rake-0.7.1.rdoc +59 -0
  39. data/vendor/rake/doc/release_notes/rake-0.7.2.rdoc +121 -0
  40. data/vendor/rake/doc/release_notes/rake-0.7.3.rdoc +47 -0
  41. data/vendor/rake/doc/release_notes/rake-0.8.0.rdoc +114 -0
  42. data/vendor/rake/doc/release_notes/rake-0.8.2.rdoc +165 -0
  43. data/vendor/rake/doc/release_notes/rake-0.8.3.rdoc +112 -0
  44. data/vendor/rake/install.rb +88 -0
  45. data/vendor/rake/lib/rake/classic_namespace.rb +8 -0
  46. data/vendor/rake/lib/rake/clean.rb +33 -0
  47. data/vendor/rake/lib/rake/contrib/compositepublisher.rb +24 -0
  48. data/vendor/rake/lib/rake/contrib/ftptools.rb +153 -0
  49. data/vendor/rake/lib/rake/contrib/publisher.rb +75 -0
  50. data/vendor/rake/lib/rake/contrib/rubyforgepublisher.rb +18 -0
  51. data/vendor/rake/lib/rake/contrib/sshpublisher.rb +47 -0
  52. data/vendor/rake/lib/rake/contrib/sys.rb +209 -0
  53. data/vendor/rake/lib/rake/gempackagetask.rb +103 -0
  54. data/vendor/rake/lib/rake/loaders/makefile.rb +35 -0
  55. data/vendor/rake/lib/rake/packagetask.rb +185 -0
  56. data/vendor/rake/lib/rake/rake_test_loader.rb +5 -0
  57. data/vendor/rake/lib/rake/rdoctask.rb +147 -0
  58. data/vendor/rake/lib/rake/ruby182_test_unit_fix.rb +23 -0
  59. data/vendor/rake/lib/rake/runtest.rb +23 -0
  60. data/vendor/rake/lib/rake/tasklib.rb +23 -0
  61. data/vendor/rake/lib/rake/testtask.rb +161 -0
  62. data/vendor/rake/lib/rake/win32.rb +54 -0
  63. data/vendor/rake/lib/rake.rb +2468 -0
  64. data/vendor/rake/test/capture_stdout.rb +26 -0
  65. data/vendor/rake/test/check_expansion.rb +5 -0
  66. data/vendor/rake/test/contrib/test_sys.rb +47 -0
  67. data/vendor/rake/test/data/chains/Rakefile +15 -0
  68. data/vendor/rake/test/data/default/Rakefile +19 -0
  69. data/vendor/rake/test/data/dryrun/Rakefile +22 -0
  70. data/vendor/rake/test/data/file_creation_task/Rakefile +33 -0
  71. data/vendor/rake/test/data/imports/Rakefile +19 -0
  72. data/vendor/rake/test/data/imports/deps.mf +1 -0
  73. data/vendor/rake/test/data/multidesc/Rakefile +17 -0
  74. data/vendor/rake/test/data/namespace/Rakefile +57 -0
  75. data/vendor/rake/test/data/rakelib/test1.rb +3 -0
  76. data/vendor/rake/test/data/rbext/rakefile.rb +3 -0
  77. data/vendor/rake/test/data/sample.mf +12 -0
  78. data/vendor/rake/test/data/statusreturn/Rakefile +8 -0
  79. data/vendor/rake/test/data/unittest/Rakefile +1 -0
  80. data/vendor/rake/test/filecreation.rb +32 -0
  81. data/vendor/rake/test/functional.rb +15 -0
  82. data/vendor/rake/test/in_environment.rb +30 -0
  83. data/vendor/rake/test/rake_test_setup.rb +10 -0
  84. data/vendor/rake/test/reqfile.rb +3 -0
  85. data/vendor/rake/test/reqfile2.rb +3 -0
  86. data/vendor/rake/test/session_functional.rb +337 -0
  87. data/vendor/rake/test/shellcommand.rb +3 -0
  88. data/vendor/rake/test/test_application.rb +694 -0
  89. data/vendor/rake/test/test_clean.rb +14 -0
  90. data/vendor/rake/test/test_definitions.rb +82 -0
  91. data/vendor/rake/test/test_earlytime.rb +35 -0
  92. data/vendor/rake/test/test_extension.rb +63 -0
  93. data/vendor/rake/test/test_file_creation_task.rb +62 -0
  94. data/vendor/rake/test/test_file_task.rb +139 -0
  95. data/vendor/rake/test/test_filelist.rb +618 -0
  96. data/vendor/rake/test/test_fileutils.rb +250 -0
  97. data/vendor/rake/test/test_ftp.rb +59 -0
  98. data/vendor/rake/test/test_invocation_chain.rb +75 -0
  99. data/vendor/rake/test/test_makefile_loader.rb +25 -0
  100. data/vendor/rake/test/test_multitask.rb +45 -0
  101. data/vendor/rake/test/test_namespace.rb +36 -0
  102. data/vendor/rake/test/test_package_task.rb +116 -0
  103. data/vendor/rake/test/test_pathmap.rb +209 -0
  104. data/vendor/rake/test/test_rake.rb +41 -0
  105. data/vendor/rake/test/test_require.rb +33 -0
  106. data/vendor/rake/test/test_rules.rb +347 -0
  107. data/vendor/rake/test/test_task_arguments.rb +89 -0
  108. data/vendor/rake/test/test_task_manager.rb +170 -0
  109. data/vendor/rake/test/test_tasklib.rb +12 -0
  110. data/vendor/rake/test/test_tasks.rb +371 -0
  111. data/vendor/rake/test/test_test_task.rb +75 -0
  112. data/vendor/rake/test/test_top_level_functions.rb +84 -0
  113. data/vendor/rake/test/test_win32.rb +57 -0
  114. metadata +195 -0
@@ -0,0 +1,534 @@
1
+ = Rakefile Format (as of version 0.8.2)
2
+
3
+ First of all, there is no special format for a Rakefile. A Rakefile
4
+ contains executable Ruby code. Anything legal in a ruby script is
5
+ allowed in a Rakefile.
6
+
7
+ Now that we understand there is no special syntax in a Rakefile, there
8
+ are some conventions that are used in a Rakefile that are a little
9
+ unusual in a typical Ruby program. Since a Rakefile is tailored to
10
+ specifying tasks and actions, the idioms used in a Rakefile are
11
+ designed to support that.
12
+
13
+ So, what goes into a Rakefile?
14
+
15
+ == Tasks
16
+
17
+ Tasks are the main unit of work in a Rakefile. Tasks have a name
18
+ (usually given as a symbol or a string), a list of prerequisites (more
19
+ symbols or strings) and a list of actions (given as a block).
20
+
21
+ === Simple Tasks
22
+
23
+ A task is declared by using the +task+ method. +task+ takes a single
24
+ parameter that is the name of the task.
25
+
26
+ task :name
27
+
28
+ === Tasks with Prerequisites
29
+
30
+ Any prerequisites are given as a list (inclosed in square brackets)
31
+ following the name and an arrow (=>).
32
+
33
+ task :name => [:prereq1, :prereq2]
34
+
35
+ <b>NOTE:</b> Although this syntax looks a little funky, it is legal
36
+ Ruby. We are constructing a hash where the key is :name and the value
37
+ for that key is the list of prerequisites. It is equivalent to the
38
+ following ...
39
+
40
+ hash = Hash.new
41
+ hash[:name] = [:prereq1, :prereq2]
42
+ task(hash)
43
+
44
+ === Tasks with Actions
45
+
46
+ Actions are defined by passing a block to the +task+ method. Any Ruby
47
+ code can be placed in the block. The block may reference the task
48
+ object via the block paramter..
49
+
50
+ task :name => [:prereq1, :prereq2] do |t|
51
+ # actions (may reference t)
52
+ end
53
+
54
+ === Multiple Definitions
55
+
56
+ A task may be specified more than once. Each specification adds its
57
+ prerequisites and actions to the existing definition. This allows one
58
+ part of a rakefile to specify the actions and a different rakefile
59
+ (perhaps separately generated) to specify the dependencies.
60
+
61
+ For example, the following is equivalent to the single task
62
+ specification given above.
63
+
64
+ task :name
65
+ task :name => [:prereq1]
66
+ task :name => [:prereq2]
67
+ task :name do |t|
68
+ # actions
69
+ end
70
+
71
+ == File Tasks
72
+
73
+ Some tasks are designed to create a file from one or more other files.
74
+ Tasks that generate these files may be skipped if the file already
75
+ exists. File tasks are used to specify file creation tasks.
76
+
77
+ File tasks are declared using the +file+ method (instead of the +task+
78
+ method). In addition, file tasks are usually named with a string
79
+ rather than a symbol.
80
+
81
+ The following file task creates a executable program (named +prog+)
82
+ given two object files name <tt>a.o</tt> and <tt>b.o</tt>. The tasks
83
+ for creating <tt>a.o</tt> and <tt>b.o</tt> are not shown.
84
+
85
+ file "prog" => ["a.o", "b.o"] do |t|
86
+ sh "cc -o #{t.name} #{t.prerequisites.join(' ')}"
87
+ end
88
+
89
+ == Directory Tasks
90
+
91
+ It is common to need to create directories upon demand. The
92
+ +directory+ convenience method is a short-hand for creating a FileTask
93
+ that creates the directory. For example, the following declaration
94
+ ...
95
+
96
+ directory "testdata/examples/doc"
97
+
98
+ is equivalent to ...
99
+
100
+ file "testdata" do |t| mkdir t.name end
101
+ file "testdata/examples" do |t| mkdir t.name end
102
+ file "testdata/examples/doc" do |t| mkdir t.name end
103
+
104
+ The +directory+ method does not accept prerequisites or actions, but
105
+ both prerequisites and actions can be added later. For example ...
106
+
107
+ directory "testdata"
108
+ file "testdata" => ["otherdata"]
109
+ file "testdata" do
110
+ cp Dir["standard_data/*.data"], "testdata"
111
+ end
112
+
113
+ == Tasks with Parallel Prerequisites
114
+
115
+ Rake allows parallel execution of prerequisites using the following syntax:
116
+
117
+ multitask :copy_files => [:copy_src, :copy_doc, :copy_bin] do
118
+ puts "All Copies Complete"
119
+ end
120
+
121
+ In this example, +copy_files+ is a normal rake task. Its actions are
122
+ executed whereever all of its prerequisites are done. The big
123
+ difference is that the prerequisites (+copy_src+, +copy_bin+ and
124
+ +copy_doc+) are executed in parallel. Each of the prerequisites are
125
+ run in their own Ruby thread, possibly allowing faster overall runtime.
126
+
127
+ === Secondary Prerequisites
128
+
129
+ If any of the primary prerequites of a multitask have common secondary
130
+ prerequisites, all of the primary/parallel prerequisites will wait
131
+ until the common prerequisites have been run.
132
+
133
+ For example, if the <tt>copy_<em>xxx</em></tt> tasks have the
134
+ following prerequisites:
135
+
136
+ task :copy_src => [:prep_for_copy]
137
+ task :copy_bin => [:prep_for_copy]
138
+ task :copy_doc => [:prep_for_copy]
139
+
140
+ Then the +prep_for_copy+ task is run before starting all the copies in
141
+ parallel. Once +prep_for_copy+ is complete, +copy_src+, +copy_bin+,
142
+ and +copy_doc+ are all run in parallel. Note that +prep_for_copy+ is
143
+ run only once, even though it is referenced in multiple threads.
144
+
145
+ === Thread Safety
146
+
147
+ The Rake internal data structures are thread-safe with respect
148
+ to the multitask parallel execution, so there is no need for the user
149
+ to do extra synchronization for Rake's benefit. However, if there are
150
+ user data structures shared between the parallel prerequisites, the
151
+ user must do whatever is necessary to prevent race conditions.
152
+
153
+ == Tasks with Arguments
154
+
155
+ Prior to version 0.8.0, rake was only able to handle command line
156
+ arguments of the form NAME=VALUE that were passed into Rake via the
157
+ ENV hash. Many folks had asked for some kind of simple command line
158
+ arguments, perhaps using "--" to separate regular task names from
159
+ argument values on the command line. The problem is that there was no
160
+ easy way to associate positional arguments on the command line with
161
+ different tasks. Suppose both tasks :a and :b expect a command line
162
+ argument: does the first value go with :a? What if :b is run first?
163
+ Should it then get the first command line argument.
164
+
165
+ Rake 0.8.0 solves this problem by explicitly passing values directly
166
+ to the tasks that need them. For example, if I had a release task
167
+ that required a version number, I could say:
168
+
169
+ rake release[0.8.2]
170
+
171
+ And the string "0.8.2" will be passed to the :release task. Multiple
172
+ arguments can be passed by separating them with a comma, for example:
173
+
174
+ rake name[john,doe]
175
+
176
+ Just a few words of caution. The rake task name and its arguments
177
+ need to be a single command line argument to rake. This generally
178
+ means no spaces. If spaces are needed, then the entire rake +
179
+ argument string should be quoted. Something like this:
180
+
181
+ rake "name[billy bob, smith]"
182
+
183
+ (Quoting rules vary between operating systems and shells, so make sure
184
+ you consult the proper docs for your OS/shell).
185
+
186
+ === Tasks that Expect Parameters
187
+
188
+ Parameters are only given to tasks that are setup to expect them. In
189
+ order to handle named parameters, the task declaration syntax for
190
+ tasks has been extended slightly.
191
+
192
+ For example, a task that needs a first name and last name might be
193
+ declared as:
194
+
195
+ task :name, [:first_name, :last_name]
196
+
197
+ The first argument is still the name of the task (:name in this case).
198
+ The next to argumements are the names of the parameters expected by
199
+ :name in an array (:first_name and :last_name in the example).
200
+
201
+ To access the values of the paramters, the block defining the task
202
+ behaviour can now accept a second parameter:
203
+
204
+ task :name, [:first_name, :last_name] do |t, args|
205
+ puts "First name is #{args.first_name}"
206
+ puts "Last name is #{args.last_name}"
207
+ end
208
+
209
+ The first argument of the block "t" is always bound to the current
210
+ task object. The second argument "args" is an open-struct like object
211
+ that allows access to the task arguments. Extra command line
212
+ arguments to a task are ignored. Missing command line arguments are
213
+ given the nil value.
214
+
215
+ If you wish to specify default values for the arguments, you can use
216
+ the with_defaults method in the task body. Here is the above example
217
+ where we specify default values for the first and last names:
218
+
219
+ task :name, [:first_name, :last_name] do |t, args|
220
+ args.with_defaults(:first_name => "John", :last_name => "Dough")
221
+ puts "First name is #{args.first_name}"
222
+ puts "Last name is #{args.last_name}"
223
+ end
224
+
225
+ === Tasks that Expect Parameters and Have Prerequisites
226
+
227
+ Tasks that use parameters have a slightly different format for
228
+ prerequisites. Use the <tt>:needs</tt> keyword to specify the
229
+ prerequisites for tasks with arguments. For example:
230
+
231
+ task :name, [:first_name, :last_name] => [:pre_name] do |t, args|
232
+ args.with_defaults(:first_name => "John", :last_name => "Dough")
233
+ puts "First name is #{args.first_name}"
234
+ puts "Last name is #{args.last_name}"
235
+ end
236
+
237
+ === Deprecated Task Parameters Format
238
+
239
+ There is an older format for declaring task parameters that omitted
240
+ the task array and used the :needs keyword to introduce the
241
+ dependencies. That format is still supported for compatibility, but
242
+ is not recommended for use.
243
+
244
+ == Accessing Task Programatically
245
+
246
+ Sometimes it is useful to manipulate tasks programatically in a
247
+ Rakefile. To find a task object, use the <tt>:[]</tt> operator on the
248
+ <tt>Rake::Task</tt>.
249
+
250
+ === Programmatic Task Example
251
+
252
+ For example, the following Rakefile defines two tasks. The :doit task
253
+ simply prints a simple "DONE" message. The :dont class will lookup
254
+ the doit class and remove (clear) all of its prerequisites and
255
+ actions.
256
+
257
+ task :doit do
258
+ puts "DONE"
259
+ end
260
+
261
+ task :dont do
262
+ Rake::Task[:doit].clear
263
+ end
264
+
265
+ Running this example:
266
+
267
+ $ rake doit
268
+ (in /Users/jim/working/git/rake/x)
269
+ DONE
270
+ $ rake dont doit
271
+ (in /Users/jim/working/git/rake/x)
272
+ $
273
+
274
+ The ability to programmatically manipulate tasks gives rake very
275
+ powerful meta-programming capabilities w.r.t. task execution, but
276
+ should be used with cation.
277
+
278
+ == Rules
279
+
280
+ When a file is named as a prerequisite, but does not have a file task
281
+ defined for it, Rake will attempt to synthesize a task by looking at a
282
+ list of rules supplied in the Rakefile.
283
+
284
+ Suppose we were trying to invoke task "mycode.o", but no task is
285
+ defined for it. But the rakefile has a rule that look like this ...
286
+
287
+ rule '.o' => ['.c'] do |t|
288
+ sh "cc #{t.source} -c -o #{t.name}"
289
+ end
290
+
291
+ This rule will synthesize any task that ends in ".o". It has a
292
+ prerequisite a source file with an extension of ".c" must exist. If
293
+ Rake is able to find a file named "mycode.c", it will automatically
294
+ create a task that builds "mycode.o" from "mycode.c".
295
+
296
+ If the file "mycode.c" does not exist, rake will attempt
297
+ to recursively synthesize a rule for it.
298
+
299
+ When a task is synthesized from a rule, the +source+ attribute of the
300
+ task is set to the matching source file. This allows us to write
301
+ rules with actions that reference the source file.
302
+
303
+ === Advanced Rules
304
+
305
+ Any regular expression may be used as the rule pattern. Additionally,
306
+ a proc may be used to calculate the name of the source file. This
307
+ allows for complex patterns and sources.
308
+
309
+ The following rule is equivalent to the example above.
310
+
311
+ rule( /\.o$/ => [
312
+ proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') }
313
+ ]) do |t|
314
+ sh "cc #{t.source} -c -o #{t.name}"
315
+ end
316
+
317
+ <b>NOTE:</b> Because of a _quirk_ in Ruby syntax, parenthesis are
318
+ required on *rule* when the first argument is a regular expression.
319
+
320
+ The following rule might be used for Java files ...
321
+
322
+ rule '.java' => [
323
+ proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') }
324
+ ] do |t|
325
+ java_compile(t.source, t.name)
326
+ end
327
+
328
+ <b>NOTE:</b> +java_compile+ is a hypothetical method that invokes the
329
+ java compiler.
330
+
331
+ == Importing Dependencies
332
+
333
+ Any ruby file (including other rakefiles) can be included with a
334
+ standard Ruby +require+ command. The rules and declarations in the
335
+ required file are just added to the definitions already accumulated.
336
+
337
+ Because the files are loaded _before_ the rake targets are evaluated,
338
+ the loaded files must be "ready to go" when the rake command is
339
+ invoked. This make generated dependency files difficult to use. By
340
+ the time rake gets around to updating the dependencies file, it is too
341
+ late to load it.
342
+
343
+ The +import+ command addresses this by specifying a file to be loaded
344
+ _after_ the main rakefile is loaded, but _before_ any targets on the
345
+ command line are specified. In addition, if the file name matches an
346
+ explicit task, that task is invoked before loading the file. This
347
+ allows dependency files to be generated and used in a single rake
348
+ command invocation.
349
+
350
+ === Example:
351
+
352
+ require 'rake/loaders/makefile'
353
+
354
+ file ".depends.mf" => [SRC_LIST] do |t|
355
+ sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}"
356
+ end
357
+
358
+ import ".depends.mf"
359
+
360
+ If ".depends" does not exist, or is out of date w.r.t. the source
361
+ files, a new ".depends" file is generated using +makedepend+ before
362
+ loading.
363
+
364
+ == Comments
365
+
366
+ Standard Ruby comments (beginning with "#") can be used anywhere it is
367
+ legal in Ruby source code, including comments for tasks and rules.
368
+ However, if you wish a task to be described using the "-T" switch,
369
+ then you need to use the +desc+ command to describe the task.
370
+
371
+ === Example:
372
+
373
+ desc "Create a distribution package"
374
+ task :package => [ ... ] do ... end
375
+
376
+ The "-T" switch (or "--tasks" if you like to spell things out) will
377
+ display a list of tasks that have a defined comment. If you use
378
+ +desc+ to describe your major tasks, you have a semi-automatic way of
379
+ generating a summary of your Rake file.
380
+
381
+ traken$ rake -T
382
+ (in /home/.../rake)
383
+ rake clean # Remove any temporary products.
384
+ rake clobber # Remove any generated file.
385
+ rake clobber_rdoc # Remove rdoc products
386
+ rake contrib_test # Run tests for contrib_test
387
+ rake default # Default Task
388
+ rake install # Install the application
389
+ rake lines # Count lines in the main rake file
390
+ rake rdoc # Build the rdoc HTML Files
391
+ rake rerdoc # Force a rebuild of the RDOC files
392
+ rake test # Run tests
393
+ rake testall # Run all test targets
394
+
395
+ Only tasks with descriptions will be displayed with the "-T" switch.
396
+ Use "-P" (or "--prereqs") to get a list of all tasks and their
397
+ prerequisites.
398
+
399
+ == Namespaces
400
+
401
+ As projects grow (and along with it, the number of tasks), it is
402
+ common for task names to begin to clash. For example, if you might
403
+ have a main program and a set of sample programs built by a single
404
+ Rakefile. By placing the tasks related to the main program in one
405
+ namespace, and the tasks for building the sample programs in a
406
+ different namespace, the task names will not will not interfer with
407
+ each other.
408
+
409
+ For example:
410
+
411
+ namespace "main"
412
+ task :build do
413
+ # Build the main program
414
+ end
415
+ end
416
+
417
+ namespace "samples" do
418
+ task :build do
419
+ # Build the sample programs
420
+ end
421
+ end
422
+
423
+ task :build => ["main:build", "samples:build"]
424
+
425
+ Referencing a task in a separate namespace can be achieved by
426
+ prefixing the task name with the namespace and a colon
427
+ (e.g. "main:build" refers to the :build task in the +main+ namespace).
428
+ Nested namespaces are supported, so
429
+
430
+ Note that the name given in the +task+ command is always the unadorned
431
+ task name without any namespace prefixes. The +task+ command always
432
+ defines a task in the current namespace.
433
+
434
+ === FileTasks
435
+
436
+ File task names are not scoped by the namespace command. Since the
437
+ name of a file task is the name of an actual file in the file system,
438
+ it makes little sense to include file task names in name space.
439
+ Directory tasks (created by the +directory+ command) are a type of
440
+ file task and are also not affected by namespaces.
441
+
442
+ === Name Resolution
443
+
444
+ When looking up a task name, rake will start with the current
445
+ namespace and attempt to find the name there. If it fails to find a
446
+ name in the current namespace, it will search the parent namespaces
447
+ until a match is found (or an error occurs if there is no match).
448
+
449
+ The "rake" namespace is a special implicit namespace that refers to
450
+ the toplevel names.
451
+
452
+ If a task name begins with a "^" character, the name resolution will
453
+ start in the parent namespace. Multiple "^" characters are allowed.
454
+
455
+ Here is an example file with multiple :run tasks and how various names
456
+ resolve in different locations.
457
+
458
+ task :run
459
+
460
+ namespace "one" do
461
+ task :run
462
+
463
+ namespace "two" do
464
+ task :run
465
+
466
+ # :run => "one:two:run"
467
+ # "two:run" => "one:two:run"
468
+ # "one:two:run" => "one:two:run"
469
+ # "one:run" => "one:run"
470
+ # "^run" => "one:run"
471
+ # "^^run" => "rake:run" (the top level task)
472
+ # "rake:run" => "rake:run" (the top level task)
473
+ end
474
+
475
+ # :run => "one:run"
476
+ # "two:run" => "one:two:run"
477
+ # "^run" => "rake:run"
478
+ end
479
+
480
+ # :run => "rake:run"
481
+ # "one:run" => "one:run"
482
+ # "one:two:run" => "one:two:run"
483
+
484
+ == FileLists
485
+
486
+ FileLists are the way Rake manages lists of files. You can treat a
487
+ FileList as an array of strings for the most part, but FileLists
488
+ support some additional operations.
489
+
490
+ === Creating a FileList
491
+
492
+ Creating a file list is easy. Just give it the list of file names:
493
+
494
+ fl = FileList['file1.rb', file2.rb']
495
+
496
+ Or give it a glob pattern:
497
+
498
+ fl = FileList['*.rb']
499
+
500
+ == Odds and Ends
501
+
502
+ === do/end verses { }
503
+
504
+ Blocks may be specified with either a +do+/+end+ pair, or with curly
505
+ braces in Ruby. We _strongly_ recommend using +do+/+end+ to specify the
506
+ actions for tasks and rules. Because the rakefile idiom tends to
507
+ leave off parenthesis on the task/file/rule methods, unusual
508
+ ambiguities can arise when using curly braces.
509
+
510
+ For example, suppose that the method +object_files+ returns a list of
511
+ object files in a project. Now we use +object_files+ as the
512
+ prerequistes in a rule specified with actions in curly braces.
513
+
514
+ # DON'T DO THIS!
515
+ file "prog" => object_files {
516
+ # Actions are expected here (but it doesn't work)!
517
+ }
518
+
519
+ Because curly braces have a higher precedence than +do+/+end+, the
520
+ block is associated with the +object_files+ method rather than the
521
+ +file+ method.
522
+
523
+ This is the proper way to specify the task ...
524
+
525
+ # THIS IS FINE
526
+ file "prog" => object_files do
527
+ # Actions go here
528
+ end
529
+
530
+ ----
531
+
532
+ == See
533
+
534
+ * README -- Main documentation for Rake.
@@ -0,0 +1,151 @@
1
+ = Why rake?
2
+
3
+ Ok, let me state from the beginning that I never intended to write this
4
+ code. I'm not convinced it is useful, and I'm not convinced anyone
5
+ would even be interested in it. All I can say is that Why's onion truck
6
+ must by been passing through the Ohio valley.
7
+
8
+ What am I talking about? ... A Ruby version of Make.
9
+
10
+ See, I can sense you cringing already, and I agree. The world certainly
11
+ doesn't need yet another reworking of the "make" program. I mean, we
12
+ already have "ant". Isn't that enough?
13
+
14
+ It started yesterday. I was helping a coworker fix a problem in one of
15
+ the Makefiles we use in our project. Not a particularly tough problem,
16
+ but during the course of the conversation I began lamenting some of the
17
+ shortcomings of make. In particular, in one of my makefiles I wanted to
18
+ determine the name of a file dynamically and had to resort to some
19
+ simple scripting (in Ruby) to make it work. "Wouldn't it be nice if you
20
+ could just use Ruby inside a Makefile" I said.
21
+
22
+ My coworker (a recent convert to Ruby) agreed, but wondered what it
23
+ would look like. So I sketched the following on the whiteboard...
24
+
25
+ "What if you could specify the make tasks in Ruby, like this ..."
26
+
27
+ task "build" do
28
+ java_compile(...args, etc ...)
29
+ end
30
+
31
+ "The task function would register "build" as a target to be made,
32
+ and the block would be the action executed whenever the build
33
+ system determined that it was time to do the build target."
34
+
35
+ We agreed that would be cool, but writing make from scratch would be WAY
36
+ too much work. And that was the end of that!
37
+
38
+ ... Except I couldn't get the thought out of my head. What exactly
39
+ would be needed to make the about syntax work as a make file? Hmmm, you
40
+ would need to register the tasks, you need some way of specifying
41
+ dependencies between tasks, and some way of kicking off the process.
42
+ Hey! What if we did ... and fifteen minutes later I had a working
43
+ prototype of Ruby make, complete with dependencies and actions.
44
+
45
+ I showed the code to my coworker and we had a good laugh. It was just
46
+ about a page worth of code that reproduced an amazing amount of the
47
+ functionality of make. We were both truely stunned with the power of
48
+ Ruby.
49
+
50
+ But it didn't do everything make did. In particular, it didn't have
51
+ timestamp based file dependencies (where a file is rebuilt if any of its
52
+ prerequisite files have a later timestamp). Obviously THAT would be a
53
+ pain to add and so Ruby Make would remain an interesting experiment.
54
+
55
+ ... Except as I walked back to my desk, I started thinking about what
56
+ file based dependecies would really need. Rats! I was hooked again,
57
+ and by adding a new class and two new methods, file/timestamp
58
+ dependencies were implemented.
59
+
60
+ Ok, now I was really hooked. Last night (during CSI!) I massaged the
61
+ code and cleaned it up a bit. The result is a bare-bones replacement
62
+ for make in exactly 100 lines of code.
63
+
64
+ For the curious, you can see it at ...
65
+ * doc/proto_rake.rdoc
66
+
67
+ Oh, about the name. When I wrote the example Ruby Make task on my
68
+ whiteboard, my coworker exclaimed "Oh! I have the perfect name: Rake ...
69
+ Get it? Ruby-Make. Rake!" He said he envisioned the tasks as leaves
70
+ and Rake would clean them up ... or something like that. Anyways, the
71
+ name stuck.
72
+
73
+ Some quick examples ...
74
+
75
+ A simple task to delete backup files ...
76
+
77
+ task :clean do
78
+ Dir['*~'].each {|fn| rm fn rescue nil}
79
+ end
80
+
81
+ Note that task names are symbols (they are slightly easier to type
82
+ than quoted strings ... but you may use quoted string if you would
83
+ rather). Rake makes the methods of the FileUtils module directly
84
+ available, so we take advantage of the <tt>rm</tt> command. Also note
85
+ the use of "rescue nil" to trap and ignore errors in the <tt>rm</tt>
86
+ command.
87
+
88
+ To run it, just type "rake clean". Rake will automatically find a
89
+ Rakefile in the current directory (or above!) and will invoke the
90
+ targets named on the command line. If there are no targets explicitly
91
+ named, rake will invoke the task "default".
92
+
93
+ Here's another task with dependencies ...
94
+
95
+ task :clobber => [:clean] do
96
+ rm_r "tempdir"
97
+ end
98
+
99
+ Task :clobber depends upon task :clean, so :clean will be run before
100
+ :clobber is executed.
101
+
102
+ Files are specified by using the "file" command. It is similar to the
103
+ task command, except that the task name represents a file, and the task
104
+ will be run only if the file doesn't exist, or if its modification time
105
+ is earlier than any of its prerequisites.
106
+
107
+ Here is a file based dependency that will compile "hello.cc" to
108
+ "hello.o".
109
+
110
+ file "hello.cc"
111
+ file "hello.o" => ["hello.cc"] do |t|
112
+ srcfile = t.name.sub(/\.o$/, ".cc")
113
+ sh %{g++ #{srcfile} -c -o #{t.name}}
114
+ end
115
+
116
+ I normally specify file tasks with string (rather than symbols). Some
117
+ file names can't be represented by symbols. Plus it makes the
118
+ distinction between them more clear to the casual reader.
119
+
120
+ Currently writing a task for each and every file in the project would be
121
+ tedious at best. I envision a set of libraries to make this job
122
+ easier. For instance, perhaps something like this ...
123
+
124
+ require 'rake/ctools'
125
+ Dir['*.c'].each do |fn|
126
+ c_source_file(fn)
127
+ end
128
+
129
+ where "c_source_file" will create all the tasks need to compile all the
130
+ C source files in a directory. Any number of useful libraries could be
131
+ created for rake.
132
+
133
+ That's it. There's no documentation (other than whats in this
134
+ message). Does this sound interesting to anyone? If so, I'll continue
135
+ to clean it up and write it up and publish it on RAA. Otherwise, I'll
136
+ leave it as an interesting excerise and a tribute to the power of Ruby.
137
+
138
+ Why /might/ rake be interesting to Ruby programmers. I don't know,
139
+ perhaps ...
140
+
141
+ * No weird make syntax (only weird Ruby syntax :-)
142
+ * No need to edit or read XML (a la ant)
143
+ * Platform independent build scripts.
144
+ * Will run anywhere Ruby exists, so no need to have "make" installed.
145
+ If you stay away from the "sys" command and use things like
146
+ 'ftools', you can have a perfectly platform independent
147
+ build script. Also rake is only 100 lines of code, so it can
148
+ easily be packaged along with the rest of your code.
149
+
150
+ So ... Sorry for the long rambling message. Like I said, I never
151
+ intended to write this code at all.