buildRustCrate: support propagatedBuildInputs in crate overrides (#503956)

This commit is contained in:
Florian Klink
2026-05-09 11:50:38 +00:00
committed by GitHub
2 changed files with 76 additions and 1 deletions
@@ -325,6 +325,7 @@ lib.makeOverridable
buildDependencies_ = buildDependencies;
processedAttrs = [
"src"
"propagatedBuildInputs"
"nativeBuildInputs"
"buildInputs"
"crateBin"
@@ -418,7 +419,8 @@ lib.makeOverridable
buildInputs =
lib.optionals stdenv.hostPlatform.isDarwin [ libiconv ]
++ (crate.buildInputs or [ ])
++ buildInputs_;
++ buildInputs_
++ completePropagatedBuildInputs;
dependencies = map lib.getLib dependencies_;
buildDependencies = map lib.getLib buildDependencies_;
@@ -428,6 +430,16 @@ lib.makeOverridable
++ lib.concatMap (dep: dep.completeBuildDeps ++ dep.completeDeps) buildDependencies
);
# Propagated native build inputs from this crate and all transitive Rust
# dependencies. Analogous to completeDeps but for native library deps:
# a crate can declare `propagatedBuildInputs` in its override and they
# will automatically be added to the buildInputs of every crate that
# depends on it, without having to repeat them up the dependency tree.
completePropagatedBuildInputs = lib.unique (
(crate.propagatedBuildInputs or [ ])
++ lib.concatMap (dep: dep.completePropagatedBuildInputs or [ ]) dependencies
);
# Create a list of features that are enabled by the crate itself and
# through the features argument of buildRustCrate. Exclude features
# with a forward slash, since they are passed through to dependencies,
@@ -1060,6 +1060,69 @@ rec {
test -x '${pkg}/bin/rcgen' && touch $out
''
);
# Test that propagatedBuildInputs declared in a crate override are
# collected by completePropagatedBuildInputs and propagate transitively
# to all crates that depend on it.
propagatedBuildInputsTest =
let
fakeNativeLib = runCommand "fake-native-lib" { } "mkdir -p $out/lib && touch $out/lib/libfoo.a";
# Library crate that declares a native dep via propagatedBuildInputs
libCrate = mkHostCrate {
crateName = "mylib";
src = mkLib "src/lib.rs";
propagatedBuildInputs = [ fakeNativeLib ];
};
# Binary crate with a direct dependency on libCrate
binCrate = mkHostCrate {
crateName = "mybin";
src = mkFile "src/main.rs" "fn main() {}";
dependencies = [ libCrate ];
};
# Intermediate library that depends on libCrate
transitiveLib = mkHostCrate {
crateName = "transitivelib";
src = mkLib "src/lib.rs";
dependencies = [ libCrate ];
};
# Binary crate that only depends on transitiveLib (not libCrate directly)
transitiveBin = mkHostCrate {
crateName = "transitivebin";
src = mkFile "src/main.rs" "fn main() {}";
dependencies = [ transitiveLib ];
};
in
runCommand "propagated-build-inputs-test"
{
libCrateInputs = libCrate.completePropagatedBuildInputs;
binCrateInputs = binCrate.completePropagatedBuildInputs;
transitiveBinInputs = transitiveBin.completePropagatedBuildInputs;
}
''
# libCrate itself should have fakeNativeLib in completePropagatedBuildInputs
echo "$libCrateInputs" | grep -q "${fakeNativeLib}" || {
echo "ERROR: fakeNativeLib not in libCrate.completePropagatedBuildInputs"
exit 1
}
# binCrate depends on libCrate, so fakeNativeLib should propagate
echo "$binCrateInputs" | grep -q "${fakeNativeLib}" || {
echo "ERROR: fakeNativeLib not propagated to binCrate.completePropagatedBuildInputs"
exit 1
}
# transitiveBin transitiveLib libCrate: fakeNativeLib should propagate transitively
echo "$transitiveBinInputs" | grep -q "${fakeNativeLib}" || {
echo "ERROR: fakeNativeLib not transitively propagated to transitiveBin.completePropagatedBuildInputs"
exit 1
}
touch $out
'';
}
);
test = releaseTools.aggregate {