Guide
Tasks and graphs
A task describes one piece of work:
compile := {
name = "compile main",
command_line = "clang-cl /c main.c /Fobuild/main.obj",
inputs = { "main.c" },
outputs = { "build/main.obj" },
dependencies = {},
}
The fields are deliberately small:
nameidentifies the task in Manny's output.command_lineis the program to execute.inputsare files read by the task.outputsare files produced by the task.dependenciesare other tasks that must finish first.working_directoryoptionally changes where the command runs and how relative paths resolve.transparentoptionally lets a task expose its dependencies directly to its dependants.
Pass one or more target tasks to manny.build():
ret manny.build({
targets = { compile },
})
Manny follows task references from those targets and constructs the reachable directed acyclic graph. A task becomes ready after its dependencies finish. Independent ready tasks execute concurrently. A failed task blocks its dependants without stopping unrelated work.
Incremental builds
For tasks with outputs, Manny compares the current task against its recorded state. It considers:
- input and output timestamps;
- compiler-discovered header dependencies;
- the command line;
- the working directory;
- normalized input and output paths;
- relevant task flags.
Configuration is covered by a BLAKE3 fingerprint, so changing a compiler option can rebuild a task even when none of its source files changed.
Completed task state is appended while the build runs. If the build is interrupted, completed work remains available on the next run. A successful build compacts the records into a checksummed binary snapshot under .manny/state in the build root.
Use --explain to see why each task rebuilt or remained current.