*goredo* redo implementation on pure Go OVERVIEW *goredo-overview* This is pure Go implementation of DJB's redo (http://cr.yp.to/redo.html) build system proposal. Originally it was just a rewrite of redo-c (https://github.com/leahneukirchen/redo-c), but later most features of apenwarr/redo (https://redo.readthedocs.io/en/latest/) were also implemented. Why yet another implementation? It is feature full and has better performance comparing to shell and Python implementation. goredo is free software: see the file COPYING for copying conditions. INSTALL *goredo-install* Either: > $ go get go.cypherpunks.ru/goredo $ goredo -symlinks $ export PATH=`pwd`:$PATH or: > $ git clone git://git.cypherpunks.ru/goredo.git $ cd goredo $ go build $ ./goredo -symlinks $ export PATH=`pwd`:$PATH < NOTES *goredo-notes* * "all" target is used by default * stdout is always captured, but no target is created if it was empty * empty targets are considered always out of date * .do's arguments are relative paths * .do search goes up to / by default, but can be limited with either REDO_TOP_DIR environment variable, or by having .redo/top file in it * target's completion messages are written after they finish * executable .do is run as is, non-executable is run with /bin/sh -e[x] * tracing (-x) can be done only for non-executable .do FEATURES *goredo-features* * explicit useful and convenient checks from apenwarr/redo: * check that $1 was not touched during .do execution * check that stdout and $3 are not written simultaneously * check that generated target was not modified "externally" outside the redo, preventing its overwriting, but continuing the build * targets, dependency information and their directories are explicitly synced (can be disabled, should work faster) * file's change is detected by comparing its ctime and BLAKE2b hash * files creation is umask-friendly (unlike mkstemp() used in redo-c) * parallel build with jobs limit, optionally in infinite mode * coloured messages (can be disabled) * verbose debug messages, including out-of-date determination, PIDs, lock and jobserver acquirings/releases * displaying of each target's execution time * each target's stderr can be displayed with the PID * optional statusline with currently running/waiting/done jobs * target's stderr can be stored on the disk with TAI64N timestamp prefixes for each line. To convert them to localtime you can use either tai64nlocal utility from daemontools (http://cr.yp.to/daemontools.html) or make a symlink, to use built-in slower decoder: > $ ln -s goredo tai64nlocal < COMMANDS *goredo-commands* * redo-ifchange, redo-ifcreate, redo-always (useful with redo-stamp) * redo -- same as redo-ifchange, but forcefully and *sequentially* run specified targets * redo-log -- display TAI64N timestamped last stderr of the target * redo-stamp -- record stamp dependency. Nothing more, just dummy * redo-cleanup -- removes either temporary, log files, or everything related to goredo * redo-whichdo -- .do search paths for specified target (similar to apenwarr/redo): > $ redo-whichdo x/y/a.b.o x/y/a.b.o.do x/y/default.b.o.do x/y/default.o.do x/y/default.do x/default.b.o.do x/default.o.do x/default.do default.b.o.do default.o.do default.do ../default.b.o.do ../default.o.do * redo-dot -- dependency DOT graph generator. For example to visualize your dependencies with GraphViz: > $ redo target [...] # to assure that .redo is filled up $ redo-dot target [...] > whatever.dot $ dot -Tpng whatever.dot > whatever.png # possibly add -Gsplines=ortho < FAQ *goredo-faq* Hashing and stamping~ All targets are checksummed if their ctime differs from the previous ones. apenwarr/redo gives many reasons why every time checksumming is bad, but in my opinion in practice all of his reasons do not apply. * Aggregate targets and willing to be out-of-date ones just must not produce empty output files. apenwarr/*, redo-c and goredo implementations consider non existing file as an out-of-date target * If you really wish to produce an empty target file, just: touch $3 DJB's proposal with both stdout and $3 gives that ability to control your desired behaviour. Those who does not capture stdout -- failed. Those who creates an empty file if no stdout was written -- failed. redo is a tool for helping people. Literally all targets can be safely "redo-stamp < $3"-ed, reducing false positive out-of-dates. Of course, with the correct working with stdout/$3 and placing necessary results in $3, instead of just silently feeding them in redo-stamp. redo implementations are already automatically records -ifchange on .do files and -ifcreate on non-existing .do files. So why they can not record redo-stamp the same way implicitly? No, Zen of Python does not applicable there, because -ifchange/-ifcreate contradict it already. Modern cryptographic hash algorithms and CPUs are so fast, that even all read and writes to or from hard drive arrays can be easily checksummed and transparently compressed, as ZFS with LZ4 and Skein/BLAKE[23] algorithms demonstrate us. goredo includes redo-stamp, that really records the stamp in the .dep file, but it does not play any role later. It is stayed just for compatibility. Removed .do can lead to permanent errors of its non existence~ That is true, because dependency on it was recorded previously. Is it safe to assume that .do-less target now is an ordinary source-file? I have no confidence in such behaviour. So it is user's decision how to deal with it, probably it was just his inaccuracy mistake. If you really want to get rid of that dependency knowledge for foo/bar target, then just remove foo/.redo/bar.dep. STATE *goredo-state* Dependency and build state is kept inside .redo subdirectory in each directory touched related the build. Each corresponding target has its own, recreated with every rebuild, .dep file. It is recfile (https://www.gnu.org/software/recutils/), that could have various dependency information (dep.rec with the schema included): > Build: 80143f04-bfff-4673-950c-081d712f573d Type: ifcreate Target: foo.o.do Type: ifchange Target: default.o.do Ctime: 1605721341.253305000 Hash: f4929732f96f11e6d4ebe94536b5edef426d00ed0146853e37a87f4295e18eda Type: always Type: stamp Hash: 5bbdf635932cb16b9127e69b6f3872577efed338f0a4ab6f2c7ca3df6ce50cc9 < LICENCE~ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. vim: filetype=help