From 8b51cdd3bea18e806e3ed63add8e19292dfc84ec Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Wed, 18 Oct 2023 11:02:45 +0000 Subject: [PATCH] rustc: add a compiler wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- doc/languages-frameworks/rust.section.md | 3 +- .../rust/rustc-wrapper/default.nix | 29 +++++++++++++++++++ .../rust/rustc-wrapper/rustc-wrapper.sh | 11 +++++++ pkgs/development/compilers/rust/1_74.nix | 1 + pkgs/development/compilers/rust/binary.nix | 6 ++-- pkgs/development/compilers/rust/cargo.nix | 2 +- pkgs/development/compilers/rust/default.nix | 4 ++- pkgs/development/compilers/rust/rustc.nix | 12 ++++---- pkgs/top-level/all-packages.nix | 7 +++-- 9 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 pkgs/build-support/rust/rustc-wrapper/default.nix create mode 100644 pkgs/build-support/rust/rustc-wrapper/rustc-wrapper.sh diff --git a/doc/languages-frameworks/rust.section.md b/doc/languages-frameworks/rust.section.md index d18b048b911b..9be381c0bfe2 100644 --- a/doc/languages-frameworks/rust.section.md +++ b/doc/languages-frameworks/rust.section.md @@ -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. - diff --git a/pkgs/build-support/rust/rustc-wrapper/default.nix b/pkgs/build-support/rust/rustc-wrapper/default.nix new file mode 100644 index 000000000000..06cfcbb5457f --- /dev/null +++ b/pkgs/build-support/rust/rustc-wrapper/default.nix @@ -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)} +'' diff --git a/pkgs/build-support/rust/rustc-wrapper/rustc-wrapper.sh b/pkgs/build-support/rust/rustc-wrapper/rustc-wrapper.sh new file mode 100644 index 000000000000..866a6912e090 --- /dev/null +++ b/pkgs/build-support/rust/rustc-wrapper/rustc-wrapper.sh @@ -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 diff --git a/pkgs/development/compilers/rust/1_74.nix b/pkgs/development/compilers/rust/1_74.nix index 72169a7b4d3f..f8749a8b65c2 100644 --- a/pkgs/development/compilers/rust/1_74.nix +++ b/pkgs/development/compilers/rust/1_74.nix @@ -16,6 +16,7 @@ , CoreFoundation, Security, SystemConfiguration , pkgsBuildTarget, pkgsBuildBuild, pkgsBuildHost , makeRustPlatform +, wrapRustc , llvmPackages_16, llvm_16 } @ args: diff --git a/pkgs/development/compilers/rust/binary.nix b/pkgs/development/compilers/rust/binary.nix index bf03077f4aa8..efef07aba4c6 100644 --- a/pkgs/development/compilers/rust/binary.nix +++ b/pkgs/development/compilers/rust/binary.nix @@ -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}"; diff --git a/pkgs/development/compilers/rust/cargo.nix b/pkgs/development/compilers/rust/cargo.nix index 8eb628aa536b..1bc1777acd47 100644 --- a/pkgs/development/compilers/rust/cargo.nix +++ b/pkgs/development/compilers/rust/cargo.nix @@ -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"; diff --git a/pkgs/development/compilers/rust/default.nix b/pkgs/development/compilers/rust/default.nix index efd7042c230c..b70b7ccf6264 100644 --- a/pkgs/development/compilers/rust/default.nix +++ b/pkgs/development/compilers/rust/default.nix @@ -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; diff --git a/pkgs/development/compilers/rust/rustc.nix b/pkgs/development/compilers/rust/rustc.nix index 3a32dfc0c1e8..cb74ec11127f 100644 --- a/pkgs/development/compilers/rust/rustc.nix +++ b/pkgs/development/compilers/rust/rustc.nix @@ -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 diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index b7992c9751b6..4fd7fa13e4ac 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -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 { };