Nix Workspace Rust #
The Rust build for nix-workspace: a plain-nixpkgs build of a crate, a devshell carrying the pre-commit hooks the monorepo holds it to, and a formatter.
Its own flake, because the framework knows no language, but a directory of the
same repo rather than a repo of its own: one history, and a module that cannot
drift from the framework it extends. Declaring this input is the whole of
taking it - nix-workspace imports the workspaceModule any input exports -
and a tree that does not declare it carries nothing Rust-shaped.
{
description = "A GNU sed-compatible stream editor written in Rust";
inputs = {
workspace.url = "git+https://tangled.org/overby.me/nix-workspace";
rust = {
url = "git+https://tangled.org/overby.me/nix-workspace?dir=modules/rust";
inputs.workspace.follows = "workspace";
};
};
outputs = inputs:
inputs.workspace {
inherit inputs;
};
}
That is the whole file. The crate is read from its own Cargo.toml, so
nothing here restates a name, a version or a binary, and the result is
packages.default, a checks.packages-default, an overlay entry and a
devshell.
workspace follows through, so the framework and this are one flake in the
lock rather than two copies of it. git-hooks arrives the same way and is never
declared here.
Options #
All under rust.
| option | default | for |
|---|---|---|
pname |
the crate's own name, else the first workspace member's | what to call the derivation; cosmetic, since the output is packages.default |
description |
the flake's own | the package's meta.description |
root |
the flake's directory | where the Cargo.toml is read from |
subdir |
"" |
the crate is one level down |
nativeBuildInputs |
[] |
nixpkgs attribute names of build-time tools |
buildInputs |
[] |
nixpkgs attribute names of libraries linked against |
env |
_: {} |
build-time environment, as a function of pkgs |
toolchain |
a rust-toolchain.toml is present |
take rustc from that file |
aliases |
{} |
extra names for a binary the crate builds |
setupHook |
null |
a file installed as nix-support/setup-hook |
hooks |
seven | the pre-commit hooks nix develop installs |
Build inputs are nixpkgs attribute names rather than packages, because the generator that writes these flakes reads them out of a project list and has no package set to resolve them against.
subdir exists because a crate whose Cargo.toml has a path dependency on a
sibling is published as several directories, so that path = "../pcre2" still
resolves. Its own crate is then one level down, and the build needs both
cargoRoot and buildAndTestSubdir, which do different jobs.
aliases are the names a drop-in replacement also answers to - gawk beside
awk, and all thirty-four of PipeWire's tool names for one multicall binary.
Cargo builds only what Cargo.toml declares as a [[bin]], so without them a
clone ships a binary under none of the names it dispatches on. The target must
be a binary cargo built, not another alias, and a target that is not there is
an error rather than a dangling symlink.
setupHook is the same gap one step further along: a tool replacing part of
stdenv is not usable by being on PATH. pkg-config earns its place by a hook
that exports PKG_CONFIG_PATH, and without one a build that lists it gets a
binary that finds nothing.
toolchain exists for compiler plugins: they link against rustc's internals,
whose API differs between releases, so they need the exact nightly named in
their own rust-toolchain.toml rather than whatever rustc nixpkgs ships.
Having that file is the request, so it is read rather than declared. What
cannot be derived is the rust-overlay overlay that provides rust-bin,
which the consuming flake supplies:
outputs = inputs:
inputs.workspace {
inherit inputs;
withOverlays = [inputs.rust-overlay.overlays.default];
};
An overlay is its own flake, so carrying it here would make every published repo fetch it for the one project that pins a toolchain.
The fine-grained build #
Declaring nix-lib as an input
switches the build to that flake's buildCargoProject: one derivation per
crate against a committed index, rather than one rustPlatform derivation for
the whole tree. Declaring the input is the whole of opting in.
It runs tests as passthru derivations rather than inside the package build, so
this adds a checks.tests that builds them - otherwise nix flake check goes
green having built none.
aliases and setupHook are not supported there and fail loudly rather than
being dropped.
Contributing #
See nix-workspace, whose repo this is a directory of.
It was split out of the framework, which shipped this as its
workspaceModules.default and imported it for any call carrying a name.
That made the framework demand a package name from every tree that took it,
and made it the one input its own module-finding had to skip.