Features
-
Cross-platform: Windows is a first-class citizen - no dependency on a POSIX-compliant shell (or any shell). Werk files work on all platforms out of the box.
-
Simple language: Werk files are written in a simple and human-friendly language that's easy to understand. It is designed to be written by hand.
-
Task recipes: Real support for executing project scrips, similar to
justrecipes or.PHONYMake targets. A command recipe will be run at most once perwerkinvocation. -
Build recipes: Files can be built from Make-like patterns, and rebuilt according to modification time.
-
Advanced outdatedness:
werkdoes more than just compare file modification timestamps. Metadata is cached between runs to support additional sources of "outdatedness". -
Separate output directory: All files produces by
werkare put in a separate output directory, which is always what you want. This is hard to achieve with Make. -
Globbing: Filesystem glob patterns work out of the box, and can be used reliably in dependencies.
werkcaches a hash of the glob result between builds, so file deletion is detected as a change. Globbing is based on theglobsetcrate, which comes fromripgrep. -
Paths can contain spaces: Make simply cannot deal.
-
Depfile support: Depfile output from C-like compilers such as
clang,gcc,cl,glslc, etc. are specially supported in build recipes. When a recipe contains adepfiledependency, it is automatically built and included when evaluating the dependencies of that recipe. -
.gitignore support: The
ignorecrate is used to hide files fromwerk. -
Dry-run: Pass
--dry-runto diagnose the build process without generating any output. -
Concurrency: Build recipes and tasks run in parallel when possible.
-
Autowatch: Werk can be run in
--watchmode, which waits for file changes and automatically rebuilds when any change is detected. -
Long-running tasks: Werk natively supports long-running processes, such as a development webserver running locally, using the
spawnstatement. This also works in combination with the--watchfeature, such that any spawned processes are automatically restarted when a rebuild is triggered.
Limitations
-
Cross-platform: Paths and commands must work across all platforms.
werkdoes not require a shell (likeshorbash), but that also means that common shell features are not available. The language provides cross-platform alternatives in most cases. -
Declarative: Very advanced build logic can be difficult to express. If the limited expression support in
werkis insufficient (and can't be easily supported in the model), consider using a more advanced solution like GNU make, CMake, ninja-build, scons, cargo-script, etc. -
Separate output directory: It is not possible to put output files next to input files, and files in the output directory are assumed to be generated by
werk. -
Multiple recipes matching the same pattern: As opposed to Make, build recipes are not disambiguated by their inputs. This means that for example it is not possible to have two recipes that match
%.o, where one takes%.cas input and the other takes%.cppas input.- Workaround 1: Define separate recipes
%.c.oand%.cpp.oto build the two kinds of source files with different output file extensions. - Workaround 2: Use capture patterns, so the build recipe pattern is
%.(c|cpp), and usematchexpressions to generate the correct compiler arguments based on the captured pattern{0}, which will evaluate to either "c" or "cpp".
- Workaround 1: Define separate recipes
-
Multiple outputs from a single recipe: This is not supported. The typical example is a code generator that outputs both a header file and a source file, like
bison. Note: This may be explicitly supported in the future.- Workaround: For the common case of a
bisonparser, define the recipe for the generatedparser.hfile, and add another recipe for theparser.cfile that has no commands, but just depends onparser.h.
- Workaround: For the common case of a
-
Detailed parallelism control:
werkcurrently does not support marking specific recipes as "non-parallel". The only way to control parallelism is by supplying the--jobscommand line parameter, which controls the number of worker threads.