Remake
|
As with make, remake uses a centralized rule file, which is named Remakefile. It contains rules with a make-like syntax:
target1 target2 ... : dependency1 dependency2 ... shell script that builds the targets
A target is known to be up-to-date if all its dependencies are. If it has no known dependencies yet the file already exits, it is assumed to be up-to-date. Obsolete targets are rebuilt thanks to the shell script provided by the rule.
As with redo, remake supports dynamic dependencies in addition to these static dependencies. Whenever a script executes remake dependency4 dependency5 ...
, these dependencies are rebuilt if they are obsolete. (So remake acts like redo-ifchange.) Moreover, these dependencies are stored in file .remake so that they are remembered in subsequent runs. Note that dynamic dependencies from previous runs are only used to decide whether a target is obsolete; they are not automatically rebuilt when they are obsolete yet a target depends on them. They will only be rebuilt once the dynamic call to remake is executed.
In other words, the following two rules have almost the same behavior.
target1 target2 ... : dependency1 dependency2 ... shell script target1 target2 ... : remake dependency1 dependency2 ... shell script
(There is a difference if the targets already exist, have never been built before, and the dependencies are either younger or obsolete, since the targets will not be rebuilt in the second case.)
The above usage of dynamic dependencies is hardly useful. Their strength lies in the fact that they can be computed on the fly:
%.o : %.c gcc -MMD -MF $1.d -o $1 -c ${1%.o}.c remake -r < $1.d rm $1.d %.cmo : %.ml ocamldep ${1%.cmo}.ml | remake -r $1 ocamlc -c ${1%.cmo}.ml after.xml: before.xml rules.xsl xsltproc --load-trace -o after.xml rules.xsl before.xml 2> deps remake $(sed -n -e "\\,//,! s,^.*URL=\"\\([^\"]*\\).*\$,\\1,p" deps) rm deps
Note that the first rule fails if any of the header files included by a C source file has to be automatically generated. In that case, one should perform a first call to remake them before calling the compiler. (Dependencies from several calls to remake are cumulative, so they will all be remembered the next time.)
Usage: remake options targets
Options:
-d
: Echo script commands.-j[N]
, –jobs=[N]
: Allow N jobs at once; infinite jobs with no argument.-k
, –keep-going
: Keep going when some targets cannot be made.-r
: Look up targets from the dependencies on standard input.-s
, –silent
, –quiet
: Do not echo targets.Lines starting with a space character or a tabulation are assumed to be rule scripts. They are only allowed after a rule header.
Lines starting with #
are considered to be comments and are ignored. They do interrupt rule scripts though.
Any other line is either a rule header or a variable definition. If such a line ends with a backslash, the following line break is ignored and the line extends to the next one.
Rule headers are a nonempty list of names, followed by a colon, followed by another list of names, possibly empty. Variable definitions are a single name followed by equal followed by a list of names, possibly empty. Basically, the syntax of a rule is as follows:
targets : prerequisites shell script
List of names are space-separated sequences of names. If a name contains a space character, it should be put into double quotes. Names can not be any of the following special characters :$(),="
. Again, quotation should be used. Quotation marks can be escaped by a backslash inside quoted names.
Variables can be used to factor lists of targets or dependencies. They are expanded as they are encountered during Remakefile parsing.
VAR1 = c d VAR2 = a $(VAR1) b $(VAR2) e :
Variables can be used inside rule scripts; they are available as non-exported shell variables there.
remake also supports a few built-in functions inspired from make.
$(addprefix prefix, list)
returns the list obtained by prepending its first argument to each element of its second argument.$(addsuffix suffix, list)
returns the list obtained by appending its first argument to each element of its second argument.Note that functions are ignored inside scripts.
A target is obsolete:
In all the other cases, it is assumed to be up-to-date (and so are all its siblings). Note that the last rule above says "latest" and not "earliest". While it might cause some obsolete targets to go unnoticed in corner cases, it allows for the following kind of rules:
config.h stamp-config_h: config.h.in config.status ./config.status config.h touch stamp-config_h
A config.status
file generally does not update header files (here config.h
) if they would not change. As a consequence, if not for the stamp-config_h
file above, a header would always be considered obsolete once one of its prerequisites is modified. Note that touching config.h
rather than stamp-config_h
would defeat the point of not updating it in the first place, since the program files would need to be rebuilt.
Once all the static prerequisites of a target have been rebuilt, remake checks if the target still needs to be built. If it was obsolete only because its dependencies needed to be rebuilt and none of them changed, the target is assumed to be up-to-date.
There are two kinds of rules. If any of the targets or prerequisites contains a %
character, the rule is said to be generic. All the targets of the rule shall then contain a single %
character. All the other rules are said to be specific.
A rule is said to match a given target:
%
character from one of its targets so that it matches the given target.When remake tries to build a given target, it looks for a specific rule that matches it. If there is one and its script is nonempty, it uses it to rebuild the target.
Otherwise, it looks for a generic rule that match the target. If there are several matching rules, it chooses the one with the shortest pattern (and if there are several ones, the earliest one). remake then looks for specific rules that match each target of the generic rule. All the prerequisites of these specific rules are added to those of the generic rule. The script of the generic rule is used to build the target.
Example:
t%1 t2%: p1 p%2 commands building t%1 and t2% t2z: p4 commands building t2z ty1: p3 # t2x is built by the first rule (which also builds tx1) and its prerequisites are p1, px2 # t2y is built by the first rule (which also builds ty1) and its prerequisites are p1, py2, p3 # t2z is built by the second rule and its prerequisite is p4
The set of rules from Remakefile is ill-formed:
g++ -o remake remake.cpp
g++ -o remake.exe remake.cpp -lws2_32
Installing remake is needed only if Remakefile does not specify the path to the executable for its recursive calls. Thanks to its single source file, remake can be shipped inside other packages and built at configuration time.
Differences with make:
-e
, thus causing them to exit as soon as an error is encountered.Differences with redo:
Remakefile: Remakefile.in ./config.status ./config.status Remakefile
Differences with both make and redo:
$1
, $2
, etc, point to the target names of the rule obtained after substituting %
. No other variables are defined.