@@ -4,6 +4,10 @@
44, cargo
55, diffutils
66, fetchCargoTarball
7+, runCommandNoCC
8+, rustPlatform
9+, callPackage
10+, remarshal
711, git
812, rust
913, rustc
@@ -26,12 +30,15 @@
2630, cargoBuildFlags ? []
2731, buildType ? "release"
2832, meta ? {}
29−, target ? null
33+, target ? rust.toRustTargetSpec stdenv.hostPlatform
3034, cargoVendorDir ? null
3135, checkType ? buildType
3236, depsExtraArgs ? {}
3337, cargoParallelTestThreads ? true
3438
39+# Toggles whether a custom sysroot is created when the target is a .json file.
40+, __internal_dontAddSysroot ? false
41+
3542# Needed to `pushd`/`popd` into a subdir of a tarball if this subdir
3643# contains a Cargo.toml, but isn't part of a workspace (which is e.g. the
3744# case for `rustfmt`/etc from the `rust-sources).
@@ -69,13 +76,26 @@ let
6976 cargoDepsCopy="$sourceRoot/${cargoVendorDir}"
7077 '';
7178
72− rustTarget = if target == null then rust.toRustTarget stdenv.hostPlatform else target;
79+ targetIsJSON = stdenv.lib.hasSuffix ".json" target;
80+ useSysroot = targetIsJSON && !__internal_dontAddSysroot;
81+
82+ # see https://github.com/rust-lang/cargo/blob/964a16a28e234a3d397b2a7031d4ab4a428b1391/src/cargo/core/compiler/compile_kind.rs#L151-L168
83+ # the "${}" is needed to transform the path into a /nix/store path before baseNameOf
84+ shortTarget = if targetIsJSON then
85+ (stdenv.lib.removeSuffix ".json" (builtins.baseNameOf "${target}"))
86+ else target;
87+
88+ sysroot = (callPackage ./sysroot {}) {
89+ inherit target shortTarget;
90+ RUSTFLAGS = args.RUSTFLAGS or "";
91+ originalCargoToml = src + /Cargo.toml; # profile info is later extracted
92+ };
7393
7494 ccForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc";
7595 cxxForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++";
7696 ccForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
7797 cxxForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
78− releaseDir = "target/${rustTarget}/${buildType}";
98+ releaseDir = "target/${shortTarget}/${buildType}";
7999 tmpDir = "${releaseDir}-tmp";
80100
81101 # Specify the stdenv's `diff` by abspath to ensure that the user's build
@@ -85,7 +105,13 @@ let
85105
86106in
87107
88−stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
108+# Tests don't currently work for `no_std`, and all custom sysroots are currently built without `std`.
109+# See https://os.phil-opp.com/testing/ for more information.
110+assert useSysroot -> !(args.doCheck or true);
111+
112+stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // stdenv.lib.optionalAttrs useSysroot {
113+ RUSTFLAGS = "--sysroot ${sysroot} " + (args.RUSTFLAGS or "");
114+} // {
89115 inherit cargoDeps;
90116
91117 patchRegistryDeps = ./patch-registry-deps;
@@ -115,7 +141,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
115141 [target."${rust.toRustTarget stdenv.buildPlatform}"]
116142 "linker" = "${ccForBuild}"
117143 ${stdenv.lib.optionalString (stdenv.buildPlatform.config != stdenv.hostPlatform.config) ''
118− [target."${rustTarget}"]
144+ [target."${shortTarget}"]
119145 "linker" = "${ccForHost}"
120146 ${# https://github.com/rust-lang/rust/issues/46651#issuecomment-433611633
121147 stdenv.lib.optionalString (stdenv.hostPlatform.isMusl && stdenv.hostPlatform.isAarch64) ''
@@ -185,7 +211,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
185211 "CXX_${rust.toRustTarget stdenv.hostPlatform}"="${cxxForHost}" \
186212 cargo build -j $NIX_BUILD_CORES \
187213 ${stdenv.lib.optionalString (buildType == "release") "--release"} \
188− --target ${rustTarget} \
214+ --target ${target} \
189215 --frozen ${concatStringsSep " " cargoBuildFlags}
190216 )
191217
@@ -205,7 +231,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
205231 '';
206232
207233 checkPhase = args.checkPhase or (let
208− argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${rustTarget} --frozen";
234+ argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${target} --frozen";
209235 threads = if cargoParallelTestThreads then "$NIX_BUILD_CORES" else "1";
210236 in ''
211237 ${stdenv.lib.optionalString (buildAndTestSubdir != null) "pushd ${buildAndTestSubdir}"}