rust: cargo: Use rustc and cargo built on Build

When cross-compiling a rust package, all we need is the std library compiled
for the target. This uses the final stage compiler which was built for Build
and then uses that as a stage0 compiler for target std library.

It also copies the rust binary from pkgsBuildBuild so that it find the new
lib/rustlib directory.

We also need to create a cargo wrapper which will use the "new" rust compiler

Also makes sure man pages and doc pages are propagated

Co-authored-by: Alyssa Ross <hi@alyssa.is>
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
Co-authored-by: Rick van Schijndel <Mindavi@users.noreply.github.com>
This commit is contained in:
Asad Mehmood 2022-06-07 11:28:03 +01:00 committed by Yureka
parent 964006733a
commit 9ee10432a4
4 changed files with 65 additions and 9 deletions

View file

@ -57,4 +57,4 @@ import ./default.nix {
rustcPatches = [ ];
}
(builtins.removeAttrs args [ "pkgsBuildTarget" "pkgsBuildBuild" "pkgsBuildHost" "llvmPackages_16" "llvm_16"])
(builtins.removeAttrs args [ "pkgsBuildTarget" "pkgsBuildHost" "llvmPackages_16" "llvm_16"])

View file

@ -0,0 +1,14 @@
{ runCommand, stdenv, lib, pkgsBuildBuild, makeShellWrapper, rustc, ... }:
runCommand "${stdenv.targetPlatform.config}-cargo-${lib.getVersion pkgsBuildBuild.cargo}" {
# Use depsBuildBuild or it tries to use target-runtimeShell
depsBuildBuild = [ makeShellWrapper ];
inherit (pkgsBuildBuild.cargo) meta;
} ''
mkdir -p $out/bin
ln -s ${pkgsBuildBuild.cargo}/share $out/share
makeWrapper "${pkgsBuildBuild.cargo}/bin/cargo" "$out/bin/cargo" \
--prefix PATH : "${rustc}/bin"
''

View file

