Chapter 19: rust, how crates reach the build
In an ordinary Rust project, cargo reads Cargo.toml, downloads the
crates and builds everything. Here buck2 builds everything (the C bot
included), and buck2 does not read Cargo.toml. Something has to translate.
That something is reindeer.
flowchart LR toml["Cargo.toml (hand-written)"] --> lock["Cargo.lock (resolved)"] lock --> reindeer["reindeer buckify"] fix["fixups/ and reindeer.toml"] --> reindeer reindeer --> buck["BUCK (generated): one target per crate"] buck --> code["first-party code: //third-party/rust:<crate>"]
Cargo.toml here is not a real package anybody builds with cargo. It is a
list of every third-party crate the project uses, with versions and
features, and a comment on most of them saying why. reindeer resolves it,
and writes BUCK: about four hundred http_archive downloads (crates are
fetched at build time, pinned by Cargo.lock, not vendored into git) and a
rust_library for each. First-party code then depends on, say,
//third-party/rust:egui.
Three crates are not from crates.io at all:
- jgenesis (
jgenesis/), the emulator, as a git subtree of jsgroth/jgenesis (GPL-3.0) from upstreamd19ee94f. This project uses itssnes-core,snes-configandjgenesis-commoncrates as path dependencies. It carries two commits of ours: "jgenesis: expose work RAM from snes-core" (SnesEmulator::wram()) and "jgenesis: let a host write work RAM" (wram_mut(), for the bot's cheats). - jevcrates (
jevcrates/), a git submodule:jev-protocol,jev-clientandjev-http, the code every Jev project here shares. It came out of this repository (aspackages/jevandpackages/jev-http) on 2026-10-01. Its URL in.gitmodulesis relative (../jevcrates.git), so it resolves beside wherever this repository was cloned from, which is whygit clone --recurse-submodulesfrom the lmjtfy site works. - rustls-rustcrypto, from its git repository's
masterbranch.
Aside: why so much effort to avoid C?
jev-httpspeaks HTTP/2 over rustls with the pure-Rust RustCrypto provider, and replay keyframes are compressed withruzstd, a pure-Rust zstd. Every C dependency is a build script finding a system library, and every one of those is a way for a build to fail on a machine that is not this one.alsa-sys(sound) is the one crate that links a system library at build time; the window's wayland, xkbcommon, X11, Vulkan and GL are opened at startup instead.
Try it. After changing
Cargo.toml:nix develop -c sh -c 'cd third-party/rust && reindeer --third-party-dir . buckify'then
git diff --stat third-party/rust/BUCKto see what moved.
For the people who maintain it
In this folder
| Path | What |
|---|---|
| fixups/ | Chapter 20: per-crate answers reindeer cannot infer, chiefly whether a crate's build.rs must run. |
| top/ | Chapter 21: the empty crate root the manifest needs in order to be a package. |
| Cargo.toml | The dependency list. The only file here edited by hand to add or bump a crate. |
| Cargo.lock | The resolution. Committed. |
| BUCK | GENERATED by reindeer. Never edited by hand. |
| reindeer.toml | Reindeer's settings: cargo_env = true, so every crate gets the CARGO_PKG_* variables cargo would set. |
| README.md | This chapter. |
| CLAUDE.md | What breaks the generated graph, for agents. |
| jgenesis/ | The emulator, a git subtree. No chapter: upstream's own docs describe it, and a subtree pull would be the only thing keeping ours honest. |
| jevcrates | The Jev crates, a git submodule with a guide of its own. No chapter here. |
← Previous: Chapter 18, patches/ · Up: third-party · Next: Chapter 20, fixups/ →