From a6fc69fe4069e804f66e01b02e382f39963bcfd2 Mon Sep 17 00:00:00 2001 From: Bernardo Meurer Date: Tue, 19 May 2026 10:16:51 -0400 Subject: [PATCH] buildRustCrate: add devDependencies parameter for buildTests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cargo links [dev-dependencies] only when building test or bench targets. buildRustCrate models normal deps (`dependencies`) and build-script deps (`buildDependencies`) but has no equivalent: callers that set `buildTests = true` for a crate with dev-deps must compute the dev-dep set themselves and splice it into `dependencies` via .override. Add a `devDependencies` parameter that is appended to the linked dependency list only when `buildTests = true`. The append happens at the single point where `dependencies` is normalized, so it threads through to the --extern flags, the deps directory in configurePhase, the metadata hash, and propagated build inputs without further changes. When `buildTests = false` the parameter is dropped, so existing lib/bin derivations are byte-identical to before — no rebuilds for users that don't pass it. Includes a test case in build-rust-crate/test that fails without the change (`can't find crate for dev_dep`). --- .../rust/build-rust-crate/default.nix | 15 ++++++++++++- .../rust/build-rust-crate/test/default.nix | 21 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix index af1ec421da9b..e3dbde5d2f16 100644 --- a/pkgs/build-support/rust/build-rust-crate/default.nix +++ b/pkgs/build-support/rust/build-rust-crate/default.nix @@ -198,6 +198,13 @@ lib.makeOverridable # Rust build dependencies, i.e. other libraries that were built # with buildRustCrate and are used by a build script. buildDependencies, + # Rust dev-dependencies, i.e. other libraries that were built + # with buildRustCrate and are linked only when `buildTests = true`. + # Mirrors Cargo's `[dev-dependencies]`: ignored for the regular + # lib/bin build, appended to `dependencies` for the test build. + # + # Default: [] + devDependencies, # Specify the "extern" name of a library if it differs from the library target. # See above for an extended explanation. # @@ -323,6 +330,7 @@ lib.makeOverridable crate = crate_ // (lib.attrByPath [ crate_.crateName ] (attr: { }) crateOverrides crate_); dependencies_ = dependencies; buildDependencies_ = buildDependencies; + devDependencies_ = devDependencies; processedAttrs = [ "src" "propagatedBuildInputs" @@ -334,6 +342,7 @@ lib.makeOverridable "libPath" "buildDependencies" "dependencies" + "devDependencies" "features" "crateRenames" "crateName" @@ -421,7 +430,10 @@ lib.makeOverridable ++ (crate.buildInputs or [ ]) ++ buildInputs_ ++ completePropagatedBuildInputs; - dependencies = map lib.getLib dependencies_; + # Dev-dependencies are only linked when building tests, mirroring + # Cargo. When buildTests is false this is a no-op, so the metadata + # hash and store path of normal lib/bin builds are unchanged. + dependencies = map lib.getLib (dependencies_ ++ lib.optionals buildTests_ devDependencies_); buildDependencies = map lib.getLib buildDependencies_; completeDeps = lib.unique (dependencies ++ lib.concatMap (dep: dep.completeDeps) dependencies); @@ -617,6 +629,7 @@ lib.makeOverridable postInstall = crate_.postInstall or ""; dependencies = crate_.dependencies or [ ]; buildDependencies = crate_.buildDependencies or [ ]; + devDependencies = crate_.devDependencies or [ ]; crateRenames = crate_.crateRenames or { }; buildTests = crate_.buildTests or false; } diff --git a/pkgs/build-support/rust/build-rust-crate/test/default.nix b/pkgs/build-support/rust/build-rust-crate/test/default.nix index 75a483a0096f..13c52a44c079 100644 --- a/pkgs/build-support/rust/build-rust-crate/test/default.nix +++ b/pkgs/build-support/rust/build-rust-crate/test/default.nix @@ -404,6 +404,27 @@ rec { "test something ... ok" ]; }; + rustLibTestsWithDevDependency = + let + devDep = mkHostCrate { + crateName = "dev-dep"; + src = mkLib "src/lib.rs"; + }; + in + { + src = mkFile "src/lib.rs" '' + #[cfg(test)] + mod tests { + #[test] + fn uses_dev_dep() { + assert_eq!(dev_dep::test(), 23); + } + } + ''; + devDependencies = [ devDep ]; + buildTests = true; + expectedTestOutputs = [ "test tests::uses_dev_dep ... ok" ]; + }; rustBinTestsCombined = { src = symlinkJoin { name = "rust-bin-tests-combined";