dowel

Getting started

From installation to building, testing, and running your first project. Task-oriented how-tos are in 63-guides.md, the manifest reference in 10-manifest.md, and the command reference in 60-cli.md.

1. Installation

There are no binary releases yet; build from source. You need:

Requirement Used for
A Rust toolchain (cargo) building dowel itself
A C compiler compiling your project; the default is cc on PATH
A C++ compiler only for projects with C++ sources; the default is c++ on PATH
ninja the default backend; without it, the sequential backend (--backend=direct) works
git clone https://github.com/sabas0ba/dowel
cd dowel
cargo build --release
export PATH="$PWD/target/release:$PATH"

dowel --version

If you need to pin or switch versions, dowelup acquires and manages dowel itself (61-acquisition.md).

2. Try the working example

examples/hello is a two-package setup: a static library (libgreet) and an executable that uses it (app).

cd examples/hello/app
dowel check                      # report diagnostics only; does not build
dowel build                      # plan and build (ninja by default)
./.dowel/build/*/bin/app

cd ../libgreet
dowel test                       # build and run the test targets

3. Create a minimal project

dowel new myapp
cd myapp
dowel build
./.dowel/build/*/bin/myapp

dowel new scaffolds a working bin package (--lib for a library, which comes with a passing dowel test target). What it generates is exactly the minimal form below — two files plus a source. dowel.toml holds package information (strict TOML read and written by machines) and dowel.build holds target definitions (written by humans); the reasons for the split are in 10-manifest.md.

myapp/
├── dowel.toml
├── dowel.build
└── src/
    └── main.c

dowel.toml:

[package]
name    = "myapp"
version = "0.1.0"
edition = "2026"

dowel.build:

[bin.myapp]
sources = glob("src/*.c")
dowel check
dowel build
./.dowel/build/*/bin/myapp

Build outputs and intermediates go under .dowel/ (add it to your git ignore). Build directories are separated per configuration (--config). Deleting .dowel/ is always safe: correctness is never lost, only the cached speedup (see the store section of 60-cli.md).

4. Split out a library and depend on it

dowel add libs/util                       # scaffold a library and declare the dependency
dowel add --git https://github.com/x/y    # declare a git dependency, pinned to HEAD's sha

dowel add creates a library package in a subdirectory (or, with --git, declares an external repository pinned to a full commit sha) and appends the [[dependencies]] entry to your dowel.toml; wiring it into a target (below) stays your choice, and the command prints the exact line to add.

Dependencies between packages are declared in dowel.toml — as a local path, as a git URL pinned to a full commit sha, or as a version constraint resolved through the system pkg-config (11-toml-reference.md). Which target uses a dependency is written in dowel.build.

app/dowel.toml:

[[dependencies]]
name = "libgreet"
path = "../libgreet"

app/dowel.build:

[bin.app.private]
deps = [dep("libgreet")]

On the library side, what propagates to dependents (public) and what applies only to the library itself (private) are separated by block:

[lib.greet]
sources = glob("src/**.c")

[lib.greet.public]
includes = [dir("include")]      # also affects the compilation of app

[lib.greet.private]
includes = [dir("src")]          # affects only this library; invisible to app

dowel why traces where a propagated value came from:

dowel why app:app includes

5. Add tests

[test.unit]
sources = glob("tests/*.c")

[test.unit.private]
deps = [target("greet")]

dowel test builds and runs them, treating exit status 0 as success. This follows the C convention; no test harness is imposed.

dowel test
dowel test --nocapture           # pass test output through
dowel test --failed --fail-fast  # only what failed last time, stop at the first failure

6. The everyday loop

If you write manifests in an editor, there is a language server (dowel lsp; 63-guides.md section 6). Diagnostics carry locations and stable codes, and unknown names come with suggestions.