Comparing solutions for building Rust on Nix

By my count, there are now no less than 6 different solutions for building Rust code with Nix. In an effort to help people choose one, and start a discussion on hopefully standardizing on something to include in Nixpkgs, here’s my effort to compare what’s out there. I should note that most of this information is based on documentation and occasional peeks at the code; I haven’t actually tested most of these solutions.

Here’s what all the columns mean:

  • Cargo.lock solution: How does this solution handle reproducibly determining what crates need to be downloaded from the Cargo.lock file? “Checksum” means it requires you to specify the checksum of all the downloaded dependencies. “Import” means it dynamically imports and parses Cargo.lock from a Nix expression, which means Cargo.lock needs to be present in the same repository as the nix expressions (or IFD must be used). “Codegen” means it generates a .nix file from the Cargo.lock, which is then committed to source control.
  • Derivations: How many derivations does this solution use to compile rust code? “1” means the project and all its dependencies are compiled in one derivation. “2” means all dependencies are moved into a separate derivation, so the project can be updated independently, but any change to the set of dependencies rebuilds everything. “Many” means each dependency is built in its own derivation, so changes to dependencies only do the minimal amount of rebuilding necessary (and, ideally, different projects can share dependences, although I haven’t checked if this works in practice).
  • Build logic: How does this solution orchestrate building of crates? “Cargo” means it relies on Cargo; buildRustCrate means it uses Nixpkgs’ buildRustCrate; “custom” means it uses its own custom logic (in Nix)
  • Supports cross: Does the solution allow for cross-compilation of crates?
Name Cargo.lock solution Derivations Build logic Supports cross Notes
buildRustPackage Checksum 1 cargo Yes Built into nixpkgs
carnix Codegen Many buildRustCrate No? Unmaintained, AFAICT; repository is gone
crate2nix Codegen (with optional IFD) Many buildRustCrate No Spiritual successor to carnix; nobody currently spending much time maintaining it
naersk Import 2 cargo No? Seems to only support building on x86
cargo2nix Codegen Many Custom Yes Seems to only support prebuilt rustc from the nixpkgs-mozilla overlay, not rustc provided by Nixpkgs
import-cargo Import 1 cargo Unclear More of a proof of concept than a full working solution
18 Likes

Thanks for the nice overview! Note that crate2nix should probably have Codegen/Import, since it can also use IFD without a pregenerated Cargo.nix. An example of one of my projects that uses crate2nix with IFD:

Thanks! I changed it to “codegen (with optional IFD)”. In my mind, import is something slightly different—it means loading and parsing the Crate.lock in pure nix code, with no IFD (although IFD might be needed in a Nixpkgs sort of situation where the Cargo.lock and the nix code are in different repos).

1 Like

It would be nice to have one more column: “support upstreams which are happy with broken Cargo.lock”, to pick that solution for cases like vector in vector: 0.10.0 -> 0.11.0 by happysalada · Pull Request #107557 · NixOS/nixpkgs · GitHub

Thanks for doing this, is there a reason you marked import-cargo as “proof of concept”? I’ve been using it for a bit and haven’t run into any issues yet (unless you consider having to use flakes an issue). Like you, I’m also am interested in looking at other possible solutions in the future, but haven’t found anything that seems like it’s the way to go yet.

Thanks for doing this, it’s definite good to have, maybe even in the wiki?

It’s a special case but it may be important to point out that codegen-units = 1 can not be honored in the case of multiple derivations, which at least for performance critical applications, can sometimes illicit a statistically significant improvement.