Add Nix flake: crane + fenix build, treefmt-nix formatting

Uses flake-parts to organize outputs, with nix/rust.nix defining a
single craneLib/toolchain/commonArgs environment shared by the package
build (nix/rust.nix) and the dev shell (nix/devshell.nix), so both stay
close to identical. Deps are cached separately from the crate itself via
crane's buildDepsOnly, giving incremental rebuilds. Checks cover clippy,
rustfmt, cargo-doc, cargo-audit, and nextest; treefmt-nix wires up
`nix fmt` for Rust/Nix/TOML files.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ALEXkc7pTro7tF1WcUuKb
This commit is contained in:
2026-08-10 23:58:00 +08:00
parent 979e77571f
commit 840cea1f10
6 changed files with 393 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
# Dev shell built from the same craneLib/toolchain as the package build
# (nix/rust.nix), so the environment developers see locally matches what
# `nix build` uses as closely as possible.
{
pkgs,
lib,
rust,
}:
rust.craneLib.devShell {
inherit (rust) checks;
packages =
with pkgs;
[
cargo-nextest
cargo-criterion
cargo-audit
cargo-expand
taplo
bacon
]
++ lib.optionals pkgs.stdenv.isLinux [ mold ]
++ lib.optionals pkgs.stdenv.isDarwin [
libiconv
darwin.apple_sdk.frameworks.Security
darwin.apple_sdk.frameworks.SystemConfiguration
];
shellHook = ''
export RUST_SRC_PATH="${rust.rustToolchain}/lib/rustlib/src/rust/library"
''
+ lib.optionalString pkgs.stdenv.isLinux ''
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="clang"
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=-fuse-ld=mold"
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="clang"
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=-fuse-ld=mold"
'';
}
+103
View File
@@ -0,0 +1,103 @@
# Shared Rust build environment: toolchain, craneLib, source filtering,
# and cached dependency artifacts. Consumed by both the package build
# (nix/package.nix, implicit below) and the dev shell (nix/devshell.nix)
# so the two stay close to identical.
{
inputs,
pkgs,
system,
lib,
}:
let
fenixPkgs = inputs.fenix.packages.${system};
rustToolchain = fenixPkgs.stable.withComponents [
"cargo"
"clippy"
"llvm-tools"
"rust-analyzer"
"rust-src"
"rustc"
"rustfmt"
];
craneLib = (inputs.crane.mkLib pkgs).overrideToolchain (_: rustToolchain);
src = craneLib.cleanCargoSource ./..;
commonArgs = {
inherit src;
strictDeps = true;
nativeBuildInputs = [
pkgs.pkg-config
]
++ lib.optionals pkgs.stdenv.isLinux [
pkgs.clang
pkgs.mold
];
buildInputs = lib.optionals pkgs.stdenv.isDarwin [
pkgs.libiconv
pkgs.darwin.apple_sdk.frameworks.Security
pkgs.darwin.apple_sdk.frameworks.SystemConfiguration
];
};
# Built once, reused by the package build, clippy, doc, and nextest —
# this is what makes incremental rebuilds fast under crane.
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
package = craneLib.buildPackage (
commonArgs
// {
inherit cargoArtifacts;
pname = "rust_template";
doCheck = false; # exercised separately via checks.nextest
}
);
checks = {
clippy = craneLib.cargoClippy (
commonArgs
// {
inherit cargoArtifacts;
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
}
);
doc = craneLib.cargoDoc (
commonArgs
// {
inherit cargoArtifacts;
env.RUSTDOCFLAGS = "--deny warnings";
}
);
fmt = craneLib.cargoFmt { inherit src; };
audit = craneLib.cargoAudit {
inherit src;
inherit (inputs) advisory-db;
};
nextest = craneLib.cargoNextest (
commonArgs
// {
inherit cargoArtifacts;
partitions = 1;
partitionType = "count";
}
);
};
in
{
inherit
craneLib
commonArgs
cargoArtifacts
package
checks
rustToolchain
;
}
+14
View File
@@ -0,0 +1,14 @@
# treefmt-nix module: wires up `nix fmt` and the `formatting` check.
_: {
perSystem = _: {
treefmt = {
projectRootFile = "flake.nix";
programs.rustfmt.enable = true;
programs.nixfmt.enable = true;
programs.deadnix.enable = true;
programs.statix.enable = true;
programs.taplo.enable = true;
};
};
}