rustc: add a compiler wrapper

We keep running into situations where we can't get the right
combination of rustc flags through build systems into rustc.
RUSTFLAGS is the only variable supported across build systems, but if
RUSTFLAGS is set, Cargo will ignore all other ways of specifying rustc
flags, including the target-specific ones, which we need to make
dynamic musl builds work.  (This is why pkgsCross.musl64.crosvm is
currently broken — it works if you unset separateDebugInfo, which
causes RUSTFLAGS not to be set.)

So, we need to do the same thing we do for C and C++ compilers, and
add a compiler wrapper so we can inject the flags we need, regardless
of the build system.

Currently the wrapper only supports a single mechanism for injecting
flags — the NIX_RUSTFLAGS environment variable.  As time goes on,
we'll probably want to add additional features, like target-specific
environment variables.
This commit is contained in:
Alyssa Ross 2023-10-18 11:02:45 +00:00 committed by Adam Joseph
parent c6f3c0403f
commit 8b51cdd3be
9 changed files with 61 additions and 14 deletions

View file

@ -963,7 +963,7 @@ repository:
lib.updateManyAttrsByPath [{
path = [ "packages" "stable" ];
update = old: old.overrideScope(final: prev: {
rustc = prev.rustc.overrideAttrs (_: {
rustc-unwrapped = prev.rustc-unwrapped.overrideAttrs (_: {
src = lib.cleanSource /git/scratch/rust;
# do *not* put passthru.isReleaseTarball=true here
});
@ -1003,4 +1003,3 @@ nix-build $NIXPKGS -A package-broken-by-rust-changes
The `git submodule update --init` and `cargo vendor` commands above
require network access, so they can't be performed from within the
`rustc` derivation, unfortunately.

View file

@ -0,0 +1,29 @@
{ lib, runCommand, rustc-unwrapped }:
runCommand "${rustc-unwrapped.pname}-wrapper-${rustc-unwrapped.version}" {
preferLocalBuild = true;
strictDeps = true;
inherit (rustc-unwrapped) outputs;
env = {
prog = "${rustc-unwrapped}/bin/rustc";
};
passthru = {
inherit (rustc-unwrapped) pname version src llvm llvmPackages;
unwrapped = rustc-unwrapped;
};
meta = rustc-unwrapped.meta // {
description = "${rustc-unwrapped.meta.description} (wrapper script)";
priority = 10;
};
} ''
mkdir -p $out/bin
ln -s ${rustc-unwrapped}/bin/* $out/bin
rm $out/bin/rustc
substituteAll ${./rustc-wrapper.sh} $out/bin/rustc
chmod +x $out/bin/rustc
${lib.concatMapStrings (output: "ln -s ${rustc-unwrapped.${output}} \$${output}\n")
(lib.remove "out" rustc-unwrapped.outputs)}
''

View file

@ -0,0 +1,11 @@
#!@shell@
# Optionally print debug info.
if (( "${NIX_DEBUG:-0}" >= 1 )); then
echo "original flags to @prog@:" >&2
printf " %q\n" "$@" >&2
echo "extra flags after to @prog@:" >&2
printf " %q\n" $NIX_RUSTFLAGS >&2
fi
exec @prog@ "$@" $NIX_RUSTFLAGS

View file

@ -16,6 +16,7 @@
, CoreFoundation, Security, SystemConfiguration
, pkgsBuildTarget, pkgsBuildBuild, pkgsBuildHost
, makeRustPlatform
, wrapRustc
, llvmPackages_16, llvm_16
} @ args:

View file

@ -1,4 +1,4 @@
{ lib, stdenv, makeWrapper, bash, curl, darwin, zlib
{ lib, stdenv, makeWrapper, wrapRustc, bash, curl, darwin, zlib
, autoPatchelfHook, gcc
, version
, src
@ -19,7 +19,7 @@ let
in
rec {
rustc = stdenv.mkDerivation {
rustc-unwrapped = stdenv.mkDerivation {
pname = "rustc-${versionType}";
inherit version;
@ -61,6 +61,8 @@ rec {
setupHooks = ./setup-hook.sh;
};
rustc = wrapRustc rustc-unwrapped;
cargo = stdenv.mkDerivation {
pname = "cargo-${versionType}";

View file

@ -11,7 +11,7 @@ rustPlatform.buildRustPackage.override {
cargo-auditable = cargo-auditable.bootstrap;
} ({
pname = "cargo";
inherit (rustc) version src;
inherit (rustc.unwrapped) version src;
# the rust source tarball already has all the dependencies vendored, no need to fetch them again
cargoVendorDir = "vendor";

View file

@ -18,6 +18,7 @@
, CoreFoundation, Security, SystemConfiguration
, pkgsBuildBuild
, makeRustPlatform
, wrapRustc
}:
let
@ -64,7 +65,7 @@ in
buildRustPackages = (selectRustPackage buildPackages).packages.stable;
# Analogous to stdenv
rustPlatform = makeRustPlatform self.buildRustPackages;
rustc = self.callPackage ./rustc.nix ({
rustc-unwrapped = self.callPackage ./rustc.nix ({
version = rustcVersion;
sha256 = rustcSha256;
inherit enableRustcDev;
@ -75,6 +76,7 @@ in
# Use boot package set to break cycle
inherit (bootstrapRustPackages) cargo rustc rustfmt;
});
rustc = wrapRustc self.rustc-unwrapped;
rustfmt = self.callPackage ./rustfmt.nix {
inherit Security;
inherit (self.buildRustPackages) rustc;

View file

@ -154,9 +154,9 @@ in stdenv.mkDerivation (finalAttrs: {
runHook preBuild
mkdir -p build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-{std,rustc}/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/
ln -s ${rustc}/lib/rustlib/${stdenv.hostPlatform.rust.rustcTargetSpec}/libstd-*.so build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-std/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/libstd.so
ln -s ${rustc}/lib/rustlib/${stdenv.hostPlatform.rust.rustcTargetSpec}/librustc_driver-*.so build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/librustc.so
ln -s ${rustc}/bin/rustc build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/rustc-main
ln -s ${rustc.unwrapped}/lib/rustlib/${stdenv.hostPlatform.rust.rustcTargetSpec}/libstd-*.so build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-std/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/libstd.so
ln -s ${rustc.unwrapped}/lib/rustlib/${stdenv.hostPlatform.rust.rustcTargetSpec}/librustc_driver-*.so build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/librustc.so
ln -s ${rustc.unwrapped}/bin/rustc build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/rustc-main
touch build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-std/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/.libstd.stamp
touch build/${stdenv.hostPlatform.rust.rustcTargetSpec}/stage0-rustc/${stdenv.hostPlatform.rust.rustcTargetSpec}/release/.librustc.stamp
python ./x.py --keep-stage=0 --stage=1 build library/std
@ -169,9 +169,9 @@ in stdenv.mkDerivation (finalAttrs: {
python ./x.py --keep-stage=0 --stage=1 install library/std
mkdir -v $out/bin $doc $man
makeWrapper ${rustc}/bin/rustc $out/bin/rustc --add-flags "--sysroot $out"
makeWrapper ${rustc}/bin/rustdoc $out/bin/rustdoc --add-flags "--sysroot $out"
ln -s ${rustc}/lib/rustlib/{manifest-rust-std-,}${stdenv.hostPlatform.rust.rustcTargetSpec} $out/lib/rustlib/
makeWrapper ${rustc.unwrapped}/bin/rustc $out/bin/rustc --add-flags "--sysroot $out"
makeWrapper ${rustc.unwrapped}/bin/rustdoc $out/bin/rustdoc --add-flags "--sysroot $out"
ln -s ${rustc.unwrapped}/lib/rustlib/{manifest-rust-std-,}${stdenv.hostPlatform.rust.rustcTargetSpec} $out/lib/rustlib/
echo rust-std-${stdenv.hostPlatform.rust.rustcTargetSpec} >> $out/lib/rustlib/components
lndir ${rustc.doc} $doc
lndir ${rustc.man} $man

View file

@ -16897,6 +16897,9 @@ with pkgs;
inherit (darwin) apple_sdk;
};
wrapRustcWith = { rustc-unwrapped, ... } @ args: callPackage ../build-support/rust/rustc-wrapper args;
wrapRustc = rustc-unwrapped: wrapRustcWith { inherit rustc-unwrapped; };
rust_1_74 = callPackage ../development/compilers/rust/1_74.nix {
inherit (darwin.apple_sdk.frameworks) CoreFoundation Security SystemConfiguration;
llvm_16 = llvmPackages_16.libllvm;
@ -16915,7 +16918,7 @@ with pkgs;
inherit (rustPackages) cargo cargo-auditable cargo-auditable-cargo-wrapper clippy rustc rustPlatform;
# https://github.com/NixOS/nixpkgs/issues/89426
rustc-wasm32 = (rustc.override {
rustc-wasm32 = wrapRustc ((rustc.unwrapped.override {
stdenv = stdenv.override {
targetPlatform = lib.systems.elaborate {
# lib.systems.elaborate won't recognize "unknown" as the last component.
@ -16925,7 +16928,7 @@ with pkgs;
};
}).overrideAttrs (old: {
configureFlags = old.configureFlags ++ ["--set=build.docs=false"];
});
}));
makeRustPlatform = callPackage ../development/compilers/rust/make-rust-platform.nix { };