rake 0.4.8

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rake might be problematic. Click here for more details.

data/TODO ADDED
@@ -0,0 +1,19 @@
1
+ = Rake Project -- To Do List
2
+
3
+ Send suggestions for this list to mailto:jim@weirichhouse.org or on
4
+ the rake-devel@rubyforge.org mailing list.
5
+
6
+ === To Do
7
+ * Provide a way to disable -w warning mode.
8
+ * Define a set of default rules that work in the absense of any Rakefile
9
+ * What about cyclic dependencies?
10
+ * Java support utilities
11
+ * Installation support utilities
12
+ * Check out installpkg.rb
13
+ * Autogenerate Dependencies
14
+ * Rules should apply to existing tasks if no actions are defined.
15
+ * How to create multiple package tasks without task name collision?
16
+ * Trap "ln -s" commands that fail and use "cp" instead (SMB mounted
17
+ drives have problems with "ln -s".
18
+
19
+ (moved DONE list to CHANGES file)
@@ -0,0 +1,8 @@
1
+ begin
2
+ require 'rake'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require_gem 'rake'
6
+ end
7
+ RakeApp.new.run
8
+
@@ -0,0 +1,38 @@
1
+ # Example Rakefile -*- ruby -*-
2
+
3
+ task :default => [:main]
4
+
5
+ file "a.o" => ["a.c"] do |t|
6
+ src = t.name.sub(/\.o$/, '.c')
7
+ sh "gcc #{src} -c -o #{t.name}"
8
+ end
9
+
10
+ file "b.o" => ["b.c"] do |t|
11
+ src = t.name.sub(/\.o$/, '.c')
12
+ sh "gcc #{src} -c -o #{t.name}"
13
+ end
14
+
15
+ file "main.o" => ["main.c"] do |t|
16
+ src = t.name.sub(/\.o$/, '.c')
17
+ sh "gcc #{src} -c -o #{t.name}"
18
+ end
19
+
20
+ OBJFILES = ["a.o", "b.o", "main.o"]
21
+ task :obj => OBJFILES
22
+
23
+ file "main" => OBJFILES do |t|
24
+ sh "gcc -o #{t.name} main.o a.o b.o"
25
+ end
26
+
27
+ task :clean do
28
+ rm_f FileList['*.o']
29
+ Dir['*~'].each { |fn| rm_f fn }
30
+ end
31
+
32
+ task :clobber => [:clean] do
33
+ rm_f "main"
34
+ end
35
+
36
+ task :run => ["main"] do
37
+ sh "./main"
38
+ end
@@ -0,0 +1,35 @@
1
+ # Example Rakefile -*- ruby -*-
2
+ # Using the power of Ruby
3
+
4
+ task :default => [:main]
5
+
6
+ def ext(fn, newext)
7
+ fn.sub(/\.[^.]+$/, newext)
8
+ end
9
+
10
+ SRCFILES = Dir['*.c']
11
+ OBJFILES = SRCFILES.collect { |fn| ext(fn,".o") }
12
+
13
+ OBJFILES.each do |objfile|
14
+ srcfile = ext(objfile, ".c")
15
+ file objfile => [srcfile] do |t|
16
+ sh "gcc #{srcfile} -c -o #{t.name}"
17
+ end
18
+ end
19
+
20
+ file "main" => OBJFILES do |t|
21
+ sh "gcc -o #{t.name} main.o a.o b.o"
22
+ end
23
+
24
+ task :clean do
25
+ rm_f FileList['*.o']
26
+ Dir['*~'].each { |fn| rm_f fn }
27
+ end
28
+
29
+ task :clobber => [:clean] do
30
+ rm_f "main"
31
+ end
32
+
33
+ task :run => ["main"] do
34
+ sh "./main"
35
+ end
@@ -0,0 +1,6 @@
1
+ #include <stdio.h>
2
+
3
+ void a()
4
+ {
5
+ printf ("In function a\n");
6
+ }
@@ -0,0 +1,6 @@
1
+ #include <stdio.h>
2
+
3
+ void b()
4
+ {
5
+ printf ("In function b\n");
6
+ }
@@ -0,0 +1,11 @@
1
+ #include <stdio.h>
2
+
3
+ extern void a();
4
+ extern void b();
5
+
6
+ int main ()
7
+ {
8
+ a();
9
+ b();
10
+ return 0;
11
+ }
@@ -0,0 +1,51 @@
1
+ = Glossary
2
+
3
+ [<b>action</b>]
4
+ Code to be executed in order to perform a task. Actions in a
5
+ rakefile are specified in a code block (usually delimited by
6
+ +do+/+end+ pairs.
7
+
8
+ [<b>execute</b>]
9
+ When a task is executed, all of its actions are performed, in
10
+ the order they were defined. Note that unlike
11
+ <tt>invoke</tt>, <tt>execute</tt> always executes the actions
12
+ (without invoking or executing the prerequisites).
13
+
14
+ [<b>file task</b> (FileTask)]
15
+ A file task is a task whose purpose is to create a file
16
+ (which has the same name as the task). When invoked, a file
17
+ task will only execute if one or more of the following
18
+ conditions are true.
19
+
20
+ 1. The associated file does not exist.
21
+ 2. A prerequisite has a later time stamp than the existing file.
22
+
23
+ Because normal Tasks always have the current time as
24
+ timestamp, a FileTask that has a normal Task prerequisite
25
+ will always execute.
26
+
27
+ [<b>invoke</b>]
28
+ When a task is invoked, first we check to see if it has been
29
+ invoked before. if it has been, then nothing else is done.
30
+ If this is the first time its been invoked, then we invoke
31
+ each of its prerequisites. Finally, we check to see if we
32
+ need to execute the actions of this task by calling
33
+ <tt>needed?</tt>. Finally, if the task is needed, we execute
34
+ its actions.
35
+
36
+ NOTE: Currently prerequisites are invoked even if the task is
37
+ not needed. This may change in the future.
38
+
39
+ [<b>prerequisites</b>]
40
+ Every task has a set (possiblity empty) of prerequisites. A
41
+ prerequisite P to Task T is itself a task that must be invoked
42
+ before Task T.
43
+
44
+ [<b>rule</b>]
45
+ A rule is a recipe for synthesizing a task when no task is
46
+ explicitly defined. Rules generally synthesize file tasks.
47
+
48
+ [<b>task</b> (Task)]
49
+ Basic unit of work in a rakefile. A task has a name, a set of
50
+ prerequisites and a list of actions to be performed.
51
+
@@ -0,0 +1,127 @@
1
+ = Original Prototype Rake
2
+
3
+ This is the original 100 line prototype rake program.
4
+
5
+ ---
6
+ #!/usr/bin/env ruby
7
+
8
+ require 'ftools'
9
+
10
+ class Task
11
+ TASKS = Hash.new
12
+
13
+ attr_reader :prerequisites
14
+
15
+ def initialize(task_name)
16
+ @name = task_name
17
+ @prerequisites = []
18
+ @actions = []
19
+ end
20
+
21
+ def enhance(deps=nil, &block)
22
+ @prerequisites |= deps if deps
23
+ @actions << block if block_given?
24
+ self
25
+ end
26
+
27
+ def name
28
+ @name.to_s
29
+ end
30
+
31
+ def invoke
32
+ @prerequisites.each { |n| Task[n].invoke }
33
+ execute if needed?
34
+ end
35
+
36
+ def execute
37
+ return if @triggered
38
+ @triggered = true
39
+ @actions.collect { |act| result = act.call(self) }.last
40
+ end
41
+
42
+ def needed?
43
+ true
44
+ end
45
+
46
+ def timestamp
47
+ Time.now
48
+ end
49
+
50
+ class << self
51
+ def [](task_name)
52
+ TASKS[intern(task_name)] or fail "Don't know how to rake #{task_name}"
53
+ end
54
+
55
+ def define_task(args, &block)
56
+ case args
57
+ when Hash
58
+ fail "Too Many Target Names: #{args.keys.join(' ')}" if args.size > 1
59
+ fail "No Task Name Given" if args.size < 1
60
+ task_name = args.keys[0]
61
+ deps = args[task_name]
62
+ else
63
+ task_name = args
64
+ deps = []
65
+ end
66
+ deps = deps.collect {|d| intern(d) }
67
+ get(task_name).enhance(deps, &block)
68
+ end
69
+
70
+ def get(task_name)
71
+ name = intern(task_name)
72
+ TASKS[name] ||= self.new(name)
73
+ end
74
+
75
+ def intern(task_name)
76
+ (Symbol === task_name) ? task_name : task_name.intern
77
+ end
78
+ end
79
+ end
80
+
81
+ class FileTask < Task
82
+ def needed?
83
+ return true unless File.exist?(name)
84
+ latest_prereq = @prerequisites.collect{|n| Task[n].timestamp}.max
85
+ return false if latest_prereq.nil?
86
+ timestamp < latest_prereq
87
+ end
88
+
89
+ def timestamp
90
+ File.new(name.to_s).mtime
91
+ end
92
+ end
93
+
94
+ def task(args, &block)
95
+ Task.define_task(args, &block)
96
+ end
97
+
98
+ def file(args, &block)
99
+ FileTask.define_task(args, &block)
100
+ end
101
+
102
+ def sys(cmd)
103
+ puts cmd
104
+ system(cmd) or fail "Command Failed: [#{cmd}]"
105
+ end
106
+
107
+ def rake
108
+ begin
109
+ here = Dir.pwd
110
+ while ! File.exist?("Rakefile")
111
+ Dir.chdir("..")
112
+ fail "No Rakefile found" if Dir.pwd == here
113
+ here = Dir.pwd
114
+ end
115
+ puts "(in #{Dir.pwd})"
116
+ load "./Rakefile"
117
+ ARGV.push("default") if ARGV.size == 0
118
+ ARGV.each { |task_name| Task[task_name].invoke }
119
+ rescue Exception => ex
120
+ puts "rake aborted ... #{ex.message}"
121
+ puts ex.backtrace.find {|str| str =~ /Rakefile/ } || ""
122
+ end
123
+ end
124
+
125
+ if __FILE__ == $0 then
126
+ rake
127
+ end
@@ -0,0 +1,234 @@
1
+ = Rakefile Format
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
+ == Rules
114
+
115
+ When a file is named as a prerequisite, but does not have a file task
116
+ defined for it, Rake will attempt to synthesize a task by looking at a
117
+ list of rules supplied in the Rakefile.
118
+
119
+ Suppose we were trying to invoke task "mycode.o", but no task is
120
+ defined for it. But the rakefile has a rule that look like this ...
121
+
122
+ rule '.o' => ['.c'] do |t|
123
+ sh "cc #{t.source} -c -o #{t.name}"
124
+ end
125
+
126
+ This rule will synthesize any task that ends in ".o". It has a
127
+ prerequisite a source file with an extension of ".c" must exist. If
128
+ Rake is able to find a file named "mycode.c", it will automatically
129
+ create a task that builds "mycode.o" from "mycode.c".
130
+
131
+ Notice that the source file "mycode.c" must exist. Rake does not
132
+ (currently) try to do multi-level task synthesis.
133
+
134
+ When a task is synthesized from a rule, the +source+ attribute of the
135
+ task is set to the matching source file. This allows us to write
136
+ rules with actions that reference the source file.
137
+
138
+ === Advanced Rules
139
+
140
+ Any regular expression may be used as the rule pattern. Additionally,
141
+ a proc may be used to calculate the name of the source file. This
142
+ allows for complex patterns and sources.
143
+
144
+ The following rule is equivalent to the example above.
145
+
146
+ rule( /\.o$/ => [
147
+ proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') }
148
+ ]) do |t|
149
+ sh "cc #{t.source} -c -o #{t.name}"
150
+ end
151
+
152
+ <b>NOTE:</b> Because of a _quirk_ in Ruby syntax, parenthesis are
153
+ required on *rule* when the first argument is a regular expression.
154
+
155
+ The following rule might be used for Java files ...
156
+
157
+ rule '.java' => [
158
+ proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') }
159
+ ] do |t|
160
+ java_compile(t.source, t.name)
161
+ end
162
+
163
+ <b>NOTE:</b> +java_compile+ is a hypothetical method that invokes the
164
+ java compiler.
165
+
166
+ == Comments
167
+
168
+ Standard Ruby comments (beginning with "#") can be used anywhere it is
169
+ legal in Ruby source code, including comments for tasks and rules.
170
+ However, if you wish a task to be described using the "-T" switch,
171
+ then you need to use the +desc+ command to describe the task.
172
+
173
+ Example:
174
+
175
+ desc "Create a distribution package"
176
+ task :package => [ ... ] do ... end
177
+
178
+ The "-T" switch (or "--tasks" if you like to spell things out) will
179
+ display a list of tasks that have a defined comment. If you use
180
+ +desc+ to describe your major tasks, you have a semi-automatic way of
181
+ generating a summary of your Rake file.
182
+
183
+ traken$ rake -T
184
+ (in /home/.../rake)
185
+ rake clean # Remove any temporary products.
186
+ rake clobber # Remove any generated file.
187
+ rake clobber_rdoc # Remove rdoc products
188
+ rake contrib_test # Run tests for contrib_test
189
+ rake default # Default Task
190
+ rake install # Install the application
191
+ rake lines # Count lines in the main rake file
192
+ rake rdoc # Build the rdoc HTML Files
193
+ rake rerdoc # Force a rebuild of the RDOC files
194
+ rake test # Run tests
195
+ rake testall # Run all test targets
196
+
197
+ Only tasks with descriptions will be displayed with the "-T" switch.
198
+ Use "-P" (or "--prereqs") to get a list of all tasks and their
199
+ prerequisites.
200
+
201
+ == Odds and Ends
202
+
203
+ === do/end verses { }
204
+
205
+ Blocks may be specified with either a +do+/+end+ pair, or with curly
206
+ braces in Ruby. We _strongly_ recommend using +do+/+end+ to specify the
207
+ actions for tasks and rules. Because the rakefile idiom tends to
208
+ leave off parenthesis on the task/file/rule methods, unusual
209
+ ambiguities can arise when using curly braces.
210
+
211
+ For example, suppose that the method +object_files+ returns a list of
212
+ object files in a project. Now we use +object_files+ as the
213
+ prerequistes in a rule specified with actions in curly braces.
214
+
215
+ # DON'T DO THIS!
216
+ file "prog" => object_files {
217
+ # Actions are expected here (but it doesn't work)!
218
+ }
219
+
220
+ Because curly braces have a higher precedence than +do+/+end+, the
221
+ block is associated with the +object_files+ method rather than the
222
+ +file+ method.
223
+
224
+ This is the proper way to specify the task ...
225
+
226
+ # THIS IS FINE
227
+ file "prog" => object_files do
228
+ # Actions go here
229
+ end
230
+
231
+ ----
232
+ == See
233
+
234
+ * README -- Main documentation for Rake.