As you can see, there are many options here. It can be difficult to decide! The wiki has a nice comparison table.
Most of these tools end up calling one of two different low-level primitives inside nixpkgs, which have unfortunately-not-very-descriptive names:
-
buildRustPackage
is for expressions which havecargo
drive the build.- a Rust binary package will build as one gigantic nix derivation which calls
cargo
on a tarball which vendors all the source code of all the crate’s dependencies. - There is no sharing of build effort between binary crates that share a common library dependency (i.e. the library is built two or more times).
- Builds are “monolithic” – if you change your source code or any of your crate’s dependencies (including adding a dependency), all of your crate’s dependencies are rebuilt.
- It is currently impossible to override a crate’s dependencies without running
cargo update
. This is a problem becausecargo update
accesses the network and cannot be run from inside a nix derivation. So if you want to override some pervasive dependency (like thering
cryptography library) in every rust package on your system you’re looking at doing a whole lot of work by hand, and then redoing that work every every time you pull from nixpkgs.
- a Rust binary package will build as one gigantic nix derivation which calls
-
buildRustCrate
is for expressions which havenix
drive the build.- Each Rust library (
.rlib
) gets its own derivation, in whichnix
callsrustc
directly. - Builds are incremental – only the libraries which change are rebuilt.
- Overriding dependencies is relatively easy; it works just like we’re used to with
.override
since the whole build plan is tree of nix derivations.
- Each Rust library (
It looks like dream2nix
uses buildRustPackage
.
I looked briefly at naersk
and crane
; it looks like each of them rolls its own equivalent of buildRustPackage
(i.e. they call cargo
and let it drive the build). So if you plan on submitting to nixpkgs at some point you would need to change tooling…
It looks like in both cases they are a tiny bit smarter than buildRustPackage
, creating two derivations instead of one: one monolithic derivation for all of your crate’s dependencies and a second one for your crate’s source code. So changing your crate’s source code will not trigger a world-rebuild. But changing or adding any of your dependencies will still rebuild all of your dependencies, and cargo
is in still driving the build.