# cargo-rake
A configuration-driven build tool that runs named targets declared in a
`Rakefile.toml`, in dependency order. It ships as both a `cargo` subcommand
(`cargo rake`) and a standalone `rake` binary.
## Installation
The two binaries are distributed through different channels:
- **`cargo-rake`** (the `cargo rake` subcommand) — through cargo.
- **`rake`** (the standalone binary) — through system package managers.
### cargo (`cargo-rake`)
```bash
cargo binstall cargo-rake # download a pre-built binary, no compile
cargo install cargo-rake # build and install from crates.io
```
### Arch Linux (`rake`)
Available from the AUR in four mutually-exclusive flavors — pre-built or
built-from-source, each in a stable and a nightly `unstable`-feature variant:
```bash
paru -S rake-bin # pre-built binary (recommended)
paru -S rake-unstable-bin # pre-built, nightly unstable build
paru -S rake # build from source
paru -S rake-unstable # build from source, nightly unstable build
```
### Debian/Ubuntu and Fedora/RHEL (`rake`)
Download the `.deb` or `.rpm` for your architecture from the
[latest release](https://github.com/rustyhorde/cargo-rake/releases/latest):
```bash
sudo dpkg -i rake_*_amd64.deb # Debian/Ubuntu
sudo rpm -i rake-*.x86_64.rpm # Fedora/RHEL
```
### macOS (`rake`)
```bash
brew install rustyhorde/rake/rake
```
## Rakefile.toml
A `Rakefile.toml` declares named **targets**. Each target owns an ordered array
of named **commands** plus an optional `depends_on` list:
```toml
[target.build]
[[target.build.command]]
name = "compile"
cmd = ["cargo", "build", "--all-features"]
[target.all]
depends_on = ["build"]
[[target.all.command]]
name = "release"
cmd = ["cargo", "build", "--release"]
[[target.all.command]]
name = "test"
cmd = ["cargo", "test"]
skip_on_error = true
```
- **`cmd`** is a program followed by its arguments. It is spawned directly — no
shell is involved — so it behaves the same on every platform.
- **`[[target.<t>.command]]`** is a TOML array of tables. Each entry needs a
`name` (a label used in `--list` output and error messages) and a `cmd`.
Commands run in **array (declaration) order**. (TOML table headers are
absolute, so the `target.<t>.command` prefix is required on each entry.)
- **`skip_on_error`** (per command, default `false`): when `true`, a non-zero
exit from that command is tolerated and the target continues with its
remaining commands instead of aborting.
- **`depends_on`** lists other targets that must run, in order, before this one.
- **`tools`** lists external tools (by name) the target needs; see below.
### Tools
A target can declare external tools (cargo subcommands and the like) it depends
on. Tools are defined once in a top-level `[tool.<name>]` table and referenced
by name from a target's `tools` list:
```toml
[tool.matrix]
crate = "cargo-matrix" # crates.io name (for the update check)
check = ["cargo-matrix", "--version"] # presence probe (zero exit = installed)
install = ["cargo", "install", "cargo-matrix"] # run when missing or out of date
update = false # default; see below
[target.clippy]
tools = ["matrix"]
[[target.clippy.command]]
name = "clippy"
cmd = ["cargo", "matrix", "clippy", "--all-targets", "--", "-Dwarnings"]
```
Before a target's commands run, each tool it references is ensured:
- The **`check`** command probes whether the tool is already installed: it must
**exit 0 when the tool is present**. For a cargo subcommand this means
`["cargo", "<sub>", "--version"]` — the bare `cargo-<sub>` binary rejects
`--version` and exits non-zero, which would make the tool look perpetually
absent. When absent, `rake` prints an `Installing` notice and runs
**`install`**.
- **`update`** (default `false`): when `true`, the installed version (parsed
from `check`'s output) is compared against the latest reported by the tool's
**`semver_check`** mode and re-installed if a newer one exists. The only mode
today is `"crates-io"` (the default), which queries the crates.io API and so
needs a **`crate`** name; a failed version check — or a `check` whose output
has no parseable version — is non-fatal and keeps the installed version. With
`update = false`, the already-installed version is used as-is.
- A failed `install` aborts the run (unlike a tolerated command failure).
Each tool is ensured at most once per run, even when several targets reference
it.
### Execution
A target runs after its transitive dependencies. Within a target, commands run
in array order and execution **stops at the first command that exits non-zero**,
aborting the dependency chain — unless that command sets `skip_on_error = true`,
in which case the failure is tolerated and execution continues. The process
exits with the code of the command that stopped the run (or the last command if
all succeeded).
## Usage
```bash
cargo rake <target> # run a target (and its dependencies)
cargo rake --list # list all targets and their commands
cargo rake --file path/to/Rakefile.toml <target>
rake <target> # the standalone binary, same interface
```
When no target is named, the `default` target runs.