lastlog.de/blog
  • timeline
  • about
  • draft
  • roadmap
  • websocket
prev. article
libnix

libnix - rust abstractions

11 apr 2025

nixosnixlibnix

motivation

status quo of rust support in nixpkgs 24.05.20241104.d063c1d (Uakari)!

but first we recap how vanilla cargo workflow (no abstracted for nix) works:

  1. rustup installs the toolchain
  2. cargo build checks the Cargo.toml/Cargo.lock
  3. creates a target/ folder to work in
  4. creates a local crates.io registry copy in ~/.cargo/registry/
  5. builds all dependencies in target/debug/deps
  6. builds the program in target/debug/myprogram

the programmer has to take care of the target/ and ~/.cargo/ folder and there is no crates build artifacts sharing between different projects, let alone users.

rust support in nixpkgs

nixpkgs features:

  • one version of rust stable, 1.84, at time of writing
  • shipping 2159 rust applications using the buildRustPackage function from rustPlatform by wrapping cargo/rustc
  • a buildRustCrate implementation

this way nixpkgs supports 2159 rust applications, at time of this writing.

nixpkgs> git grep buildRustPackage *.nix | wc -l
2159

using buildRustPackage

buildRustPackage calls cargo which then calls rustc.

{ lib, stdenv, rustPlatform, fetchFromGitHub, pkg-config, openssl, libiconv,
  CoreServices, Security, SystemConfiguration
}:

rustPlatform.buildRustPackage rec {
  pname = "trunk";
  version = "0.21.1";

  src = fetchFromGitHub {
    owner = "trunk-rs";
    repo = "trunk";
    rev = "v${version}";
    sha256 = "sha256-6EuSz7bFlL49l5gjoKCyRTfAWiwIHFdG0t+StvGj7f8=";
  };

  nativeBuildInputs = [ pkg-config ];
  buildInputs = if stdenv.isDarwin
    then [ libiconv CoreServices Security SystemConfiguration]
    else [ openssl ];

  # requires network
  checkFlags = [ "--skip=tools::tests::download_and_install_binaries" ];

  cargoHash = "sha256-NfGDra5xHVY04CofTriCUspLY3f4Tiq6Wm9ON0K8jwY=";

  postConfigure = ''
    cargo metadata --offline
  '';

  meta = with lib; {
    homepage = "https://github.com/trunk-rs/trunk";
    description = "Build, bundle & ship your Rust WASM application to the web";
    maintainers = with maintainers; [ freezeboy flosse ];
    license = with licenses; [ asl20 ];
  };
}

when installing trunk, this abstraction:

  • creates a trunk-0.21.1-vendor.tar.gz with all the cargo libraries contained in this one file and
  • on each failing crate dependency it has to recompile all crate dependencies again.

using buildRustCrate

buildRustCrate replaces cargo and is used by crate2nix but not very much from nixpkgs itself.

See buildRustPackage implementation.

summary of nixpkgs support

the buildRustPackage, works remarkably well but there are many aspects where it lacks and motivates for projects like: crane, naersk, cargo2nix and crate2nix as well as drop-in toolchain replacements like oxalica/rust-overlay and fenix.

installing cargo/rustc toolchain(s)

this is like rustup: these projects bring rustc/cargo to your system so you can start developing ‘imperatively’ pretty similar to windows, linux and mac or you can use buildRustPackage!

# name stars toolchains commits open issues closed issues notes
1 nixpkgs ? stable ? ? ? nixpkgs built-in toolchain (using cargo),
built on hydra, also wraps cargo
2 oxalica/rust-overlay 830 stable, beta, nightly 1469 6 120 drop-in replacement to install different rust versions
3 fenix 620 stable, beta, nightly 1949 24 50 drop-in replacement to install different rust versions
4 nixpkgs-mozilla 511 ? 264 49 88 obsolete,
drop-in replacement to install different rust versions

Oxalica and fenix: both projects provides a similar set of packages and overlays under different APIs.

  • Oxalica’s overlay allows you to select a particular Rust version without you providing a hash or a flake input, but comes with a larger git repository than fenix.
  • Fenix also provides rust-analyzer nightly in addition to the Rust toolchains.

Both oxalica’s overlay and fenix better integrate with nix and cache optimizations. Because of this and ergonomics, either of those community projects should be preferred to the Mozilla’s Rust overlay (nixpkgs-mozilla).

drop-in replacements for buildRustPackage

# name stars tagged
releases
commits open
issues
closed
issues
evaluator store entry
per crate
download
store entry
per crate
build
custom
registry
support
IFD
implications
support tool
1 crane 819 52 601 21 202 craneLib.mkDummySrc yes yes yes no no
2 naersk 677 0 345 50 110 naersk.buildPackage yes no no no no
3 cargo2nix 407 14 633 62 118 rustBuilder.makePackageSet yes yes yes no cargo2nix creates Crates.nix
4 create2nix 338 10 1336 80 110 buildRustCrate (from nixpkgs) yes yes no yes in fallback mode, otherwise no crate2nix creates Cargo.nix

experiments

the experiments are at https://github.com/qknight/rust-nix-abstraction-tests

see:

  • cargo2nix
  • crate2nix
  • naersk
  • crane

to reproduce and play with the abstractions do:

  • clone the repo

    git clone https://github.com/qknight/rust-nix-abstraction-tests
  • list all related store activity:

    cd cargo2nix
    nix path-info --derivation --recursive .#default
  • hiearchically browse the store

    cd cargo2nix
    nix path-info --derivation --recursive .#default | grep trunk
    ... use the output to learn the exact store path ...
    nix-tree --derivation /nix/store/6ibmcbvb5wccaf2gpjpxlnhzja4r3qp0-trunk-0.21.4.drv

drop-in replacements for buildRustPackage (obsolete)

# name stars commits language notes
1 rust2nix 8 12 rust obsolete
2 carnix 10 43 pure nix obsolete,
3 nixcrates 15 63 rust obsolete, build crates (with custom cargo reimplementation written in rust),
lacks proper semver dependencies

summary

rust/cargo support in nix has come a long way and while there are over 2k rust-projects in nixpkgs, the nixpkgs abstraction is fairly limited and favours ease of deployment over a good developer experience.

  • tools like crane and naersk can be used like buildRustCrate.
  • cargo2nix and crate2nix try to replace later calls to cargo by creating a pure nix build system.

all in all, these abstractions require deep nix knowledge if something goes wrong and at times require lots of extra work from the developers and potentially lock-in into Nix and NixOS.

it sets the stage for a different concept: using nix directly from cargo. that will be the focus of the next article in the libnix series.

article source