I have implemented the build system redo as designed by DJB in Bourne Shell. To understand how redo can be simpler, more flexible, more powerful and more reliable than make, read Introduction to redo and/or redo: a top-down software build system.
The implementation itself depends only on GNU Core Utilities or BusyBox. It takes around twice the time of apenwarr's Python redo implementation to return from a dependency check while using fewer resources.
To build a file target, you have to create a dofile target.do with shell commands that write the intended result of the build either to standard output or to its parameter $3. Then run redo target
.
The default target is all: redo
without arguments executes commands from all.do.
When redo runs a dofile, it gives it three parameters:
$1 | filename of target |
$2 | basename of target, without extension if default dofile is used |
$3 | filename of temporary output file that is renamed on build success |
Redo removes the extension that it gets from the default dofile filename:
Target | Dofile | Parameter $2 |
---|---|---|
a.b.c | a.b.c.do | a.b.c |
a.b.c | default.do | a.b.c |
a.b.c | default.c.do | a.b |
a.b.c | default.b.c.do | a |
Use the redo-ifchange command in a dofile: redo-ifchange dependency
inside target.do means: If the target is built, the dependency is built if it does not exist and recorded as a dependency. On subsequent builds, if dependency does not exist or has changed since the last build, both dependency and target are rebuilt.
For dependency checking, this implementation of redo checks the dependencies' ctime against the stored ctime. If the ctime differs, it checks the dependencies' md5sum against the stored md5sum. This is arguably more useful than just using ctime.
Use the redo-ifcreate command in a dofile: redo-ifcreate ne_dependency
inside target.do means: If target is built, the non-existing file ne_dependency is recorded as a non-existence dependency. If ne_dependency exists on subsequent builds, target is rebuilt.
Short option | Long option | Effect |
---|---|---|
-d | --debug | print dependency checks as they happen |
-h | --help | print usage instructions and exit |
-s | --shuffle | randomize build order to find dependency bugs |
-x | --xtrace | print commands as they are executed (variables expanded) |
You can use the shell builtins &
and wait
to execute commands asynchronously. The following line in a dofile builds targets a and b in parallel: redo-ifchange a & redo-ifchange b & ; wait