4. Connecting recipes
When one recipe's command reads another recipe's artifact, say so in the…
When one recipe’s command reads another recipe’s artifact, say so in the command:
recipe compile gather "src/*.c" cook "build/$<in.stem>.o" { gcc -c $<in> -o $<out> }
recipe link cook "build/app" { gcc $<compile> -o $<out> }$<compile> does three jobs in one stroke: it expands to compile’s outputs
(space-joined), it records the dependency edge, and it folds those artifacts’
contents into link’s cache key. That last one is the important one. Edit a
.c file and cook recompiles one object, then relinks; but if a rebuilt
object comes out byte-identical, the change stops propagating and link stays
cached. And because the read is declared, cook why can attribute a link
miss to the exact artifact that changed.
The reference is also precise about waiting: only the step that references
compile waits for it. Other steps in the recipe proceed.
The colon is for ordering, not reading. A header dependency
(recipe a: b) is a fence: every unit of a waits for all of b, and
nothing of b’s content enters a’s key. That’s the right tool exactly when
nothing is read: grouping meta-targets, chores that want a build first,
run-X-before-Y.
recipe all: compile link check
chore play: link ./build/appIf your command reads an artifact, use the reference. If you only need order, use the colon. Writing both for the same edge is redundant, and cook warns.
Parallel where it can be. Independent units run concurrently; the default
parallelism is your CPU count, overridable with -j:
cook -j 1 link # serialcook -j 8 link # cap at 8Cycles are an error, caught during graph construction before any work runs.
The default recipe is build: bare cook runs it. If a recipe name
collides with a subcommand (init, menu, list, modules, test, dag,
logs, cache, serve, emit-lua, affected, why), the subcommand wins;
prefix the recipe with + to force it: cook +test runs the recipe named
test, cook test runs the test runner.
Namespacing across Cookfiles is done with import, not dotted names. A recipe
declared in one Cookfile always has a single, undotted name; dots appear only at
reference sites and route through an import alias:
import backend ./backendimport frontend ./frontend
recipe ship: backend.build frontend.build cook "out/release.tar" { tar cf $<out> dist }recipe backend.build at a declaration site is a parse error; put recipe build in backend/Cookfile and import it. (More on composition in
Modules and composition.)