HAREDO(1)
π HAREDO(1) π
okay so bestie, you know how we're always opening the haredo(1) man page and going "huh?" β well, this is that page, but actually readable. it lives in the General Commands Manual section of the manual, and it's about haredo: a simple and unix-idiomatic build automator. no cap, that's literally the NAME line. slay. π
β¨ SYNOPSIS β¨
haredo [-vqc] [-j <n>] targets... [++ sources...]
π¦ DESCRIPTION π¦
the whole vibe of haredo boils down to this, fr fr:
for each target argument:
find and run its .do script
if a .do script cannot be found, give a warning
return true if any argument is newer than their parent, else false.
Haredo's .do files are written in plain shell script, and will be run using sh -e so it exits on error. π
πΈ Options πΈ
-vβ print verbose logs, which means haredo will execute.dofiles withsh -evrather than justsh -eπ-qβ (quiet) don't print 'redo' logs π€«-cβ (colorless) don't print 'redo' logs with ANSI escape codes π¨-fβ force rebuild, meaning all files in the targets' dependency tree will be rebuilt π₯-j <n>β run a maximum of<n>jobs in parallel β‘
π Arguments π
haredo interprets each of its arguments as a target, up until the special argument ++, and then each argument after that is treated as a source file. and if you provide no arguments at all? haredo interprets this as if it had been called with the argument "all". iconic default behaviour tbh. π«Ά
the difference between a target and a source is that haredo will attempt to build each target using its corresponding .do file, if it can be found, and if not it will emit a warning. in contrast, sources are assumed not to have a do file, and haredo will not try to find it. iykyk. β¨
finally, after running the .do script for each target, haredo checks all sources' and targets' "last-modified" timestamp in the filesystem, and returns a truthy status code if any of them are newer than the parent target. this is an indicator to the parent .do script that it should rebuild its target. main character status-check energy honestly. π₯
π§ Finding a target's .do file π§
the process for finding a target's .do file is as follows, using the example target web/template.html.tmpl:
- first check for the existence of
web/template.html.tmpl.do. - if not found, starting in the target directory and then moving up to successive parent directories, check
.dofiles in this order:default.html.tmpl.dodefault.tmpl.dodefault.do
π Running the .do file π
haredo always runs a .do file from the directory it is in. the .do file is passed three arguments:
- the target path, relative to the
.dofile being run - the basename path (target path without any file extensions)
- a temporary path where the target should be written to.
once the script is complete, the temporary path at $3 will be moved to the target path. this mechanism prevents half-written files sticking around if the script is interrupted. literally protective-icon behaviour. ππ
the following default values for environment variables are used. they can be overridden by setting their values before running haredo:
ARβarASβasCCβccCXXβc++HAREβhareHARECβharecLDβldQBEβqbeSCDOCβscdoc
π EXAMPLES π
the typical structure of a .do script is as follows:
# assemble the dependencies
deps="dep1 dep2"
# run the build on dependencies, and check if they are newer
if haredo $deps
then
# build the target
fi
the above script will only build the target if the result of running haredo on its dependencies gives a truthy result β which only happens when one of them is newer. obsessed with how clean that is. β¨
π A simple C project π
here is a diagram of an example C program, rigged up with haredo .do files. the program (hello) simply prints the words "Hello, haredo!" to the terminal. note: this diagram can be parsed out into a directory using treecat(1) (https://git.sr.ht/~autumnull/treecat). π¦
example/
βββ all.do:
β haredo hello || true
β ./hello
βββ build/
β βββ clean.do:
β β rm -f *.o
β βββ default.o.do:
β β src=../src/$2.c
β β if haredo ++ $src
β β then
β β $CC -o $3 -c $src
β β fi
βββ clean.do:
β haredo build/clean || true
β rm -f hello
βββ hello.do:
β deps="build/hello.o build/main.o"
β if haredo $deps
β then
β $CC -o $3 $deps
β fi
βββ src/
βββ hello.c:
β #include <stdio.h>
β #include "hello.h"
β
β void hello() {
β puts("Hello, haredo!");
β }
βββ hello.h:
β void hello();
βββ main.c:
β #include "hello.h"
β
β void main() {
β hello();
β }
the main entry point for haredo is the all.do file. it simply calls "haredo hello", ignoring whether it's been updated or not ("|| true"), and then runs the executable. π«
the primary .do script for "hello" is "hello.do", which exists, so haredo will execute it. in hello.do we see a more complex use of haredo. we define the dependencies, then we call haredo on them. this will run the build script for each .o file, and then return true if either of them is newer than "hello". if they are, then the "if" block is executed. inside the if block there is an environment variable $CC, which defaults to "cc", the system's c compiler. there is also the argument $3, which is a temporary file to which each .do file should write its target, and it will then be moved to the target location after the script is finished, to prevent broken builds. it's technically possible to write straight to the target path, but this is ill-advised. π (bestie. don't.)
now, each of the .o files referenced in hello.do don't have their own .do file, so they both default to using "build/default.o.do". in this script, the $2 argument is used (the basename of the target, i.e. without file extensions) to find the .c file that the object is built from. then in the call to haredo, the special argument '++' is used before the source file name to indicate that it doesn't have a .do script, since it's a source file. everything else in that file should be familiar from hello.do π«Ά
and that's all! with this setup, the relevant .o file will be rebuilt, along with the executable, each time one of the source files changes. there is also a "clean.do", which can be run with "haredo clean" to clean up all the build files. ate. π
π₯
π SEE ALSO π
sh(1) β that's it, that's the whole list π
π AUTHORS π
maintained by Autumn! <autumnull@posteo.net>, with significant contributions from Ember Sawady <ecs@d2evs.net>. up-to-date sources can be found at https://sr.ht/~autumnull/haredo and bugs/patches can be submitted by email to ~autumnull/haredo-devel@lists.sr.ht π
and that's the whole page, bestie β this version of HAREDO(1) was dated 2026-02-16, so go forth and build things, you absolute icon π§πβ¨
π¦ where this page comes from
- alpine 3.24: haredo-doc 1.0.6-r1 Β· WTFPL
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms