No build system required — dhake evaluates its own buildfile and builds
dhake.com from source. The committed dhake.com is the
bootstrap binary.
$ ./dhake.com.dbg # evaluates Dhakefile.dhall, builds dhake.com $ ./dhake.com.dbg --list # list targets $ ./tests/build.sh ./dhake.com.dbg # run the test suite
-j N runs up to N independent targets concurrently. On first failure it stops scheduling new targets but lets running ones finish (make-style).
Recipes are Dhall tagged-union values: Shell, Copy, Mkdir, Rm, Touch, Move, Symlink, Chmod, Echo, Env, Run.
Topologically orders targets, detects cycles, and builds only the subgraph reachable from the requested target(s).
Nanosecond-mtime up-to-date checks skip unchanged targets and their dependency closures.
-n prints the actions without running them; phony targets (e.g. clean) are always rebuilt.
A single cosmocc APE that runs on Linux, macOS, Windows, and the BSDs — and builds itself.
let Action = < Shell : Text | Copy : { from : Text, to : Text } | Mkdir : Text | Rm : Text | Touch : Text | Move : { from : Text, to : Text } | Symlink : { from : Text, to : Text } | Chmod : { path : Text, mode : Text } | Echo : Text | Env : { key : Text, value : Text } | Run : { argv : List Text } > let Target = { deps : List Text, phony : Bool, recipe : List Action } in { targets = [ { mapKey = "hello" , mapValue = { deps = [ "hello.c" ], phony = False , recipe = [ < Shell = "cc -o hello hello.c" > ] } } , { mapKey = "clean" , mapValue = { deps = [] : List Text, phony = True , recipe = [ < Rm = "hello" > ] } } ] , default = "hello" }
Makefiles are turing-tarpit shell scripts with surprising whitespace semantics. Dhall is a strongly-typed, total configuration language — your build definition gets type checking, imports, and reusable functions, and it always terminates. The build plan is a plain value you can reason about, not a recipe of shell side effects.