Rust/Cargo: cargo2nix VS crane VS dream2nix VS ...?

It seems like cargo2nix, crane, and dream2nix are the best, most mature builders for cargo/rust; is that right or are there better ones? What is the difference between them? What is the most solid/mature for a rust project that will be in development/maintenance for years?

cargo2nix seems the only one that makes a derivation per dependency (see 17275/11, 17275/13) as to make better UX for development/building; from Java/Maven experience in Nix, I know well the pain of fixed output derivations with all dependencies in a single derivation. cargo2nix also idealized integrating with dream2nix.

Seems like nix-cargo-integration uses dream2nix. dream2nix also seems interesting for its Node.js integration (I will likely use Node.js/Typescript as well).

I will likely try all them out by myself, but wanted some opinions from experienced users or who have some insight.

1 Like

No one can answer that right now.

AFAIK crane is good for local development but when deploying for production all the extra derivations and caching steps slow things down quite a bit.

1 Like

For a project (workspace with 19 crates) at work we are using cargo2nix.

After initial setup it’s convenient.

Just a cargo2nix -f Cargo.nix in the project root after any change to any Cargo.toml.

Only problem/inconvenience we had so far: If you want to use tokio-console you need to rebuild
your project with

[build]
rustflags = ["--cfg", "tokio_unstable"]

in the .cargo/config.toml file. That is not picked up by the version of cargo2nix we are using. You have to edit the generated
file by hand to make it happen.

1 Like

If you don’t need workspace support and don’t want to depend on dream2nix or crane/cargo2nix I recommend this flake template I made → https://github.com/Kranzes/nix-templates/blob/38dadb934b46e3dabc47612977f166bd7c55fd50/rust/flake.nix

If you do need workspace support and want faster builds via separate derivation caching (Crane) I recommend using dream2nix, dream2nix’s API/interface is significantly better than the native Crane one IMO.

A dream2nix template should look like this:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    flake-parts = { url = "github:hercules-ci/flake-parts"; inputs.nixpkgs-lib.follows = "nixpkgs"; };
    dream2nix = { url = "github:nix-community/dream2nix"; inputs.nixpkgs.follows = "nixpkgs"; };
  };

  outputs = inputs:
    inputs.flake-parts.lib.mkFlake { inherit inputs; } {
      systems = [ "x86_64-linux" ];
      imports = [ inputs.dream2nix.flakeModuleBeta ];

      perSystem = { pkgs, lib, ... }: {
        dream2nix.inputs.self.source = inputs.self;
      };
    };
}

I also suggest against using cargo2nix as it has the worst API and flakes support. Another thing worth reading is Crane’s author thoughts on per-crate caching and why it might not be worth it or reliably possible → Incremental builds of dependencies · ipetkov/crane · Discussion #213 · GitHub

1 Like

TL/DR: I don’t understand your opinion about cargo2nix.

A lot of the discussion in the link you posted comes down to the fact, that changing feature flags (which might happen by adding new dependencies, too) might result in a rebuild of more dependencies, than
just the directly affected ones.

I don’t see how that invalidates the benefit of only rebuilding, what needs to be rebuild.

For example we use aws-sdk-ec2 and syn which have really huge build times. Any tool creating a single derivation containing all the dependencies of our project, would force us to endure that build time
every time we make any change to a Cargo.toml. With cargo2nix we only need to rebuild those
monsters, when we do a general update of the versions of our dependencies.

Also, there might be some confusion of cargo2nix and crate2nix in that discussion.

cargo2nix uses cargo as a library. So it doesn’t need to recreate cargo, just translate its results into Nix expressions.

crate2nix uses the output of cargo metadata. I don’t know whether there is any knowledge about a project cargo doesn’t put into this output.

at 08:25:14 ❯ cargo metadata --help
Output the resolved dependencies of a package, the concrete used versions including overrides, in machine-readable format

Reads to me like, this should be the build plan.

A tool not using cargo would have to recreate a lot of its logic.

In the link you posted, ipetkov also writes

If you don’t care about using cargo then cargo2nix might be a great option!

1 Like

Sorry I was thinking of crate2nix not cargo2nix, these names are killing me :sweat_smile:.

2 Likes