Fetching crates.io dependencies
zut builds are hermetic: the build phase has no network access. So fetching
third-party crates is a separate, explicit step — zut fetch — that runs once,
downloads everything into the content-addressed store, and generates a BUILD
file the hermetic build then consumes offline.
The workflow
Point zut fetch at a Cargo lockfile:
$ zut fetch Cargo.lock
zut fetch Cargo.lock
fetch serde 1.0.210
fetch serde_derive 1.0.210
...
42 crate(s): 42 fetched, 0 reused → .zut/crates.lock + //crates/BUILD
This does four things:
- Downloads each registry crate’s
.cratearchive over HTTPS (the only networked step — zut ships its own TLS viastd.http.Client). - Checksum-verifies each archive against the lockfile’s SHA-256, then unpacks it into a CAS Tree (a content-addressed directory).
- Records a manifest at
.zut/crates.lockmapping eachname versionto its Tree digest. - Generates
//crates/BUILD—crate_library/crate_proc_macrotargets wired with the right editions, features, and dependency edges.
When cargo and the host triple are available, zut runs cargo metadata for a
faithful model (real editions, resolved features, lib/proc-macro kinds). Without
them it falls back to a lockfile-only model (edition 2021, no features).
Idempotent & incremental
zut fetch is safe to re-run. A crate whose Tree is already in the CAS (per the
prior .zut/crates.lock) is reused, not re-downloaded:
$ zut fetch Cargo.lock
reuse serde 1.0.210
...
42 crate(s): 1 fetched, 41 reused → .zut/crates.lock + //crates/BUILD
Downloads run in parallel across worker threads (--jobs=N to bound them).
Using the fetched crates
Depend on a generated target from your own BUILD:
load("@builtin//:rust.bzl", "rust_binary")
rust_binary(
name = "app",
crate_root = "src/main.rs",
srcs = ["src/main.rs"],
edition = "2021",
out = "app",
deps = ["//crates:serde"],
)
Then zut build //:app runs entirely offline — the sources are grafted from the
CAS Trees recorded earlier.
For the full design — URL construction, the manifest format, the generated model, and the cargo-as-toolchain decision — see
docs/design/crates-io.md.