Overview
Getting from cargo build to shipped software is a story in three parts:
cross-compiling for targets you don't develop on (where Rust is good but not
Go-effortless), packaging releases for humans and CI to consume (where cargo-dist has
become the standard answer), and defending the dependency graph (where Rust's
everything-from-source, thousands-of-small-crates culture makes supply-chain tooling
non-optional). The comparison point is
Go's building & releasing: same
static-binary endgame, more moving parts on the way.
Key points
- Cross-compilation = target + linker:
rustup target addinstalls the stdlib for a triple, but unlike Go you also need a cross-linker for the target — the reason plaincargo build --targetfails whereGOOS=linux go buildjust works. - The workarounds are mature: cross (runs the build in Docker images with the right toolchains, QEMU for foreign-arch tests) and cargo-zigbuild (uses Zig's bundled clang as a universal cross-linker — the lightest path, glibc version targeting included).
- Fully-static Linux binaries:
--target x86_64-unknown-linux-musl— theFROM scratchcontainer play; watch for C dependencies (openssl → use rustls; oropenssl/vendored). - cargo-dist automates the release: from a git tag it builds a target matrix in CI, produces archives, shell/PowerShell installers, Homebrew formulae and npm shims, and publishes a GitHub release with checksums — the community-standard answer to "how do users install my Rust tool", GoReleaser's counterpart.
- cargo-release handles the other half — version bumps, changelog, tagging,
cargo publishordering across a workspace. - cargo-audit checks
Cargo.lockagainst the RustSec advisory database — the minimum bar, in every CI. - cargo-deny is the policy engine: advisories + license allow-lists + duplicate
version bans + registry/source restrictions, one
deny.toml, fail-the-build semantics. - cargo-vet (Mozilla) tackles what scanning can't: has a human reviewed this code? — records audits per crate version, lets organizations share and import each other's audit sets (Mozilla's, Google's), and fails on unvetted additions. cargo-crev is the older web-of-trust cousin.
- Why the vigilance:
build.rsand proc macros execute arbitrary code at build time on developer and CI machines — a typosquatted crate owns your laptop before the binary even runs. Lockfiles,--lockedin CI, minimal-dependency culture and vet/deny are the layered answer.
Details
Release pipeline, the house shape
rustup target add x86_64-unknown-linux-musl aarch64-apple-darwin
cargo zigbuild --release --target x86_64-unknown-linux-musl # or: cross build
cargo dist init # generates the CI release workflow
git tag v1.2.0 && git push --tags # cargo-dist takes it from here
CI gates alongside: cargo audit, cargo deny check, cargo vet (where adopted),
plus cargo build --locked so the lockfile is the build.
SBOM & provenance
cargo auditable embeds the dependency list into the binary itself (readable by
cargo audit bin); cargo-sbom/cyclonedx-rust produce standard SBOM documents;
crates.io has shipped provenance attestations for publishes from CI. Between the
immutable registry, lockfiles and these attestations, Rust's story now roughly matches
Go's sumdb-and-govulncheck posture — with cargo-vet as
the piece Go lacks.
Related
- The Rust build ecosystem — parent overview; the artifact formats being shipped here.
- Cargo in depth — profiles, lockfiles and publishing mechanics this pipeline drives.
- Security testing — where audit/deny/vet sit in the wider testing portfolio.
- Building & releasing Go — the effortless-cross-compilation contrast and GoReleaser.
- AppSec fundamentals — the SCA vocabulary and supply-chain concern these tools instantiate for Rust.