This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
= Rake Command Line Usage
|
||||
|
||||
Rake is invoked from the command line using:
|
||||
|
||||
% rake [options ...] [VAR=VALUE ...] [targets ...]
|
||||
|
||||
Options are:
|
||||
|
||||
[<tt><em>name</em>=<em>value</em></tt>]
|
||||
Set the environment variable <em>name</em> to <em>value</em>
|
||||
during the execution of the <b>rake</b> command. You can access
|
||||
the value by using ENV['<em>name</em>'].
|
||||
|
||||
[<tt>--all</tt> (-A)]
|
||||
Used in combination with the -T and -D options, will force
|
||||
those options to show all the tasks, even the ones without comments.
|
||||
|
||||
[<tt>--backtrace</tt>{=_output_} (-n)]
|
||||
Enable a full backtrace (i.e. like --trace, but without the task
|
||||
tracing details). The _output_ parameter is optional, but if
|
||||
specified it controls where the backtrace output is sent. If
|
||||
_output_ is <tt>stdout</tt>, then backtrace output is directed to
|
||||
standard output. If _output_ is <tt>stderr</tt>, or if it is
|
||||
missing, then the backtrace output is sent to standard error.
|
||||
|
||||
[<tt>--comments</tt>]
|
||||
Used in combination with the -W options to force the output to
|
||||
contain commented options only. This is the reverse of
|
||||
<tt>--all</tt>.
|
||||
|
||||
[<tt>--describe</tt> _pattern_ (-D)]
|
||||
Describe the tasks (matching optional PATTERN), then exit.
|
||||
|
||||
[<tt>--dry-run</tt> (-n)]
|
||||
Do a dry run. Print the tasks invoked and executed, but do not
|
||||
actually execute any of the actions.
|
||||
|
||||
[<tt>--execute</tt> _code_ (-e)]
|
||||
Execute some Ruby code and exit.
|
||||
|
||||
[<tt>--execute-print</tt> _code_ (-p)]
|
||||
Execute some Ruby code, print the result, and exit.
|
||||
|
||||
[<tt>--execute-continue</tt> _code_ (-E)]
|
||||
Execute some Ruby code, then continue with normal task processing.
|
||||
|
||||
[<tt>--help</tt> (-H)]
|
||||
Display some help text and exit.
|
||||
|
||||
[<tt>--jobs</tt> _number_ (-j)]
|
||||
|
||||
Specifies the maximum number of concurrent threads allowed. Rake
|
||||
will allocate threads as needed up to this maximum number.
|
||||
|
||||
If omitted, Rake will attempt to estimate the number of CPUs on
|
||||
the system and add 4 to that number.
|
||||
|
||||
The concurrent threads are used to execute the <tt>multitask</tt>
|
||||
prerequisites. Also see the <tt>-m</tt> option which turns all
|
||||
tasks into multitasks.
|
||||
|
||||
Sample values:
|
||||
(no -j) : Allow up to (# of CPUs + 4) number of threads
|
||||
--jobs : Allow unlimited number of threads
|
||||
--jobs=1 : Allow only one thread (the main thread)
|
||||
--jobs=16 : Allow up to 16 concurrent threads
|
||||
|
||||
[<tt>--job-stats</tt> _level_]
|
||||
|
||||
Display job statistics at the completion of the run. By default,
|
||||
this will display the requested number of active threads (from the
|
||||
-j options) and the maximum number of threads in play at any given
|
||||
time.
|
||||
|
||||
If the optional _level_ is <tt>history</tt>, then a complete trace
|
||||
of task history will be displayed on standard output.
|
||||
|
||||
[<tt>--libdir</tt> _directory_ (-I)]
|
||||
Add _directory_ to the list of directories searched for require.
|
||||
|
||||
[<tt>--multitask</tt> (-m)]
|
||||
Treat all tasks as multitasks. ('make/drake' semantics)
|
||||
|
||||
[<tt>--nosearch</tt> (-N)]
|
||||
Do not search for a Rakefile in parent directories.
|
||||
|
||||
[<tt>--prereqs</tt> (-P)]
|
||||
Display a list of all tasks and their immediate prerequisites.
|
||||
|
||||
[<tt>--quiet</tt> (-q)]
|
||||
Do not echo commands from FileUtils.
|
||||
|
||||
[<tt>--rakefile</tt> _filename_ (-f)]
|
||||
Use _filename_ as the name of the rakefile. The default rakefile
|
||||
names are +rakefile+ and +Rakefile+ (with +rakefile+ taking
|
||||
precedence). If the rakefile is not found in the current
|
||||
directory, +rake+ will search parent directories for a match. The
|
||||
directory where the Rakefile is found will become the current
|
||||
directory for the actions executed in the Rakefile.
|
||||
|
||||
[<tt>--rakelibdir</tt> _rakelibdir_ (-R)]
|
||||
Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')
|
||||
|
||||
[<tt>--require</tt> _name_ (-r)]
|
||||
Require _name_ before executing the Rakefile.
|
||||
|
||||
[<tt>--rules</tt>]
|
||||
Trace the rules resolution.
|
||||
|
||||
[<tt>--silent (-s)</tt>]
|
||||
Like --quiet, but also suppresses the 'in directory' announcement.
|
||||
|
||||
[<tt>--suppress-backtrace _pattern_ </tt>]
|
||||
Line matching the regular expression _pattern_ will be removed
|
||||
from the backtrace output. Note that the --backtrace option is the
|
||||
full backtrace without these lines suppressed.
|
||||
|
||||
[<tt>--system</tt> (-g)]
|
||||
Use the system wide (global) rakefiles. The project Rakefile is
|
||||
ignored. By default, the system wide rakefiles are used only if no
|
||||
project Rakefile is found. On Unix-like system, the system wide
|
||||
rake files are located in $HOME/.rake. On a windows system they
|
||||
are stored in $APPDATA/Rake.
|
||||
|
||||
[<tt>--no-system</tt> (-G)]
|
||||
Use the project level Rakefile, ignoring the system-wide (global)
|
||||
rakefiles.
|
||||
|
||||
[<tt>--tasks</tt> <em>pattern</em> (-T)]
|
||||
Display a list of the major tasks and their comments. Comments
|
||||
are defined using the "desc" command. If a pattern is given, then
|
||||
only tasks matching the pattern are displayed.
|
||||
|
||||
[<tt>--trace</tt>{=_output_} (-t)]
|
||||
Turn on invoke/execute tracing. Also enable full backtrace on
|
||||
errors. The _output_ parameter is optional, but if specified it
|
||||
controls where the trace output is sent. If _output_ is
|
||||
<tt>stdout</tt>, then trace output is directed to standard output.
|
||||
If _output_ is <tt>stderr</tt>, or if it is missing, then trace
|
||||
output is sent to standard error.
|
||||
|
||||
[<tt>--verbose</tt> (-v)]
|
||||
Echo the Sys commands to standard output.
|
||||
|
||||
[<tt>--version</tt> (-V)]
|
||||
Display the program version and exit.
|
||||
|
||||
[<tt>--where</tt> <em>pattern</em> (-W)]
|
||||
Display tasks that match <em>pattern</em> and the file and line
|
||||
number where the task is defined. By default this option will
|
||||
display all tasks, not just the tasks that have descriptions.
|
||||
|
||||
[<tt>--no-deprecation-warnings</tt> (-X)]
|
||||
Do not display the deprecation warnings.
|
||||
|
||||
In addition, any command line option of the form
|
||||
<em>VAR</em>=<em>VALUE</em> will be added to the environment hash
|
||||
<tt>ENV</tt> and may be tested in the Rakefile.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Example Rakefile -*- ruby -*-
|
||||
|
||||
task :default => [:main]
|
||||
|
||||
file "a.o" => ["a.c"] do |t|
|
||||
src = t.name.sub(/\.o$/, '.c')
|
||||
sh "gcc #{src} -c -o #{t.name}"
|
||||
end
|
||||
|
||||
file "b.o" => ["b.c"] do |t|
|
||||
src = t.name.sub(/\.o$/, '.c')
|
||||
sh "gcc #{src} -c -o #{t.name}"
|
||||
end
|
||||
|
||||
file "main.o" => ["main.c"] do |t|
|
||||
src = t.name.sub(/\.o$/, '.c')
|
||||
sh "gcc #{src} -c -o #{t.name}"
|
||||
end
|
||||
|
||||
OBJFILES = ["a.o", "b.o", "main.o"]
|
||||
task :obj => OBJFILES
|
||||
|
||||
file "main" => OBJFILES do |t|
|
||||
sh "gcc -o #{t.name} main.o a.o b.o"
|
||||
end
|
||||
|
||||
task :clean do
|
||||
rm_f FileList['*.o']
|
||||
Dir['*~'].each { |fn| rm_f fn }
|
||||
end
|
||||
|
||||
task :clobber => [:clean] do
|
||||
rm_f "main"
|
||||
end
|
||||
|
||||
task :run => ["main"] do
|
||||
sh "./main"
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
# Example Rakefile -*- ruby -*-
|
||||
# Using the power of Ruby
|
||||
|
||||
task :default => [:main]
|
||||
|
||||
def ext(fn, newext)
|
||||
fn.sub(/\.[^.]+$/, newext)
|
||||
end
|
||||
|
||||
SRCFILES = Dir['*.c']
|
||||
OBJFILES = SRCFILES.collect { |fn| ext(fn,".o") }
|
||||
|
||||
OBJFILES.each do |objfile|
|
||||
srcfile = ext(objfile, ".c")
|
||||
file objfile => [srcfile] do |t|
|
||||
sh "gcc #{srcfile} -c -o #{t.name}"
|
||||
end
|
||||
end
|
||||
|
||||
file "main" => OBJFILES do |t|
|
||||
sh "gcc -o #{t.name} main.o a.o b.o"
|
||||
end
|
||||
|
||||
task :clean do
|
||||
rm_f FileList['*.o']
|
||||
Dir['*~'].each { |fn| rm_f fn }
|
||||
end
|
||||
|
||||
task :clobber => [:clean] do
|
||||
rm_f "main"
|
||||
end
|
||||
|
||||
task :run => ["main"] do
|
||||
sh "./main"
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void a()
|
||||
{
|
||||
printf ("In function a\n");
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void b()
|
||||
{
|
||||
printf ("In function b\n");
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
extern void a();
|
||||
extern void b();
|
||||
|
||||
int main ()
|
||||
{
|
||||
a();
|
||||
b();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
= Glossary
|
||||
|
||||
action ::
|
||||
Code to be executed in order to perform a task. Actions in a Rakefile are
|
||||
specified in a code block. (Usually delimited by +do+/+end+ pairs.)
|
||||
|
||||
execute ::
|
||||
When a task is executed, all of its actions are performed in the order they
|
||||
were defined. Note that, unlike <tt>invoke</tt>, <tt>execute</tt> always
|
||||
executes the actions (without invoking or executing the prerequisites).
|
||||
|
||||
file task (Rake::FileTask) ::
|
||||
A file task is a task whose purpose is to create a file (which has the same
|
||||
name as the task). When invoked, a file task will only execute if one or
|
||||
more of the following conditions are true.
|
||||
|
||||
1. The associated file does not exist.
|
||||
2. A prerequisite has a later time stamp than the existing file.
|
||||
|
||||
Because normal Tasks always have the current time as timestamp, a FileTask
|
||||
that has a normal Task prerequisite will always execute.
|
||||
|
||||
invoke ::
|
||||
When a task is invoked, first we check to see if it has been invoked before.
|
||||
If it has been, then nothing else is done. If this is the first time it has
|
||||
been invoked, then we invoke each of its prerequisites. Finally, we check
|
||||
to see if we need to execute the actions of this task by calling
|
||||
Rake::Task#needed?. If the task is needed, we execute its actions.
|
||||
|
||||
NOTE: Prerequisites are still invoked even if the task is not needed.
|
||||
|
||||
prerequisites ::
|
||||
Every task has a (possibly empty) set of prerequisites. A prerequisite P to
|
||||
Task T is itself a task that must be invoked before Task T.
|
||||
|
||||
rule ::
|
||||
A rule is a recipe for synthesizing a task when no task is explicitly
|
||||
defined. Rules generally synthesize file tasks.
|
||||
|
||||
task (Rake::Task) ::
|
||||
The basic unit of work in a Rakefile. A task has a name, a set of
|
||||
prerequisites, and a list of actions to be performed.
|
||||
@@ -0,0 +1,592 @@
|
||||
# frozen_string_literal: true
|
||||
module RDoc
|
||||
module Page
|
||||
|
||||
FONTS = "\"Bitstream Vera Sans\", Verdana, Arial, Helvetica, sans-serif"
|
||||
|
||||
STYLE = <<CSS
|
||||
a {
|
||||
color: #00F;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #77F;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
body, td, p {
|
||||
font-family: %fonts%;
|
||||
background: #FFF;
|
||||
color: #000;
|
||||
margin: 0px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
#description p {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.sectiontitle {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding: 0.5em;
|
||||
padding-left: 2em;
|
||||
background: #005;
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
border: 1px dotted black;
|
||||
}
|
||||
|
||||
.attr-rw {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
text-align: center;
|
||||
color: #055;
|
||||
}
|
||||
|
||||
.attr-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.attr-desc {
|
||||
}
|
||||
|
||||
.attr-value {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.file-title-prefix {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.file-title {
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
background: #005;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.banner {
|
||||
background: #005;
|
||||
color: #FFF;
|
||||
border: 1px solid black;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.banner td {
|
||||
background: transparent;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
h1 a, h2 a, .sectiontitle a, .banner a {
|
||||
color: #FF0;
|
||||
}
|
||||
|
||||
h1 a:hover, h2 a:hover, .sectiontitle a:hover, .banner a:hover {
|
||||
color: #FF7;
|
||||
}
|
||||
|
||||
.dyn-source {
|
||||
display: none;
|
||||
background: #FFE;
|
||||
color: #000;
|
||||
border: 1px dotted black;
|
||||
margin: 0.5em 2em 0.5em 2em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.dyn-source .cmt {
|
||||
color: #00F;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.dyn-source .kw {
|
||||
color: #070;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.method {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.description pre {
|
||||
padding: 0.5em;
|
||||
border: 1px dotted black;
|
||||
background: #FFE;
|
||||
}
|
||||
|
||||
.method .title {
|
||||
font-family: monospace;
|
||||
font-size: large;
|
||||
border-bottom: 1px dashed black;
|
||||
margin-bottom: 0.3em;
|
||||
padding-bottom: 0.1em;
|
||||
}
|
||||
|
||||
.method .description, .method .sourcecode {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.description p, .sourcecode p {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.method .sourcecode p.source-link {
|
||||
text-indent: 0em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.method .aka {
|
||||
margin-top: 0.3em;
|
||||
margin-left: 1em;
|
||||
font-style: italic;
|
||||
text-indent: 2em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding: 1em;
|
||||
border: 1px solid black;
|
||||
font-size: x-large;
|
||||
font-weight: bold;
|
||||
color: #FFF;
|
||||
background: #007;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding: 0.5em 1em 0.5em 1em;
|
||||
border: 1px solid black;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
color: #FFF;
|
||||
background: #009;
|
||||
}
|
||||
|
||||
h3, h4, h5, h6 {
|
||||
padding: 0.2em 1em 0.2em 1em;
|
||||
border: 1px dashed black;
|
||||
color: #000;
|
||||
background: #AAF;
|
||||
}
|
||||
|
||||
.sourcecode > pre {
|
||||
padding: 0.5em;
|
||||
border: 1px dotted black;
|
||||
background: #FFE;
|
||||
}
|
||||
|
||||
CSS
|
||||
|
||||
XHTML_PREAMBLE = %{<?xml version="1.0" encoding="%charset%"?>
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
}
|
||||
|
||||
HEADER = XHTML_PREAMBLE + <<ENDHEADER
|
||||
<html>
|
||||
<head>
|
||||
<title>%title%</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
|
||||
<link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
// <![CDATA[
|
||||
|
||||
function toggleSource( id )
|
||||
{
|
||||
var elem
|
||||
var link
|
||||
|
||||
if( document.getElementById )
|
||||
{
|
||||
elem = document.getElementById( id )
|
||||
link = document.getElementById( "l_" + id )
|
||||
}
|
||||
else if ( document.all )
|
||||
{
|
||||
elem = eval( "document.all." + id )
|
||||
link = eval( "document.all.l_" + id )
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if( elem.style.display == "block" )
|
||||
{
|
||||
elem.style.display = "none"
|
||||
link.innerHTML = "show source"
|
||||
}
|
||||
else
|
||||
{
|
||||
elem.style.display = "block"
|
||||
link.innerHTML = "hide source"
|
||||
}
|
||||
}
|
||||
|
||||
function openCode( url )
|
||||
{
|
||||
window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
|
||||
}
|
||||
// ]]>
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
ENDHEADER
|
||||
|
||||
FILE_PAGE = <<HTML
|
||||
<table border='0' cellpadding='0' cellspacing='0' width="100%" class='banner'>
|
||||
<tr><td>
|
||||
<table width="100%" border='0' cellpadding='0' cellspacing='0'><tr>
|
||||
<td class="file-title" colspan="2"><span class="file-title-prefix">File</span><br />%short_name%</td>
|
||||
<td align="right">
|
||||
<table border='0' cellspacing="0" cellpadding="2">
|
||||
<tr>
|
||||
<td>Path:</td>
|
||||
<td>%full_path%
|
||||
IF:cvsurl
|
||||
(<a href="%cvsurl%">CVS</a>)
|
||||
ENDIF:cvsurl
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Modified:</td>
|
||||
<td>%dtm_modified%</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table><br>
|
||||
HTML
|
||||
|
||||
###################################################################
|
||||
|
||||
CLASS_PAGE = <<HTML
|
||||
<table width="100%" border='0' cellpadding='0' cellspacing='0' class='banner'><tr>
|
||||
<td class="file-title"><span class="file-title-prefix">%classmod%</span><br />%full_name%</td>
|
||||
<td align="right">
|
||||
<table cellspacing=0 cellpadding=2>
|
||||
<tr valign="top">
|
||||
<td>In:</td>
|
||||
<td>
|
||||
START:infiles
|
||||
HREF:full_path_url:full_path:
|
||||
IF:cvsurl
|
||||
(<a href="%cvsurl%">CVS</a>)
|
||||
ENDIF:cvsurl
|
||||
END:infiles
|
||||
</td>
|
||||
</tr>
|
||||
IF:parent
|
||||
<tr>
|
||||
<td>Parent:</td>
|
||||
<td>
|
||||
IF:par_url
|
||||
<a href="%par_url%">
|
||||
ENDIF:par_url
|
||||
%parent%
|
||||
IF:par_url
|
||||
</a>
|
||||
ENDIF:par_url
|
||||
</td>
|
||||
</tr>
|
||||
ENDIF:parent
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
HTML
|
||||
|
||||
###################################################################
|
||||
|
||||
METHOD_LIST = <<HTML
|
||||
<div id="content">
|
||||
IF:diagram
|
||||
<table cellpadding='0' cellspacing='0' border='0' width="100%"><tr><td align="center">
|
||||
%diagram%
|
||||
</td></tr></table>
|
||||
ENDIF:diagram
|
||||
|
||||
IF:description
|
||||
<div class="description">%description%</div>
|
||||
ENDIF:description
|
||||
|
||||
IF:requires
|
||||
<div class="sectiontitle">Required Files</div>
|
||||
<ul>
|
||||
START:requires
|
||||
<li>HREF:aref:name:</li>
|
||||
END:requires
|
||||
</ul>
|
||||
ENDIF:requires
|
||||
|
||||
IF:toc
|
||||
<div class="sectiontitle">Contents</div>
|
||||
<ul>
|
||||
START:toc
|
||||
<li><a href="#%href%">%secname%</a></li>
|
||||
END:toc
|
||||
</ul>
|
||||
ENDIF:toc
|
||||
|
||||
IF:methods
|
||||
<div class="sectiontitle">Methods</div>
|
||||
<ul>
|
||||
START:methods
|
||||
<li>HREF:aref:name:</li>
|
||||
END:methods
|
||||
</ul>
|
||||
ENDIF:methods
|
||||
|
||||
IF:includes
|
||||
<div class="sectiontitle">Included Modules</div>
|
||||
<ul>
|
||||
START:includes
|
||||
<li>HREF:aref:name:</li>
|
||||
END:includes
|
||||
</ul>
|
||||
ENDIF:includes
|
||||
|
||||
START:sections
|
||||
IF:sectitle
|
||||
<div class="sectiontitle"><a nem="%secsequence%">%sectitle%</a></div>
|
||||
IF:seccomment
|
||||
<div class="description">
|
||||
%seccomment%
|
||||
</div>
|
||||
ENDIF:seccomment
|
||||
ENDIF:sectitle
|
||||
|
||||
IF:classlist
|
||||
<div class="sectiontitle">Classes and Modules</div>
|
||||
%classlist%
|
||||
ENDIF:classlist
|
||||
|
||||
IF:constants
|
||||
<div class="sectiontitle">Constants</div>
|
||||
<table border='0' cellpadding='5'>
|
||||
START:constants
|
||||
<tr valign='top'>
|
||||
<td class="attr-name">%name%</td>
|
||||
<td>=</td>
|
||||
<td class="attr-value">%value%</td>
|
||||
</tr>
|
||||
IF:desc
|
||||
<tr valign='top'>
|
||||
<td> </td>
|
||||
<td colspan="2" class="attr-desc">%desc%</td>
|
||||
</tr>
|
||||
ENDIF:desc
|
||||
END:constants
|
||||
</table>
|
||||
ENDIF:constants
|
||||
|
||||
IF:attributes
|
||||
<div class="sectiontitle">Attributes</div>
|
||||
<table border='0' cellpadding='5'>
|
||||
START:attributes
|
||||
<tr valign='top'>
|
||||
<td class='attr-rw'>
|
||||
IF:rw
|
||||
[%rw%]
|
||||
ENDIF:rw
|
||||
</td>
|
||||
<td class='attr-name'>%name%</td>
|
||||
<td class='attr-desc'>%a_desc%</td>
|
||||
</tr>
|
||||
END:attributes
|
||||
</table>
|
||||
ENDIF:attributes
|
||||
|
||||
IF:method_list
|
||||
START:method_list
|
||||
IF:methods
|
||||
<div class="sectiontitle">%type% %category% methods</div>
|
||||
START:methods
|
||||
<div class="method">
|
||||
<div class="title">
|
||||
IF:callseq
|
||||
<a name="%aref%"></a><b>%callseq%</b>
|
||||
ENDIF:callseq
|
||||
IFNOT:callseq
|
||||
<a name="%aref%"></a><b>%name%</b>%params%
|
||||
ENDIF:callseq
|
||||
IF:codeurl
|
||||
[ <a href="javascript:openCode('%codeurl%')">source</a> ]
|
||||
ENDIF:codeurl
|
||||
</div>
|
||||
IF:m_desc
|
||||
<div class="description">
|
||||
%m_desc%
|
||||
</div>
|
||||
ENDIF:m_desc
|
||||
IF:aka
|
||||
<div class="aka">
|
||||
This method is also aliased as
|
||||
START:aka
|
||||
<a href="%aref%">%name%</a>
|
||||
END:aka
|
||||
</div>
|
||||
ENDIF:aka
|
||||
IF:sourcecode
|
||||
<div class="sourcecode">
|
||||
<p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
|
||||
<div id="%aref%_source" class="dyn-source">
|
||||
<pre>
|
||||
%sourcecode%
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
ENDIF:sourcecode
|
||||
</div>
|
||||
END:methods
|
||||
ENDIF:methods
|
||||
END:method_list
|
||||
ENDIF:method_list
|
||||
END:sections
|
||||
</div>
|
||||
HTML
|
||||
|
||||
FOOTER = <<ENDFOOTER
|
||||
</body>
|
||||
</html>
|
||||
ENDFOOTER
|
||||
|
||||
BODY = HEADER + <<ENDBODY
|
||||
!INCLUDE! <!-- banner header -->
|
||||
|
||||
<div id="bodyContent">
|
||||
#{METHOD_LIST}
|
||||
</div>
|
||||
|
||||
#{FOOTER}
|
||||
ENDBODY
|
||||
|
||||
########################## Source code ##########################
|
||||
|
||||
SRC_PAGE = XHTML_PREAMBLE + <<HTML
|
||||
<html>
|
||||
<head><title>%title%</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
|
||||
<style>
|
||||
.ruby-comment { color: green; font-style: italic }
|
||||
.ruby-constant { color: #4433aa; font-weight: bold; }
|
||||
.ruby-identifier { color: #222222; }
|
||||
.ruby-ivar { color: #2233dd; }
|
||||
.ruby-keyword { color: #3333FF; font-weight: bold }
|
||||
.ruby-node { color: #777777; }
|
||||
.ruby-operator { color: #111111; }
|
||||
.ruby-regexp { color: #662222; }
|
||||
.ruby-value { color: #662222; font-style: italic }
|
||||
.kw { color: #3333FF; font-weight: bold }
|
||||
.cmt { color: green; font-style: italic }
|
||||
.str { color: #662222; font-style: italic }
|
||||
.re { color: #662222; }
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<pre>%code%</pre>
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
|
||||
########################## Index ################################
|
||||
|
||||
FR_INDEX_BODY = <<HTML
|
||||
!INCLUDE!
|
||||
HTML
|
||||
|
||||
FILE_INDEX = XHTML_PREAMBLE + <<HTML
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
|
||||
<style>
|
||||
<!--
|
||||
body {
|
||||
background-color: #EEE;
|
||||
font-family: #{FONTS};
|
||||
color: #000;
|
||||
margin: 0px;
|
||||
}
|
||||
.banner {
|
||||
background: #005;
|
||||
color: #FFF;
|
||||
padding: 0.2em;
|
||||
font-size: small;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
.entries {
|
||||
margin: 0.25em 1em 0 1em;
|
||||
font-size: x-small;
|
||||
}
|
||||
a {
|
||||
color: #00F;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
a:hover {
|
||||
color: #77F;
|
||||
text-decoration: underline;
|
||||
}
|
||||
-->
|
||||
</style>
|
||||
<base target="docwin">
|
||||
</head>
|
||||
<body>
|
||||
<div class="banner">%list_title%</div>
|
||||
<div class="entries">
|
||||
START:entries
|
||||
<a href="%href%">%name%</a><br>
|
||||
END:entries
|
||||
</div>
|
||||
</body></html>
|
||||
HTML
|
||||
|
||||
CLASS_INDEX = FILE_INDEX
|
||||
METHOD_INDEX = FILE_INDEX
|
||||
|
||||
INDEX = XHTML_PREAMBLE + <<HTML
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>%title%</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
|
||||
</head>
|
||||
|
||||
<frameset cols="20%,*">
|
||||
<frameset rows="15%,35%,50%">
|
||||
<frame src="fr_file_index.html" title="Files" name="Files" />
|
||||
<frame src="fr_class_index.html" name="Classes" />
|
||||
<frame src="fr_method_index.html" name="Methods" />
|
||||
</frameset>
|
||||
IF:inline_source
|
||||
<frame src="%initial_page%" name="docwin">
|
||||
ENDIF:inline_source
|
||||
IFNOT:inline_source
|
||||
<frameset rows="80%,20%">
|
||||
<frame src="%initial_page%" name="docwin">
|
||||
<frame src="blank.html" name="source">
|
||||
</frameset>
|
||||
ENDIF:inline_source
|
||||
<noframes>
|
||||
<body bgcolor="white">
|
||||
Click <a href="html/index.html">here</a> for a non-frames
|
||||
version of this page.
|
||||
</body>
|
||||
</noframes>
|
||||
</frameset>
|
||||
|
||||
</html>
|
||||
HTML
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
= Original Prototype Rake
|
||||
|
||||
This is the original 100 line prototype rake program.
|
||||
|
||||
---
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'ftools'
|
||||
|
||||
class Task
|
||||
TASKS = Hash.new
|
||||
|
||||
attr_reader :prerequisites
|
||||
|
||||
def initialize(task_name)
|
||||
@name = task_name
|
||||
@prerequisites = []
|
||||
@actions = []
|
||||
end
|
||||
|
||||
def enhance(deps=nil, &block)
|
||||
@prerequisites |= deps if deps
|
||||
@actions << block if block_given?
|
||||
self
|
||||
end
|
||||
|
||||
def name
|
||||
@name.to_s
|
||||
end
|
||||
|
||||
def invoke
|
||||
@prerequisites.each { |n| Task[n].invoke }
|
||||
execute if needed?
|
||||
end
|
||||
|
||||
def execute
|
||||
return if @triggered
|
||||
@triggered = true
|
||||
@actions.collect { |act| result = act.call(self) }.last
|
||||
end
|
||||
|
||||
def needed?
|
||||
true
|
||||
end
|
||||
|
||||
def timestamp
|
||||
Time.now
|
||||
end
|
||||
|
||||
class << self
|
||||
def [](task_name)
|
||||
TASKS[intern(task_name)] or fail "Don't know how to rake #{task_name}"
|
||||
end
|
||||
|
||||
def define_task(args, &block)
|
||||
case args
|
||||
when Hash
|
||||
fail "Too Many Target Names: #{args.keys.join(' ')}" if args.size > 1
|
||||
fail "No Task Name Given" if args.size < 1
|
||||
task_name = args.keys[0]
|
||||
deps = args[task_name]
|
||||
else
|
||||
task_name = args
|
||||
deps = []
|
||||
end
|
||||
deps = deps.collect {|d| intern(d) }
|
||||
get(task_name).enhance(deps, &block)
|
||||
end
|
||||
|
||||
def get(task_name)
|
||||
name = intern(task_name)
|
||||
TASKS[name] ||= self.new(name)
|
||||
end
|
||||
|
||||
def intern(task_name)
|
||||
(Symbol === task_name) ? task_name : task_name.intern
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class FileTask < Task
|
||||
def needed?
|
||||
return true unless File.exist?(name)
|
||||
latest_prereq = @prerequisites.collect{|n| Task[n].timestamp}.max
|
||||
return false if latest_prereq.nil?
|
||||
timestamp < latest_prereq
|
||||
end
|
||||
|
||||
def timestamp
|
||||
File.new(name.to_s).mtime
|
||||
end
|
||||
end
|
||||
|
||||
def task(args, &block)
|
||||
Task.define_task(args, &block)
|
||||
end
|
||||
|
||||
def file(args, &block)
|
||||
FileTask.define_task(args, &block)
|
||||
end
|
||||
|
||||
def sys(cmd)
|
||||
puts cmd
|
||||
system(cmd) or fail "Command Failed: [#{cmd}]"
|
||||
end
|
||||
|
||||
def rake
|
||||
begin
|
||||
here = Dir.pwd
|
||||
while ! File.exist?("Rakefile")
|
||||
Dir.chdir("..")
|
||||
fail "No Rakefile found" if Dir.pwd == here
|
||||
here = Dir.pwd
|
||||
end
|
||||
puts "(in #{Dir.pwd})"
|
||||
load "./Rakefile"
|
||||
ARGV.push("default") if ARGV.size == 0
|
||||
ARGV.each { |task_name| Task[task_name].invoke }
|
||||
rescue Exception => ex
|
||||
puts "rake aborted ... #{ex.message}"
|
||||
puts ex.backtrace.find {|str| str =~ /Rakefile/ } || ""
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0 then
|
||||
rake
|
||||
end
|
||||
@@ -0,0 +1,156 @@
|
||||
.Dd June 12, 2016
|
||||
.Dt RAKE 1
|
||||
.Os rake 11.2.2
|
||||
.Sh NAME
|
||||
.Nm rake
|
||||
.Nd make-like build utility for Ruby
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl f Ar rakefile
|
||||
.Op Ar options
|
||||
.Ar targets ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a
|
||||
.Xr make 1 Ns -like
|
||||
build utility for Ruby.
|
||||
Tasks and dependencies are specified in standard Ruby syntax.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl m , Fl -multitask
|
||||
Treat all tasks as multitasks.
|
||||
.It Fl B , Fl -build-all
|
||||
Build all prerequisites, including those which are up\-to\-date.
|
||||
.It Fl j , Fl -jobs Ar num_jobs
|
||||
Specifies the maximum number of tasks to execute in parallel (default is number of CPU cores + 4).
|
||||
.El
|
||||
.Ss Modules
|
||||
.Bl -tag -width Ds
|
||||
.It Fl I , Fl -libdir Ar libdir
|
||||
Include
|
||||
.Ar libdir
|
||||
in the search path for required modules.
|
||||
.It Fl r , Fl -require Ar module
|
||||
Require
|
||||
.Ar module
|
||||
before executing
|
||||
.Pa rakefile .
|
||||
.El
|
||||
.Ss Rakefile location
|
||||
.Bl -tag -width Ds
|
||||
.It Fl f , Fl -rakefile Ar filename
|
||||
Use
|
||||
.Ar filename
|
||||
as the rakefile to search for.
|
||||
.It Fl N , Fl -no-search , Fl -nosearch
|
||||
Do not search parent directories for the Rakefile.
|
||||
.It Fl G , Fl -no-system , Fl -nosystem
|
||||
Use standard project Rakefile search paths, ignore system wide rakefiles.
|
||||
.It Fl R , Fl -rakelib Ar rakelibdir , Fl -rakelibdir Ar rakelibdir
|
||||
Auto-import any .rake files in
|
||||
.Ar rakelibdir
|
||||
(default is
|
||||
.Sq rakelib )
|
||||
.It Fl g , Fl -system
|
||||
Use system-wide (global) rakefiles (usually
|
||||
.Pa ~/.rake/*.rake ) .
|
||||
.El
|
||||
.Ss Debugging
|
||||
.Bl -tag -width Ds
|
||||
.It Fl -backtrace Ns = Ns Ar out
|
||||
Enable full backtrace.
|
||||
.Ar out
|
||||
can be
|
||||
.Dv stderr
|
||||
(default) or
|
||||
.Dv stdout .
|
||||
.It Fl t , Fl -trace Ns = Ns Ar out
|
||||
Turn on invoke/execute tracing, enable full backtrace.
|
||||
.Ar out
|
||||
can be
|
||||
.Dv stderr
|
||||
(default) or
|
||||
.Dv stdout .
|
||||
.It Fl -suppress-backtrace Ar pattern
|
||||
Suppress backtrace lines matching regexp
|
||||
.Ar pattern .
|
||||
Ignored if
|
||||
.Fl -trace
|
||||
is on.
|
||||
.It Fl -rules
|
||||
Trace the rules resolution.
|
||||
.It Fl n , Fl -dry-run
|
||||
Do a dry run without executing actions.
|
||||
.It Fl T , Fl -tasks Op Ar pattern
|
||||
Display the tasks (matching optional
|
||||
.Ar pattern )
|
||||
with descriptions, then exit.
|
||||
.It Fl D , Fl -describe Op Ar pattern
|
||||
Describe the tasks (matching optional
|
||||
.Ar pattern ) ,
|
||||
then exit.
|
||||
.It Fl W , Fl -where Op Ar pattern
|
||||
Describe the tasks (matching optional
|
||||
.Ar pattern ) ,
|
||||
then exit.
|
||||
.It Fl P , Fl -prereqs
|
||||
Display the tasks and dependencies, then exit.
|
||||
.It Fl e , Fl -execute Ar code
|
||||
Execute some Ruby code and exit.
|
||||
.It Fl p , Fl -execute-print Ar code
|
||||
Execute some Ruby code, print the result, then exit.
|
||||
.It Fl E , Fl -execute-continue Ar code
|
||||
Execute some Ruby code, then continue with normal task processing.
|
||||
.El
|
||||
.Ss Information
|
||||
.Bl -tag -width Ds
|
||||
.It Fl v , Fl -verbose
|
||||
Log message to standard output.
|
||||
.It Fl q , Fl -quiet
|
||||
Do not log messages to standard output.
|
||||
.It Fl s , Fl -silent
|
||||
Like
|
||||
.Fl -quiet ,
|
||||
but also suppresses the
|
||||
.Sq in directory
|
||||
announcement.
|
||||
.It Fl X , Fl -no-deprecation-warnings
|
||||
Disable the deprecation warnings.
|
||||
.It Fl -comments
|
||||
Show commented tasks only
|
||||
.It Fl A , Fl -all
|
||||
Show all tasks, even uncommented ones (in combination with
|
||||
.Fl T
|
||||
or
|
||||
.Fl D )
|
||||
.It Fl -job-stats Op Ar level
|
||||
Display job statistics.
|
||||
If
|
||||
.Ar level
|
||||
is
|
||||
.Sq history ,
|
||||
displays a complete job list.
|
||||
.It Fl V , Fl -version
|
||||
Display the program version.
|
||||
.It Fl h , Fl H , Fl -help
|
||||
Display a help message.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
The complete documentation for
|
||||
.Nm rake
|
||||
has been installed at
|
||||
.Pa /usr/share/doc/rake-doc/html/index.html .
|
||||
It is also available online at
|
||||
.Lk https://ruby.github.io/rake .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
.Nm
|
||||
was written by
|
||||
.An Jim Weirich Aq Mt jim@weirichhouse.org .
|
||||
.Pp
|
||||
This manual was created by
|
||||
.An Caitlin Matos Aq Mt caitlin.matos@zoho.com
|
||||
for the Debian project (but may be used by others).
|
||||
It was inspired by the manual by
|
||||
.An Jani Monoses Aq Mt jani@iv.ro
|
||||
for the Ubuntu project.
|
||||
@@ -0,0 +1,622 @@
|
||||
= Rakefile Format
|
||||
|
||||
First of all, there is no special format for a Rakefile. A Rakefile
|
||||
contains executable Ruby code. Anything legal in a ruby script is
|
||||
allowed in a Rakefile.
|
||||
|
||||
Now that we understand there is no special syntax in a Rakefile, there
|
||||
are some conventions that are used in a Rakefile that are a little
|
||||
unusual in a typical Ruby program. Since a Rakefile is tailored to
|
||||
specifying tasks and actions, the idioms used in a Rakefile are
|
||||
designed to support that.
|
||||
|
||||
So, what goes into a Rakefile?
|
||||
|
||||
== Tasks
|
||||
|
||||
Tasks are the main unit of work in a Rakefile. Tasks have a name
|
||||
(usually given as a symbol or a string), a list of prerequisites (more
|
||||
symbols or strings) and a list of actions (given as a block).
|
||||
|
||||
=== Simple Tasks
|
||||
|
||||
A task is declared by using the +task+ method. +task+ takes a single
|
||||
parameter that is the name of the task.
|
||||
|
||||
task :name
|
||||
|
||||
=== Tasks with Prerequisites
|
||||
|
||||
Any prerequisites are given as a list (enclosed in square brackets)
|
||||
following the name and an arrow (=>).
|
||||
|
||||
task name: [:prereq1, :prereq2]
|
||||
|
||||
*NOTE:* Although this syntax looks a little funky, it is legal
|
||||
Ruby. We are constructing a hash where the key is :name and the value
|
||||
for that key is the list of prerequisites. It is equivalent to the
|
||||
following ...
|
||||
|
||||
hash = Hash.new
|
||||
hash[:name] = [:prereq1, :prereq2]
|
||||
task(hash)
|
||||
|
||||
You can also use strings for task names and prerequisites, rake doesn't care.
|
||||
This is the same task definition:
|
||||
|
||||
task 'name' => %w[prereq1 prereq2]
|
||||
|
||||
As is this:
|
||||
|
||||
task name: %w[prereq1 prereq2]
|
||||
|
||||
We'll prefer this style for regular tasks with prerequisites throughout the
|
||||
rest of the document. Using an array of strings for the prerequisites means
|
||||
you will need to make fewer changes if you need to move tasks into namespaces
|
||||
or perform other refactorings.
|
||||
|
||||
=== Tasks with Actions
|
||||
|
||||
Actions are defined by passing a block to the +task+ method. Any Ruby
|
||||
code can be placed in the block. The block may reference the task
|
||||
object via the block parameter.
|
||||
|
||||
task name: [:prereq1, :prereq2] do |t|
|
||||
# actions (may reference t)
|
||||
end
|
||||
|
||||
=== Multiple Definitions
|
||||
|
||||
A task may be specified more than once. Each specification adds its
|
||||
prerequisites and actions to the existing definition. This allows one
|
||||
part of a rakefile to specify the actions and a different rakefile
|
||||
(perhaps separately generated) to specify the dependencies.
|
||||
|
||||
For example, the following is equivalent to the single task
|
||||
specification given above.
|
||||
|
||||
task :name
|
||||
task name: :prereq1
|
||||
task name: %w[prereq2]
|
||||
task :name do |t|
|
||||
# actions
|
||||
end
|
||||
|
||||
== File Tasks
|
||||
|
||||
Some tasks are designed to create a file from one or more other files.
|
||||
Tasks that generate these files may be skipped if the file already
|
||||
exists. File tasks are used to specify file creation tasks.
|
||||
|
||||
File tasks are declared using the +file+ method (instead of the +task+
|
||||
method). In addition, file tasks are usually named with a string
|
||||
rather than a symbol.
|
||||
|
||||
The following file task creates a executable program (named +prog+)
|
||||
given two object files named +a.o+ and +b.o+. The tasks
|
||||
for creating +a.o+ and +b.o+ are not shown.
|
||||
|
||||
file "prog" => ["a.o", "b.o"] do |t|
|
||||
sh "cc -o #{t.name} #{t.prerequisites.join(' ')}"
|
||||
end
|
||||
|
||||
== Directory Tasks
|
||||
|
||||
It is common to need to create directories upon demand. The
|
||||
+directory+ convenience method is a short-hand for creating a FileTask
|
||||
that creates the directory. For example, the following declaration
|
||||
...
|
||||
|
||||
directory "testdata/examples/doc"
|
||||
|
||||
is equivalent to ...
|
||||
|
||||
file "testdata" do |t| mkdir t.name end
|
||||
file "testdata/examples" => ["testdata"] do |t| mkdir t.name end
|
||||
file "testdata/examples/doc" => ["testdata/examples"] do |t| mkdir t.name end
|
||||
|
||||
The +directory+ method does not accept prerequisites or actions, but
|
||||
both prerequisites and actions can be added later. For example ...
|
||||
|
||||
directory "testdata"
|
||||
file "testdata" => ["otherdata"]
|
||||
file "testdata" do
|
||||
cp Dir["standard_data/*.data"], "testdata"
|
||||
end
|
||||
|
||||
== Tasks with Parallel Prerequisites
|
||||
|
||||
Rake allows parallel execution of prerequisites using the following syntax:
|
||||
|
||||
multitask copy_files: %w[copy_src copy_doc copy_bin] do
|
||||
puts "All Copies Complete"
|
||||
end
|
||||
|
||||
In this example, +copy_files+ is a normal rake task. Its actions are
|
||||
executed whenever all of its prerequisites are done. The big
|
||||
difference is that the prerequisites (+copy_src+, +copy_bin+ and
|
||||
+copy_doc+) are executed in parallel. Each of the prerequisites are
|
||||
run in their own Ruby thread, possibly allowing faster overall runtime.
|
||||
|
||||
=== Secondary Prerequisites
|
||||
|
||||
If any of the primary prerequisites of a multitask have common secondary
|
||||
prerequisites, all of the primary/parallel prerequisites will wait
|
||||
until the common prerequisites have been run.
|
||||
|
||||
For example, if the <tt>copy_<em>xxx</em></tt> tasks have the
|
||||
following prerequisites:
|
||||
|
||||
task copy_src: :prep_for_copy
|
||||
task copy_bin: :prep_for_copy
|
||||
task copy_doc: :prep_for_copy
|
||||
|
||||
Then the +prep_for_copy+ task is run before starting all the copies in
|
||||
parallel. Once +prep_for_copy+ is complete, +copy_src+, +copy_bin+,
|
||||
and +copy_doc+ are all run in parallel. Note that +prep_for_copy+ is
|
||||
run only once, even though it is referenced in multiple threads.
|
||||
|
||||
=== Thread Safety
|
||||
|
||||
The Rake internal data structures are thread-safe with respect
|
||||
to the multitask parallel execution, so there is no need for the user
|
||||
to do extra synchronization for Rake's benefit. However, if there are
|
||||
user data structures shared between the parallel prerequisites, the
|
||||
user must do whatever is necessary to prevent race conditions.
|
||||
|
||||
== Tasks with Arguments
|
||||
|
||||
Prior to version 0.8.0, rake was only able to handle command line
|
||||
arguments of the form NAME=VALUE that were passed into Rake via the
|
||||
ENV hash. Many folks had asked for some kind of simple command line
|
||||
arguments, perhaps using "--" to separate regular task names from
|
||||
argument values on the command line. The problem is that there was no
|
||||
easy way to associate positional arguments on the command line with
|
||||
different tasks. Suppose both tasks :a and :b expect a command line
|
||||
argument: does the first value go with :a? What if :b is run first?
|
||||
Should it then get the first command line argument.
|
||||
|
||||
Rake 0.8.0 solves this problem by explicitly passing values directly
|
||||
to the tasks that need them. For example, if I had a release task
|
||||
that required a version number, I could say:
|
||||
|
||||
rake release[0.8.2]
|
||||
|
||||
And the string "0.8.2" will be passed to the :release task. Multiple
|
||||
arguments can be passed by separating them with a comma, for example:
|
||||
|
||||
rake name[john,doe]
|
||||
|
||||
Just a few words of caution. The rake task name and its arguments
|
||||
need to be a single command line argument to rake. This generally
|
||||
means no spaces. If spaces are needed, then the entire name +
|
||||
argument string should be quoted. Something like this:
|
||||
|
||||
rake "name[billy bob, smith]"
|
||||
|
||||
(Quoting rules vary between operating systems and shells, so make sure
|
||||
you consult the proper docs for your OS/shell).
|
||||
|
||||
=== Tasks that Expect Parameters
|
||||
|
||||
Parameters are only given to tasks that are setup to expect them. In
|
||||
order to handle named parameters, the task declaration syntax for
|
||||
tasks has been extended slightly.
|
||||
|
||||
For example, a task that needs a first name and last name might be
|
||||
declared as:
|
||||
|
||||
task :name, [:first_name, :last_name]
|
||||
|
||||
The first argument is still the name of the task (:name in this case).
|
||||
The next two arguments are the names of the parameters expected by
|
||||
:name in an array (:first_name and :last_name in the example).
|
||||
|
||||
To access the values of the parameters, the block defining the task
|
||||
behaviour can now accept a second parameter:
|
||||
|
||||
task :name, [:first_name, :last_name] do |t, args|
|
||||
puts "First name is #{args.first_name}"
|
||||
puts "Last name is #{args.last_name}"
|
||||
end
|
||||
|
||||
The first argument of the block "t" is always bound to the current
|
||||
task object. The second argument "args" is an open-struct like object
|
||||
that allows access to the task arguments. Extra command line
|
||||
arguments to a task are ignored.
|
||||
|
||||
If you wish to specify default values for the arguments, you can use
|
||||
the with_defaults method in the task body. Here is the above example
|
||||
where we specify default values for the first and last names:
|
||||
|
||||
task :name, [:first_name, :last_name] do |t, args|
|
||||
args.with_defaults(:first_name => "John", :last_name => "Dough")
|
||||
puts "First name is #{args.first_name}"
|
||||
puts "Last name is #{args.last_name}"
|
||||
end
|
||||
|
||||
=== Tasks that Expect Parameters and Have Prerequisites
|
||||
|
||||
Tasks that use parameters have a slightly different format for
|
||||
prerequisites. Use the arrow notation to indicate the prerequisites
|
||||
for tasks with arguments. For example:
|
||||
|
||||
task :name, [:first_name, :last_name] => [:pre_name] do |t, args|
|
||||
args.with_defaults(:first_name => "John", :last_name => "Dough")
|
||||
puts "First name is #{args.first_name}"
|
||||
puts "Last name is #{args.last_name}"
|
||||
end
|
||||
|
||||
=== Tasks that take Variable-length Parameters
|
||||
|
||||
Tasks that need to handle a list of values as a parameter can use the
|
||||
extras method of the args variable. This allows for tasks that can
|
||||
loop over a variable number of values, and its compatible with named
|
||||
parameters as well:
|
||||
|
||||
task :email, [:message] do |t, args|
|
||||
mail = Mail.new(args.message)
|
||||
recipients = args.extras
|
||||
recipients.each do |target|
|
||||
mail.send_to(target)
|
||||
end
|
||||
end
|
||||
|
||||
There is also the convenience method to_a that returns all parameters
|
||||
in the sequential order they were given, including those associated
|
||||
with named parameters.
|
||||
|
||||
=== Deprecated Task Parameters Format
|
||||
|
||||
There is an older format for declaring task parameters that omitted
|
||||
the task argument array and used the :needs keyword to introduce the
|
||||
dependencies. That format is still supported for compatibility, but
|
||||
is not recommended for use. The older format may be dropped in future
|
||||
versions of rake.
|
||||
|
||||
== Accessing Task Programmatically
|
||||
|
||||
Sometimes it is useful to manipulate tasks programmatically in a
|
||||
Rakefile. To find a task object use Rake::Task.[].
|
||||
|
||||
=== Programmatic Task Example
|
||||
|
||||
For example, the following Rakefile defines two tasks. The :doit task
|
||||
simply prints a simple "DONE" message. The :dont class will lookup
|
||||
the doit class and remove (clear) all of its prerequisites and
|
||||
actions.
|
||||
|
||||
task :doit do
|
||||
puts "DONE"
|
||||
end
|
||||
|
||||
task :dont do
|
||||
Rake::Task[:doit].clear
|
||||
end
|
||||
|
||||
Running this example:
|
||||
|
||||
$ rake doit
|
||||
(in /Users/jim/working/git/rake/x)
|
||||
DONE
|
||||
$ rake dont doit
|
||||
(in /Users/jim/working/git/rake/x)
|
||||
$
|
||||
|
||||
The ability to programmatically manipulate tasks gives rake very
|
||||
powerful meta-programming capabilities w.r.t. task execution, but
|
||||
should be used with caution.
|
||||
|
||||
== Rules
|
||||
|
||||
When a file is named as a prerequisite, but does not have a file task
|
||||
defined for it, Rake will attempt to synthesize a task by looking at a
|
||||
list of rules supplied in the Rakefile.
|
||||
|
||||
Suppose we were trying to invoke task "mycode.o", but no task is
|
||||
defined for it. But the rakefile has a rule that look like this ...
|
||||
|
||||
rule '.o' => ['.c'] do |t|
|
||||
sh "cc #{t.source} -c -o #{t.name}"
|
||||
end
|
||||
|
||||
This rule will synthesize any task that ends in ".o". It has a
|
||||
prerequisite a source file with an extension of ".c" must exist. If
|
||||
Rake is able to find a file named "mycode.c", it will automatically
|
||||
create a task that builds "mycode.o" from "mycode.c".
|
||||
|
||||
If the file "mycode.c" does not exist, rake will attempt
|
||||
to recursively synthesize a rule for it.
|
||||
|
||||
When a task is synthesized from a rule, the +source+ attribute of the
|
||||
task is set to the matching source file. This allows us to write
|
||||
rules with actions that reference the source file.
|
||||
|
||||
=== Advanced Rules
|
||||
|
||||
Any regular expression may be used as the rule pattern. Additionally,
|
||||
a proc may be used to calculate the name of the source file. This
|
||||
allows for complex patterns and sources.
|
||||
|
||||
The following rule is equivalent to the example above.
|
||||
|
||||
rule( /\.o$/ => [
|
||||
proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') }
|
||||
]) do |t|
|
||||
sh "cc #{t.source} -c -o #{t.name}"
|
||||
end
|
||||
|
||||
*NOTE:* Because of a _quirk_ in Ruby syntax, parenthesis are
|
||||
required on *rule* when the first argument is a regular expression.
|
||||
|
||||
The following rule might be used for Java files ...
|
||||
|
||||
rule '.class' => [
|
||||
proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') }
|
||||
] do |t|
|
||||
java_compile(t.source, t.name)
|
||||
end
|
||||
|
||||
*NOTE:* +java_compile+ is a hypothetical method that invokes the
|
||||
java compiler.
|
||||
|
||||
== Importing Dependencies
|
||||
|
||||
Any ruby file (including other rakefiles) can be included with a
|
||||
standard Ruby +require+ command. The rules and declarations in the
|
||||
required file are just added to the definitions already accumulated.
|
||||
|
||||
Because the files are loaded _before_ the rake targets are evaluated,
|
||||
the loaded files must be "ready to go" when the rake command is
|
||||
invoked. This makes generated dependency files difficult to use. By
|
||||
the time rake gets around to updating the dependencies file, it is too
|
||||
late to load it.
|
||||
|
||||
The +import+ command addresses this by specifying a file to be loaded
|
||||
_after_ the main rakefile is loaded, but _before_ any targets on the
|
||||
command line are invoked. In addition, if the file name matches an
|
||||
explicit task, that task is invoked before loading the file. This
|
||||
allows dependency files to be generated and used in a single rake
|
||||
command invocation.
|
||||
|
||||
Example:
|
||||
|
||||
require 'rake/loaders/makefile'
|
||||
|
||||
file ".depends.mf" => [SRC_LIST] do |t|
|
||||
sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}"
|
||||
end
|
||||
|
||||
import ".depends.mf"
|
||||
|
||||
If ".depends" does not exist, or is out of date w.r.t. the source
|
||||
files, a new ".depends" file is generated using +makedepend+ before
|
||||
loading.
|
||||
|
||||
== Comments
|
||||
|
||||
Standard Ruby comments (beginning with "#") can be used anywhere it is
|
||||
legal in Ruby source code, including comments for tasks and rules.
|
||||
However, if you wish a task to be described using the "-T" switch,
|
||||
then you need to use the +desc+ command to describe the task.
|
||||
|
||||
Example:
|
||||
|
||||
desc "Create a distribution package"
|
||||
task package: %w[ ... ] do ... end
|
||||
|
||||
The "-T" switch (or "--tasks" if you like to spell things out) will
|
||||
display a list of tasks that have a description. If you use +desc+ to
|
||||
describe your major tasks, you have a semi-automatic way of generating
|
||||
a summary of your Rake file.
|
||||
|
||||
$ rake -T
|
||||
(in /home/.../rake)
|
||||
rake clean # Remove any temporary products.
|
||||
rake clobber # Remove any generated file.
|
||||
rake clobber_rdoc # Remove rdoc products
|
||||
rake contrib_test # Run tests for contrib_test
|
||||
rake default # Default Task
|
||||
rake install # Install the application
|
||||
rake lines # Count lines in the main rake file
|
||||
rake rdoc # Build the rdoc HTML Files
|
||||
rake rerdoc # Force a rebuild of the RDOC files
|
||||
rake test # Run tests
|
||||
rake testall # Run all test targets
|
||||
|
||||
Only tasks with descriptions will be displayed with the "-T" switch.
|
||||
Use "-P" (or "--prereqs") to get a list of all tasks and their
|
||||
prerequisites.
|
||||
|
||||
== Namespaces
|
||||
|
||||
As projects grow (and along with it, the number of tasks), it is
|
||||
common for task names to begin to clash. For example, if you might
|
||||
have a main program and a set of sample programs built by a single
|
||||
Rakefile. By placing the tasks related to the main program in one
|
||||
namespace, and the tasks for building the sample programs in a
|
||||
different namespace, the task names will not interfere with each other.
|
||||
|
||||
For example:
|
||||
|
||||
namespace "main" do
|
||||
task :build do
|
||||
# Build the main program
|
||||
end
|
||||
end
|
||||
|
||||
namespace "samples" do
|
||||
task :build do
|
||||
# Build the sample programs
|
||||
end
|
||||
end
|
||||
|
||||
task build: %w[main:build samples:build]
|
||||
|
||||
Referencing a task in a separate namespace can be achieved by
|
||||
prefixing the task name with the namespace and a colon
|
||||
(e.g. "main:build" refers to the :build task in the +main+ namespace).
|
||||
Nested namespaces are supported.
|
||||
|
||||
Note that the name given in the +task+ command is always the unadorned
|
||||
task name without any namespace prefixes. The +task+ command always
|
||||
defines a task in the current namespace.
|
||||
|
||||
=== FileTasks
|
||||
|
||||
File task names are not scoped by the namespace command. Since the
|
||||
name of a file task is the name of an actual file in the file system,
|
||||
it makes little sense to include file task names in name space.
|
||||
Directory tasks (created by the +directory+ command) are a type of
|
||||
file task and are also not affected by namespaces.
|
||||
|
||||
=== Name Resolution
|
||||
|
||||
When looking up a task name, rake will start with the current
|
||||
namespace and attempt to find the name there. If it fails to find a
|
||||
name in the current namespace, it will search the parent namespaces
|
||||
until a match is found (or an error occurs if there is no match).
|
||||
|
||||
The "rake" namespace is a special implicit namespace that refers to
|
||||
the toplevel names.
|
||||
|
||||
If a task name begins with a "^" character, the name resolution will
|
||||
start in the parent namespace. Multiple "^" characters are allowed.
|
||||
|
||||
Here is an example file with multiple :run tasks and how various names
|
||||
resolve in different locations.
|
||||
|
||||
task :run
|
||||
|
||||
namespace "one" do
|
||||
task :run
|
||||
|
||||
namespace "two" do
|
||||
task :run
|
||||
|
||||
# :run => "one:two:run"
|
||||
# "two:run" => "one:two:run"
|
||||
# "one:two:run" => "one:two:run"
|
||||
# "one:run" => "one:run"
|
||||
# "^run" => "one:run"
|
||||
# "^^run" => "rake:run" (the top level task)
|
||||
# "rake:run" => "rake:run" (the top level task)
|
||||
end
|
||||
|
||||
# :run => "one:run"
|
||||
# "two:run" => "one:two:run"
|
||||
# "^run" => "rake:run"
|
||||
end
|
||||
|
||||
# :run => "rake:run"
|
||||
# "one:run" => "one:run"
|
||||
# "one:two:run" => "one:two:run"
|
||||
|
||||
== FileLists
|
||||
|
||||
FileLists are the way Rake manages lists of files. You can treat a
|
||||
FileList as an array of strings for the most part, but FileLists
|
||||
support some additional operations.
|
||||
|
||||
=== Creating a FileList
|
||||
|
||||
Creating a file list is easy. Just give it the list of file names:
|
||||
|
||||
fl = FileList['file1.rb', file2.rb']
|
||||
|
||||
Or give it a glob pattern:
|
||||
|
||||
fl = FileList['*.rb']
|
||||
|
||||
== Odds and Ends
|
||||
|
||||
=== do/end versus { }
|
||||
|
||||
Blocks may be specified with either a +do+/+end+ pair, or with curly
|
||||
braces in Ruby. We _strongly_ recommend using +do+/+end+ to specify the
|
||||
actions for tasks and rules. Because the rakefile idiom tends to
|
||||
leave off parentheses on the task/file/rule methods, unusual
|
||||
ambiguities can arise when using curly braces.
|
||||
|
||||
For example, suppose that the method +object_files+ returns a list of
|
||||
object files in a project. Now we use +object_files+ as the
|
||||
prerequisites in a rule specified with actions in curly braces.
|
||||
|
||||
# DON'T DO THIS!
|
||||
file "prog" => object_files {
|
||||
# Actions are expected here (but it doesn't work)!
|
||||
}
|
||||
|
||||
Because curly braces have a higher precedence than +do+/+end+, the
|
||||
block is associated with the +object_files+ method rather than the
|
||||
+file+ method.
|
||||
|
||||
This is the proper way to specify the task ...
|
||||
|
||||
# THIS IS FINE
|
||||
file "prog" => object_files do
|
||||
# Actions go here
|
||||
end
|
||||
|
||||
== Rakefile Path
|
||||
|
||||
When issuing the +rake+ command in a terminal, Rake will look
|
||||
for a Rakefile in the current directory. If a Rakefile is not found,
|
||||
it will search parent directories until one is found.
|
||||
|
||||
For example, if a Rakefile resides in the +project/+ directory,
|
||||
moving deeper into the project's directory tree will not have an adverse
|
||||
effect on rake tasks:
|
||||
|
||||
$ pwd
|
||||
/home/user/project
|
||||
|
||||
$ cd lib/foo/bar
|
||||
$ pwd
|
||||
/home/user/project/lib/foo/bar
|
||||
|
||||
$ rake run_pwd
|
||||
/home/user/project
|
||||
|
||||
As far as rake is concerned, all tasks are run from the directory in
|
||||
which the Rakefile resides.
|
||||
|
||||
=== Multiple Rake Files
|
||||
|
||||
Not all tasks need to be included in a single Rakefile. Additional
|
||||
rake files (with the file extension "+.rake+") may be placed in
|
||||
+rakelib+ directory located at the top level of a project (i.e.
|
||||
the same directory that contains the main +Rakefile+).
|
||||
|
||||
Also, rails projects may include additional rake files in the
|
||||
+lib/tasks+ directory.
|
||||
|
||||
=== Clean and Clobber Tasks
|
||||
|
||||
Through <tt>require 'rake/clean'</tt> Rake provides +clean+ and +clobber+
|
||||
tasks:
|
||||
|
||||
+clean+ ::
|
||||
Clean up the project by deleting scratch files and backup files. Add files
|
||||
to the +CLEAN+ FileList to have the +clean+ target handle them.
|
||||
|
||||
+clobber+ ::
|
||||
Clobber all generated and non-source files in a project. The task depends
|
||||
on +clean+, so all the +CLEAN+ files will be deleted as well as files in the
|
||||
+CLOBBER+ FileList. The intent of this task is to return a project to its
|
||||
pristine, just unpacked state.
|
||||
|
||||
You can add file names or glob patterns to both the +CLEAN+ and +CLOBBER+
|
||||
lists.
|
||||
|
||||
=== Phony Task
|
||||
|
||||
The phony task can be used as a dependency to allow file-based tasks to use
|
||||
non-file-based-tasks as prerequisites without forcing them to rebuild. You
|
||||
can <tt>require 'rake/phony'</tt> to add the +phony+ task.
|
||||
|
||||
----
|
||||
|
||||
== See
|
||||
|
||||
* README.rdoc -- Main documentation for Rake.
|
||||
@@ -0,0 +1,151 @@
|
||||
= Why rake?
|
||||
|
||||
Ok, let me state from the beginning that I never intended to write this
|
||||
code. I'm not convinced it is useful, and I'm not convinced anyone
|
||||
would even be interested in it. All I can say is that Why's onion truck
|
||||
must by been passing through the Ohio valley.
|
||||
|
||||
What am I talking about? ... A Ruby version of Make.
|
||||
|
||||
See, I can sense you cringing already, and I agree. The world certainly
|
||||
doesn't need yet another reworking of the "make" program. I mean, we
|
||||
already have "ant". Isn't that enough?
|
||||
|
||||
It started yesterday. I was helping a coworker fix a problem in one of
|
||||
the Makefiles we use in our project. Not a particularly tough problem,
|
||||
but during the course of the conversation I began lamenting some of the
|
||||
shortcomings of make. In particular, in one of my makefiles I wanted to
|
||||
determine the name of a file dynamically and had to resort to some
|
||||
simple scripting (in Ruby) to make it work. "Wouldn't it be nice if you
|
||||
could just use Ruby inside a Makefile" I said.
|
||||
|
||||
My coworker (a recent convert to Ruby) agreed, but wondered what it
|
||||
would look like. So I sketched the following on the whiteboard...
|
||||
|
||||
"What if you could specify the make tasks in Ruby, like this ..."
|
||||
|
||||
task "build" do
|
||||
java_compile(...args, etc ...)
|
||||
end
|
||||
|
||||
"The task function would register "build" as a target to be made,
|
||||
and the block would be the action executed whenever the build
|
||||
system determined that it was time to do the build target."
|
||||
|
||||
We agreed that would be cool, but writing make from scratch would be WAY
|
||||
too much work. And that was the end of that!
|
||||
|
||||
... Except I couldn't get the thought out of my head. What exactly
|
||||
would be needed to make the about syntax work as a make file? Hmmm, you
|
||||
would need to register the tasks, you need some way of specifying
|
||||
dependencies between tasks, and some way of kicking off the process.
|
||||
Hey! What if we did ... and fifteen minutes later I had a working
|
||||
prototype of Ruby make, complete with dependencies and actions.
|
||||
|
||||
I showed the code to my coworker and we had a good laugh. It was just
|
||||
about a page worth of code that reproduced an amazing amount of the
|
||||
functionality of make. We were both truly stunned with the power of
|
||||
Ruby.
|
||||
|
||||
But it didn't do everything make did. In particular, it didn't have
|
||||
timestamp based file dependencies (where a file is rebuilt if any of its
|
||||
prerequisite files have a later timestamp). Obviously THAT would be a
|
||||
pain to add and so Ruby Make would remain an interesting experiment.
|
||||
|
||||
... Except as I walked back to my desk, I started thinking about what
|
||||
file based dependencies would really need. Rats! I was hooked again,
|
||||
and by adding a new class and two new methods, file/timestamp
|
||||
dependencies were implemented.
|
||||
|
||||
Ok, now I was really hooked. Last night (during CSI!) I massaged the
|
||||
code and cleaned it up a bit. The result is a bare-bones replacement
|
||||
for make in exactly 100 lines of code.
|
||||
|
||||
For the curious, you can see it at ...
|
||||
* doc/proto_rake.rdoc
|
||||
|
||||
Oh, about the name. When I wrote the example Ruby Make task on my
|
||||
whiteboard, my coworker exclaimed "Oh! I have the perfect name: Rake ...
|
||||
Get it? Ruby-Make. Rake!" He said he envisioned the tasks as leaves
|
||||
and Rake would clean them up ... or something like that. Anyways, the
|
||||
name stuck.
|
||||
|
||||
Some quick examples ...
|
||||
|
||||
A simple task to delete backup files ...
|
||||
|
||||
task :clean do
|
||||
Dir['*~'].each {|fn| rm fn rescue nil}
|
||||
end
|
||||
|
||||
Note that task names are symbols (they are slightly easier to type
|
||||
than quoted strings ... but you may use quoted string if you would
|
||||
rather). Rake makes the methods of the FileUtils module directly
|
||||
available, so we take advantage of the <tt>rm</tt> command. Also note
|
||||
the use of "rescue nil" to trap and ignore errors in the <tt>rm</tt>
|
||||
command.
|
||||
|
||||
To run it, just type "rake clean". Rake will automatically find a
|
||||
Rakefile in the current directory (or above!) and will invoke the
|
||||
targets named on the command line. If there are no targets explicitly
|
||||
named, rake will invoke the task "default".
|
||||
|
||||
Here's another task with dependencies ...
|
||||
|
||||
task :clobber => [:clean] do
|
||||
rm_r "tempdir"
|
||||
end
|
||||
|
||||
Task :clobber depends upon task :clean, so :clean will be run before
|
||||
:clobber is executed.
|
||||
|
||||
Files are specified by using the "file" command. It is similar to the
|
||||
task command, except that the task name represents a file, and the task
|
||||
will be run only if the file doesn't exist, or if its modification time
|
||||
is earlier than any of its prerequisites.
|
||||
|
||||
Here is a file based dependency that will compile "hello.cc" to
|
||||
"hello.o".
|
||||
|
||||
file "hello.cc"
|
||||
file "hello.o" => ["hello.cc"] do |t|
|
||||
srcfile = t.name.sub(/\.o$/, ".cc")
|
||||
sh %{g++ #{srcfile} -c -o #{t.name}}
|
||||
end
|
||||
|
||||
I normally specify file tasks with string (rather than symbols). Some
|
||||
file names can't be represented by symbols. Plus it makes the
|
||||
distinction between them more clear to the casual reader.
|
||||
|
||||
Currently writing a task for each and every file in the project would be
|
||||
tedious at best. I envision a set of libraries to make this job
|
||||
easier. For instance, perhaps something like this ...
|
||||
|
||||
require 'rake/ctools'
|
||||
Dir['*.c'].each do |fn|
|
||||
c_source_file(fn)
|
||||
end
|
||||
|
||||
where "c_source_file" will create all the tasks need to compile all the
|
||||
C source files in a directory. Any number of useful libraries could be
|
||||
created for rake.
|
||||
|
||||
That's it. There's no documentation (other than whats in this
|
||||
message). Does this sound interesting to anyone? If so, I'll continue
|
||||
to clean it up and write it up and publish it on RAA. Otherwise, I'll
|
||||
leave it as an interesting exercise and a tribute to the power of Ruby.
|
||||
|
||||
Why /might/ rake be interesting to Ruby programmers. I don't know,
|
||||
perhaps ...
|
||||
|
||||
* No weird make syntax (only weird Ruby syntax :-)
|
||||
* No need to edit or read XML (a la ant)
|
||||
* Platform independent build scripts.
|
||||
* Will run anywhere Ruby exists, so no need to have "make" installed.
|
||||
If you stay away from the "sys" command and use things like
|
||||
'ftools', you can have a perfectly platform independent
|
||||
build script. Also rake is only 100 lines of code, so it can
|
||||
easily be packaged along with the rest of your code.
|
||||
|
||||
So ... Sorry for the long rambling message. Like I said, I never
|
||||
intended to write this code at all.
|
||||
Reference in New Issue
Block a user