@ -15,12 +15,15 @@
, buildPackages
, newScope, callPackage
, CoreFoundation, Security, SystemConfiguration
, pkgsBuildBuild
, makeRustPlatform
}:
let
# Use `import` to make sure no packages sneak in here.
lib' = import ../../../build-support/rust/lib { inherit lib; };
# Allow faster cross compiler generation by reusing Build artifacts
fastCross = (stdenv.buildPlatform == stdenv.hostPlatform) && (stdenv.hostPlatform != stdenv.targetPlatform);
in
{
lib = lib';
@ -48,7 +51,10 @@ in
# Like `buildRustPackages`, but may also contain prebuilt binaries to
# break cycle. Just like `bootstrapTools` for nixpkgs as a whole,
# nothing in the final package set should refer to this.
bootstrapRustPackages = self.buildRustPackages.overrideScope (_: _:
bootstrapRustPackages = if fastCross
then pkgsBuildBuild.rustPackages
else
self.buildRustPackages.overrideScope (_: _:
lib.optionalAttrs (stdenv.buildPlatform == stdenv.hostPlatform)
(selectRustPackage buildPackages).packages.prebuilt);
bootRustPlatform = makeRustPlatform bootstrapRustPackages;
@ -61,7 +67,7 @@ in
version = rustcVersion;
sha256 = rustcSha256;
inherit enableRustcDev;
inherit llvmShared llvmSharedForBuild llvmSharedForHost llvmSharedForTarget llvmPackages;
inherit llvmShared llvmSharedForBuild llvmSharedForHost llvmSharedForTarget llvmPackages fastCross;
patches = rustcPatches;
@ -72,11 +78,11 @@ in
inherit Security;
inherit (self.buildRustPackages) rustc;
};
cargo = self.callPackage ./cargo.nix {
cargo = if (!fastCross) then self.callPackage ./cargo.nix {
# Use boot package set to break cycle
rustPlatform = bootRustPlatform;
inherit CoreFoundation Security;
};
} else self.callPackage ./cargo_cross.nix {};
cargo-auditable = self.callPackage ./cargo-auditable.nix { };
cargo-auditable-cargo-wrapper = self.callPackage ./cargo-auditable-cargo-wrapper.nix { };
clippy = self.callPackage ./clippy.nix {

View file

@ -15,6 +15,10 @@
, wezterm
, firefox
, thunderbird
# This only builds std for target and reuses the rustc from build.
, fastCross
, lndir
, makeWrapper
}:
let
@ -87,13 +91,13 @@ in stdenv.mkDerivation rec {
# (build!=target): When cross-building a compiler we need to add
# the build platform as well so rustc can compile build.rs
# scripts.
] ++ optionals (stdenv.buildPlatform != stdenv.targetPlatform) [
] ++ optionals (stdenv.buildPlatform != stdenv.targetPlatform && !fastCross) [
(rust.toRustTargetSpec stdenv.buildPlatform)
# (host!=target): When building a cross-targeting compiler we
# need to add the host platform as well so rustc can compile
# build.rs scripts.
] ++ optionals (stdenv.hostPlatform != stdenv.targetPlatform) [
] ++ optionals (stdenv.hostPlatform != stdenv.targetPlatform && !fastCross) [
(rust.toRustTargetSpec stdenv.hostPlatform)
])}"
@ -132,6 +136,37 @@ in stdenv.mkDerivation rec {
"--set rust.jemalloc"
];
# if we already have a rust compiler for build just compile the target std
# library and reuse compiler
buildPhase = if fastCross then "
runHook preBuild
mkdir -p build/${rust.toRustTargetSpec stdenv.hostPlatform}/stage0-{std,rustc}/${rust.toRustTargetSpec stdenv.hostPlatform}/release/
ln -s ${rustc}/lib/rustlib/${rust.toRustTargetSpec stdenv.hostPlatform}/libstd-*.so build/${rust.toRustTargetSpec stdenv.hostPlatform}/stage0-std/${rust.toRustTargetSpec stdenv.hostPlatform}/release/libstd.so
ln -s ${rustc}/lib/rustlib/${rust.toRustTargetSpec stdenv.hostPlatform}/librustc_driver-*.so build/${rust.toRustTargetSpec stdenv.hostPlatform}/stage0-rustc/${rust.toRustTargetSpec stdenv.hostPlatform}/release/librustc.so
ln -s ${rustc}/bin/rustc build/${rust.toRustTargetSpec stdenv.hostPlatform}/stage0-rustc/${rust.toRustTargetSpec stdenv.hostPlatform}/release/rustc-main
touch build/${rust.toRustTargetSpec stdenv.hostPlatform}/stage0-std/${rust.toRustTargetSpec stdenv.hostPlatform}/release/.libstd.stamp
touch build/${rust.toRustTargetSpec stdenv.hostPlatform}/stage0-rustc/${rust.toRustTargetSpec stdenv.hostPlatform}/release/.librustc.stamp
python ./x.py --keep-stage=0 --stage=1 build library/std
runHook postBuild
" else null;
installPhase = if fastCross then ''
runHook preInstall
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-,}${rust.toRustTargetSpec stdenv.hostPlatform} $out/lib/rustlib/
echo rust-std-${rust.toRustTargetSpec stdenv.hostPlatform} >> $out/lib/rustlib/components
lndir ${rustc.doc} $doc
lndir ${rustc.man} $man
runHook postInstall
'' else null;
# The bootstrap.py will generated a Makefile that then executes the build.
# The BOOTSTRAP_ARGS used by this Makefile must include all flags to pass
# to the bootstrap builder.
@ -179,7 +214,8 @@ in stdenv.mkDerivation rec {
nativeBuildInputs = [
file python3 rustc cmake
which libffi removeReferencesTo pkg-config xz
];
]
++ optionals fastCross [ lndir makeWrapper ];
buildInputs = [ openssl ]
++ optionals stdenv.isDarwin [ libiconv Security ]
@ -188,7 +224,7 @@ in stdenv.mkDerivation rec {
outputs = [ "out" "man" "doc" ];
setOutputFlags = false;
postInstall = lib.optionalString enableRustcDev ''
postInstall = lib.optionalString (enableRustcDev && !fastCross) ''
# install rustc-dev components. Necessary to build rls, clippy...
python x.py dist rustc-dev
tar xf build/dist/rustc-dev*tar.gz