makeRustPlatform: support custom targets

This commit is contained in:
Aaron Janse 2020-10-08 14:32:49 -07:00
parent 38abb8f734
commit f8ea4e0c3d
4 changed files with 137 additions and 7 deletions

View File

@ -4,6 +4,10 @@
, cargo
, diffutils
, fetchCargoTarball
, runCommandNoCC
, rustPlatform
, callPackage
, remarshal
, git
, rust
, rustc
@ -26,12 +30,15 @@
, cargoBuildFlags ? []
, buildType ? "release"
, meta ? {}
, target ? null
, target ? rust.toRustTarget stdenv.hostPlatform
, cargoVendorDir ? null
, checkType ? buildType
, depsExtraArgs ? {}
, cargoParallelTestThreads ? true
# Toggles whether a custom sysroot is created when the target is a .json file.
, __internal_dontAddSysroot ? false
# Needed to `pushd`/`popd` into a subdir of a tarball if this subdir
# contains a Cargo.toml, but isn't part of a workspace (which is e.g. the
# case for `rustfmt`/etc from the `rust-sources).
@ -68,14 +75,26 @@ let
else ''
cargoDepsCopy="$sourceRoot/${cargoVendorDir}"
'';
targetIsJSON = stdenv.lib.hasSuffix ".json" target;
rustTarget = if target == null then rust.toRustTarget stdenv.hostPlatform else target;
# see https://github.com/rust-lang/cargo/blob/964a16a28e234a3d397b2a7031d4ab4a428b1391/src/cargo/core/compiler/compile_kind.rs#L151-L168
# the "${}" is needed to transform the path into a /nix/store path before baseNameOf
shortTarget = if targetIsJSON then
(stdenv.lib.removeSuffix ".json" (builtins.baseNameOf "${target}"))
else target;
sysroot = (callPackage ./sysroot {}) {
inherit target shortTarget;
RUSTFLAGS = args.RUSTFLAGS or "";
originalCargoToml = src + /Cargo.toml; # profile info is later extracted
};
ccForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc";
cxxForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++";
ccForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
cxxForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
releaseDir = "target/${rustTarget}/${buildType}";
releaseDir = "target/${shortTarget}/${buildType}";
tmpDir = "${releaseDir}-tmp";
# Specify the stdenv's `diff` by abspath to ensure that the user's build
@ -115,7 +134,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
[target."${rust.toRustTarget stdenv.buildPlatform}"]
"linker" = "${ccForBuild}"
${stdenv.lib.optionalString (stdenv.buildPlatform.config != stdenv.hostPlatform.config) ''
[target."${rustTarget}"]
[target."${shortTarget}"]
"linker" = "${ccForHost}"
${# https://github.com/rust-lang/rust/issues/46651#issuecomment-433611633
stdenv.lib.optionalString (stdenv.hostPlatform.isMusl && stdenv.hostPlatform.isAarch64) ''
@ -183,9 +202,11 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
"CXX_${rust.toRustTarget stdenv.buildPlatform}"="${cxxForBuild}" \
"CC_${rust.toRustTarget stdenv.hostPlatform}"="${ccForHost}" \
"CXX_${rust.toRustTarget stdenv.hostPlatform}"="${cxxForHost}" \
cargo build -j $NIX_BUILD_CORES \
${stdenv.lib.optionalString
(targetIsJSON && !__internal_dontAddSysroot) "RUSTFLAGS=\"--sysroot ${sysroot} $RUSTFLAGS\" "
}cargo build -j $NIX_BUILD_CORES \
${stdenv.lib.optionalString (buildType == "release") "--release"} \
--target ${rustTarget} \
--target ${target} \
--frozen ${concatStringsSep " " cargoBuildFlags}
)
@ -205,7 +226,7 @@ stdenv.mkDerivation ((removeAttrs args ["depsExtraArgs"]) // {
'';
checkPhase = args.checkPhase or (let
argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${rustTarget} --frozen";
argstr = "${stdenv.lib.optionalString (checkType == "release") "--release"} --target ${target} --frozen";
threads = if cargoParallelTestThreads then "$NIX_BUILD_CORES" else "1";
in ''
${stdenv.lib.optionalString (buildAndTestSubdir != null) "pushd ${buildAndTestSubdir}"}

View File

@ -0,0 +1,20 @@
[[package]]
name = "alloc"
version = "0.0.0"
dependencies = ["compiler_builtins", "core"]
[[package]]
name = "compiler_builtins"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bc4ac2c824d2bfc612cba57708198547e9a26943af0632aff033e0693074d5c"
dependencies = ["rustc-std-workspace-core"]
[[package]]
name = "core"
version = "0.0.0"
[[package]]
name = "rustc-std-workspace-core"
version = "1.99.0"
dependencies = ["core"]

View File

@ -0,0 +1,44 @@
import os
import toml
rust_src = os.environ['RUSTC_SRC']
orig_cargo = os.environ['ORIG_CARGO']
base = {
'package': {
'name': 'alloc',
'version': '0.0.0',
'authors': ['The Rust Project Developers'],
'edition': '2018',
},
'dependencies': {
'compiler_builtins': {
'version': '0.1.0',
'features': ['rustc-dep-of-std', 'mem'],
},
'core': {
'path': os.path.join(rust_src, 'libcore'),
},
},
'lib': {
'name': 'alloc',
'path': os.path.join(rust_src, 'liballoc/lib.rs'),
},
'patch': {
'crates-io': {
'rustc-std-workspace-core': {
'path': os.path.join(rust_src, 'tools/rustc-std-workspace-core'),
},
},
},
}
with open(orig_cargo, 'r') as f:
src = toml.loads(f.read())
if 'profile' in src:
base['profile'] = src['profile']
out = toml.dumps(base)
with open('Cargo.toml', 'x') as f:
f.write(out)

View File

@ -0,0 +1,45 @@
{ stdenv, rust, rustPlatform, buildPackages }:
{ shortTarget, originalCargoToml, target, RUSTFLAGS }:
let rustSrc = stdenv.mkDerivation {
name = "rust-src";
src = rustPlatform.rust.rustc.src;
preferLocalBuild = true;
phases = [ "unpackPhase" "installPhase" ];
installPhase = "cp -r src $out";
};
cargoSrc = stdenv.mkDerivation {
name = "cargo-src";
preferLocalBuild = true;
phases = [ "installPhase" ];
installPhase = ''
RUSTC_SRC=${rustSrc} ORIG_CARGO=${originalCargoToml} \
${buildPackages.python3.withPackages (ps: with ps; [ toml ])}/bin/python3 ${./cargo.py}
mkdir -p $out
cp Cargo.toml $out/Cargo.toml
cp ${./Cargo.lock} $out/Cargo.lock
'';
};
in rustPlatform.buildRustPackage {
inherit target RUSTFLAGS;
name = "custom-sysroot";
src = cargoSrc;
RUSTC_BOOTSTRAP = 1;
__internal_dontAddSysroot = true;
cargoSha256 = "1snkfsx3jb1p5izwlfwkgp8hxhgpa35nmx939sp5730vf9whqqwg";
installPhase = ''
export LIBS_DIR=$out/lib/rustlib/${shortTarget}/lib
mkdir -p $LIBS_DIR
for f in target/${shortTarget}/release/deps/*.{rlib,rmeta}; do
cp $f $LIBS_DIR
done
export RUST_SYSROOT=$(rustc --print=sysroot)
export HOST=${rust.toRustTarget stdenv.buildPlatform}
cp -r $RUST_SYSROOT/lib/rustlib/$HOST $out
'';
}