Rust

The Rust rules expose Cargo packages as selectable imp labels without replacing Cargo's package model. A label can build one or more binaries, run the package's test suite, publish binaries under dist/, and participate in workspace-wide formatting and linting. Rust, Cargo, the C link driver, linker, and optional compiler cache are all declared tool dependencies rather than ambient host requirements.

Available goals

GoalIntegrationModule
imp buildCargo//rules/rust
imp testCargo//rules/rust
imp packageCargo//rules/rust
imp fmtrustfmt//rules/rust/rustfmt
imp lintClippy//rules/rust/clippy

Set up the workspace

Import the Rust rules in imp.workspace.js. They provide the default Rust toolchain and C link driver; workflow modules enable their high-level commands and load the formatter and linter integrations:

import "//rules/rust";
import "//rules/workflows/fmt";
import "//rules/workflows/lint";
import "//rules/workflows/package";
import "//rules/workflows/test";

Toolchains may also select an explicit C link driver, linker, and kache tool handle. Pinning them in the workspace file makes the same tool graph available to build, test, and Clippy instead of letting those commands drift apart.

When a kache target is set, KACHE_BASE_DIR and rustc's --remap-path-prefix are wired up automatically so cache hits survive imp's per-run sandbox paths, and KACHE_MAX_SIZE caps the on-disk object cache at 4GiB by default — override it via kacheToolchain(version, { cacheSize: "8GiB" }). Caching stays strictly local: KACHE_LOCAL_ONLY=1 is always set, so no S3/remote cache config kache supports is ever reached. Once kache has been used at least once, imp cache stats --details also prints its own kache stats output (hit rate, compile counts, …) alongside the on-disk size for the kache-data cache — this starts kache's background daemon if it isn't already running, since kache (unlike sccache) needs the daemon up to report stats at all.

Kache does not cache user-facing executable links by default. Enable that workspace-wide when those links dominate builds:

export const kacheConfig = { cacheExecutables: true };

This repository's workspace also imports //rules/imp/mode, which declares the default (opt=debug) and release (opt=release) profiles. Cargo builds follow the selected profile:

imp build --profile release //path/to/package:server

release: true on an individual cargoPackage() remains an unconditional opt-in to Cargo's release profile.

Declare a Cargo package

In the directory containing Cargo.toml, add a BUILD.js:

import { cargoPackage } from "//rules/rust";

export const server = cargoPackage({
    bin: "server",
    release: true,
    // This package has no Rust documentation examples to execute.
    doctest: false,
});

The export name forms the label address, so this declaration is selected as //path/to/package:server. Set path when the manifest is below the declaring BUILD.js. bin accepts a string or a list and can explicitly name the binaries Cargo produces. When omitted, the rule derives binary targets from Cargo.toml; a library-only crate can still be formatted, linted, and tested, but has no binary artifact for build or package.

For a package declared inside an enclosing Cargo workspace, set workspaceMember: true. That stages the workspace root and sibling path dependencies so Cargo can resolve the outer [workspace]. Leave it false for a standalone crate or for the target representing the workspace root itself.

Run goals

imp build //path/to/package:server
imp test //path/to/package:server
imp fmt --check //path/to/package:server
imp lint //path/to/package:server
imp package //path/to/package:server

build captures Cargo's selected binaries in the task result. package publishes the build output to dist/path/to/package/server. Tests are always executed rather than replaying a cached successful run; compilation work below the test invocation can still use the normal task and compiler caches.

cargoArgs and testArgs append arguments to the corresponding Cargo command. Use testTools for host programs that tests invoke: they are resolved imperatively and placed on the sandbox's PATH. Use deps for additional resource inputs such as files referenced by include_str! or include_bytes!. doctest overrides the workspace default for that package; set rustConfig.doctest: false to disable Cargo doc-tests workspace-wide.

Generate missing BUILD files

The Rust build generator can declare packages for otherwise unowned Cargo.toml files. Enable it explicitly in imp.workspace.js:

import "//rules/rust/generate_build";

export const rustConfig = {
    buildGenerate: true,
    // Defaults to true; turn it off for a workspace with no Rust doc-tests.
    doctest: false,
};

Then run imp goal generate-build. The generator uses cargo metadata to identify package names, binaries, workspace roots, and workspace members. It is off by default and does not rewrite declarations that already own a manifest.

Available goals

GoalToolProduct module
imp gen-lockfileskache//rules/rust/kache/toolchain
imp gen-lockfilesRust//rules/rust/toolchain

Configuration

OptionTypeDefaultRequired
buildGenerateboolfalseno
doctestbooltrueno

Example

export const rustConfig = {
    buildGenerate: false,
    doctest: true,
};

Targets

cargoPackage

const cargoPackage

Declare a Cargo package target: a self-contained crate, a cargo workspace root (member manifests are globbed via **\/Cargo.toml), or one member of an outer workspace declared elsewhere (see workspaceMember). bin is optional — a lib-only package is a fully valid target for fmt/test, just not for build/package. even when the workspace opt mode is debug. setting for this package. a cargo workspace rooted in an ancestor directory (not this one) — build/ test/fmt sandbox inputs glob from the repo root instead of just path, so cargo can resolve the enclosing [workspace] and any path-deps on sibling members. Leave false for a self-contained crate or a workspace root itself.

ParameterTypeDescription
optsobject
[opts.path="."]stringWorkspace-relative directory containing Cargo.toml.
[opts.bin]stringstring[]
[opts.release=false]booleanAlways build with cargo build --release,
[opts.toolchain]objectstring
[opts.cargoArgs=[]]string[]Extra arguments appended to cargo build.
[opts.testArgs=[]]string[]Extra arguments appended to cargo test.
[opts.testTools=[]]ArraynativeTool() specifications exposed on PATH while running cargo test.
[opts.deps=[]]ArrayExtra deps, e.g. a resourcePackage() (see //rules/asset) providing non-.rs files an include_str!/include_bytes! needs.
[opts.testDeps=[]]ArrayresourcePackage() deps the test binaries read at runtime but the crate doesn't compile against — materialized into the test sandbox only, so changing them re-runs tests without invalidating the build.
[opts.doctest]booleanOverride the workspace rustConfig.doctest
[opts.workspaceMember=false]booleanThis package is a member of

Returns: object Exported label handle.