It’s very similar to Naersk in the regard that it will build the entire workspace in one go. The unit of caching is the entire derivation itself, just like in Naersk.
The advantage over Naersk is that the nix API makes it much easier to compose different cargo invocations as completely separate derivations (you could do this with Naersk but you really have to understand all the internals to wire it all up right).
Here’s a quick flake example illustrating what you could do:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
crane.url = "github:ipetkov/crane";
crane.inputs.nixpkgs.follows = "nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
flake-utils.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, crane, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
};
craneLib = crane.lib.${system};
src = ./.;
# Build *just* the cargo dependencies, so we can reuse
# all of that work (e.g. via cachix) when running in CI
cargoArtifacts = craneLib.buildDepsOnly {
inherit src;
};
# Run clippy (and deny all warnings) on the crate source,
# resuing the dependency artifacts (e.g. from build scripts or
# proc-macros) from above.
#
# Note that this is done as a separate derivation so it
# does not impact building just the crate by itself.
my-crate-clippy = craneLib.cargoClippy {
inherit cargoArtifacts src;
cargoClippyExtraArgs = "-- --deny warnings";
};
# Build the actual crate itself, reusing the dependency
# artifacts from above.
my-crate = craneLib.buildPackage {
inherit cargoArtifacts src;
};
# Also run the crate tests under cargo-tarpaulin so that we can keep
# track of code coverage
my-crate-coverage = craneLib.cargoTarpaulin {
inherit cargoArtifacts src;
};
in
{
defaultPackage = my-crate;
checks = {
inherit
# Build the crate as part of `nix flake check` for convenience
my-crate
my-crate-clippy
my-crate-coverage;
};
});
}