Merge pull request #99066 from lopsided98/buildrustcrate-target-vars

buildRustCrate: fix target config environment variables on 32-bit ARM
This commit is contained in:
John Ericson 2020-10-11 16:46:29 -04:00 committed by GitHub
commit d3d55bcc81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 36 deletions

View File

@ -1,4 +1,4 @@
{ lib, stdenv, echo_colored, noisily, mkRustcDepArgs, mkRustcFeatureArgs }: { lib, stdenv, rust, echo_colored, noisily, mkRustcDepArgs, mkRustcFeatureArgs }:
{ {
build build
, buildDependencies , buildDependencies
@ -17,7 +17,6 @@
, libName , libName
, libPath , libPath
, release , release
, target_os
, verbose , verbose
, workspace_member }: , workspace_member }:
let version_ = lib.splitString "-" crateVersion; let version_ = lib.splitString "-" crateVersion;
@ -124,8 +123,8 @@ in ''
export CARGO_PKG_AUTHORS="${authors}" export CARGO_PKG_AUTHORS="${authors}"
export CARGO_PKG_DESCRIPTION="${crateDescription}" export CARGO_PKG_DESCRIPTION="${crateDescription}"
export CARGO_CFG_TARGET_ARCH=${stdenv.hostPlatform.parsed.cpu.name} export CARGO_CFG_TARGET_ARCH=${rust.toTargetArch stdenv.hostPlatform}
export CARGO_CFG_TARGET_OS=${target_os} export CARGO_CFG_TARGET_OS=${rust.toTargetOs stdenv.hostPlatform}
export CARGO_CFG_TARGET_FAMILY="unix" export CARGO_CFG_TARGET_FAMILY="unix"
export CARGO_CFG_UNIX=1 export CARGO_CFG_UNIX=1
export CARGO_CFG_TARGET_ENV="gnu" export CARGO_CFG_TARGET_ENV="gnu"
@ -136,8 +135,8 @@ in ''
export CARGO_MANIFEST_DIR=$(pwd) export CARGO_MANIFEST_DIR=$(pwd)
export DEBUG="${toString (!release)}" export DEBUG="${toString (!release)}"
export OPT_LEVEL="${toString optLevel}" export OPT_LEVEL="${toString optLevel}"
export TARGET="${stdenv.hostPlatform.config}" export TARGET="${rust.toRustTarget stdenv.hostPlatform}"
export HOST="${stdenv.hostPlatform.config}" export HOST="${rust.toRustTarget stdenv.buildPlatform}"
export PROFILE=${if release then "release" else "debug"} export PROFILE=${if release then "release" else "debug"}
export OUT_DIR=$(pwd)/target/build/${crateName}.out export OUT_DIR=$(pwd)/target/build/${crateName}.out
export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0} export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0}

View File

@ -8,12 +8,6 @@
, cargo, jq }: , cargo, jq }:
let let
# This doesn't appear to be officially documented anywhere yet.
# See https://github.com/rust-lang-nursery/rust-forge/issues/101.
target_os = if stdenv.hostPlatform.isDarwin
then "macos"
else stdenv.hostPlatform.parsed.kernel.name;
# Create rustc arguments to link against the given list of dependencies # Create rustc arguments to link against the given list of dependencies
# and renames. # and renames.
# #
@ -52,7 +46,7 @@ let
inherit (import ./log.nix { inherit lib; }) noisily echo_colored; inherit (import ./log.nix { inherit lib; }) noisily echo_colored;
configureCrate = import ./configure-crate.nix { configureCrate = import ./configure-crate.nix {
inherit lib stdenv echo_colored noisily mkRustcDepArgs mkRustcFeatureArgs; inherit lib stdenv rust echo_colored noisily mkRustcDepArgs mkRustcFeatureArgs;
}; };
buildCrate = import ./build-crate.nix { buildCrate = import ./build-crate.nix {
@ -284,7 +278,7 @@ stdenv.mkDerivation (rec {
inherit crateName buildDependencies completeDeps completeBuildDeps crateDescription inherit crateName buildDependencies completeDeps completeBuildDeps crateDescription
crateFeatures crateRenames libName build workspace_member release libPath crateVersion crateFeatures crateRenames libName build workspace_member release libPath crateVersion
extraLinkFlags extraRustcOpts extraLinkFlags extraRustcOpts
crateAuthors crateHomepage verbose colors target_os; crateAuthors crateHomepage verbose colors;
}; };
buildPhase = buildCrate { buildPhase = buildCrate {
inherit crateName dependencies inherit crateName dependencies

View File

@ -1,4 +1,5 @@
{ lib { lib
, buildPackages
, buildRustCrate , buildRustCrate
, callPackage , callPackage
, releaseTools , releaseTools
@ -10,13 +11,14 @@
}: }:
let let
mkCrate = args: let mkCrate = buildRustCrate: args: let
p = { p = {
crateName = "nixtestcrate"; crateName = "nixtestcrate";
version = "0.1.0"; version = "0.1.0";
authors = [ "Test <test@example.com>" ]; authors = [ "Test <test@example.com>" ];
} // args; } // args;
in buildRustCrate p; in buildRustCrate p;
mkHostCrate = mkCrate buildRustCrate;
mkCargoToml = mkCargoToml =
{ name, crateVersion ? "0.1.0", path ? "Cargo.toml" }: { name, crateVersion ? "0.1.0", path ? "Cargo.toml" }:
@ -68,15 +70,15 @@ let
mkLib = name: mkFile name "pub fn test() -> i32 { return 23; }"; mkLib = name: mkFile name "pub fn test() -> i32 { return 23; }";
mkTest = crateArgs: let mkTest = crateArgs: let
crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]); crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
hasTests = crateArgs.buildTests or false; hasTests = crateArgs.buildTests or false;
expectedTestOutputs = crateArgs.expectedTestOutputs or null; expectedTestOutputs = crateArgs.expectedTestOutputs or null;
binaries = map (v: ''"${v.name}"'') (crateArgs.crateBin or []); binaries = map (v: lib.escapeShellArg v.name) (crateArgs.crateBin or []);
isLib = crateArgs ? libName || crateArgs ? libPath; isLib = crateArgs ? libName || crateArgs ? libPath;
crateName = crateArgs.crateName or "nixtestcrate"; crateName = crateArgs.crateName or "nixtestcrate";
libName = crateArgs.libName or crateName; libName = crateArgs.libName or crateName;
libTestBinary = if !isLib then null else mkCrate { libTestBinary = if !isLib then null else mkHostCrate {
crateName = "run-test-${crateName}"; crateName = "run-test-${crateName}";
dependencies = [ crate ]; dependencies = [ crate ];
src = mkBinExtern "src/main.rs" libName; src = mkBinExtern "src/main.rs" libName;
@ -89,18 +91,27 @@ let
runCommand "run-buildRustCrate-${crateName}-test" { runCommand "run-buildRustCrate-${crateName}-test" {
nativeBuildInputs = [ crate ]; nativeBuildInputs = [ crate ];
} (if !hasTests then '' } (if !hasTests then ''
${lib.concatStringsSep "\n" binaries} ${lib.concatMapStringsSep "\n" (binary:
# Can't actually run the binary when cross-compiling
(lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "type ") + binary
) binaries}
${lib.optionalString isLib '' ${lib.optionalString isLib ''
test -e ${crate}/lib/*.rlib || exit 1 test -e ${crate}/lib/*.rlib || exit 1
${libTestBinary}/bin/run-test-${crateName} ${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "test -x "} \
${libTestBinary}/bin/run-test-${crateName}
''} ''}
touch $out touch $out
'' else '' '' else if stdenv.hostPlatform == stdenv.buildPlatform then ''
for file in ${crate}/tests/*; do for file in ${crate}/tests/*; do
$file 2>&1 >> $out $file 2>&1 >> $out
done done
set -e set -e
${lib.concatMapStringsSep "\n" (o: "grep '${o}' $out || { echo 'output \"${o}\" not found in:'; cat $out; exit 23; }") expectedTestOutputs} ${lib.concatMapStringsSep "\n" (o: "grep '${o}' $out || { echo 'output \"${o}\" not found in:'; cat $out; exit 23; }") expectedTestOutputs}
'' else ''
for file in ${crate}/tests/*; do
test -x "$file"
done
touch "$out"
'' ''
); );
@ -109,7 +120,7 @@ let
`name` is used as part of the derivation name that performs the checking. `name` is used as part of the derivation name that performs the checking.
`crateArgs` is passed to `mkCrate` to build the crate with `buildRustCrate`. `crateArgs` is passed to `mkHostCrate` to build the crate with `buildRustCrate`.
`expectedFiles` contains a list of expected file paths in the output. E.g. `expectedFiles` contains a list of expected file paths in the output. E.g.
`[ "./bin/my_binary" ]`. `[ "./bin/my_binary" ]`.
@ -124,7 +135,7 @@ let
assert (builtins.isList expectedFiles); assert (builtins.isList expectedFiles);
let let
crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]); crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
crateOutput = if output == null then crate else crate."${output}"; crateOutput = if output == null then crate else crate."${output}";
expectedFilesFile = writeTextFile { expectedFilesFile = writeTextFile {
name = "expected-files-${name}"; name = "expected-files-${name}";
@ -188,17 +199,17 @@ let
crateBinRename1 = { crateBinRename1 = {
crateBin = [{ name = "my-binary-rename1"; }]; crateBin = [{ name = "my-binary-rename1"; }];
src = mkBinExtern "src/main.rs" "foo_renamed"; src = mkBinExtern "src/main.rs" "foo_renamed";
dependencies = [ (mkCrate { crateName = "foo"; src = mkLib "src/lib.rs"; }) ]; dependencies = [ (mkHostCrate { crateName = "foo"; src = mkLib "src/lib.rs"; }) ];
crateRenames = { "foo" = "foo_renamed"; }; crateRenames = { "foo" = "foo_renamed"; };
}; };
crateBinRename2 = { crateBinRename2 = {
crateBin = [{ name = "my-binary-rename2"; }]; crateBin = [{ name = "my-binary-rename2"; }];
src = mkBinExtern "src/main.rs" "foo_renamed"; src = mkBinExtern "src/main.rs" "foo_renamed";
dependencies = [ (mkCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ]; dependencies = [ (mkHostCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ];
crateRenames = { "foo" = "foo_renamed"; }; crateRenames = { "foo" = "foo_renamed"; };
}; };
crateBinRenameMultiVersion = let crateBinRenameMultiVersion = let
crateWithVersion = version: mkCrate { crateWithVersion = version: mkHostCrate {
crateName = "my_lib"; crateName = "my_lib";
inherit version; inherit version;
src = mkFile "src/lib.rs" '' src = mkFile "src/lib.rs" ''
@ -307,7 +318,7 @@ let
fn main() {} fn main() {}
''; '';
dependencies = [ dependencies = [
(mkCrate { (mkHostCrate {
crateName = "somerlib"; crateName = "somerlib";
type = [ "rlib" ]; type = [ "rlib" ];
src = mkLib "src/lib.rs"; src = mkLib "src/lib.rs";
@ -315,7 +326,7 @@ let
]; ];
}; };
buildScriptDeps = let buildScriptDeps = let
depCrate = boolVal: mkCrate { depCrate = buildRustCrate: boolVal: mkCrate buildRustCrate {
crateName = "bar"; crateName = "bar";
src = mkFile "src/lib.rs" '' src = mkFile "src/lib.rs" ''
pub const baz: bool = ${boolVal}; pub const baz: bool = ${boolVal};
@ -339,8 +350,8 @@ let
'') '')
]; ];
}; };
buildDependencies = [ (depCrate "true") ]; buildDependencies = [ (depCrate buildPackages.buildRustCrate "true") ];
dependencies = [ (depCrate "false") ]; dependencies = [ (depCrate buildRustCrate "false") ];
buildTests = true; buildTests = true;
expectedTestOutputs = [ "test baz_false ... ok" ]; expectedTestOutputs = [ "test baz_false ... ok" ];
}; };
@ -373,7 +384,7 @@ let
# Regression test for https://github.com/NixOS/nixpkgs/pull/88054 # Regression test for https://github.com/NixOS/nixpkgs/pull/88054
# Build script output should be rewritten as valid env vars. # Build script output should be rewritten as valid env vars.
buildScriptIncludeDirDeps = let buildScriptIncludeDirDeps = let
depCrate = mkCrate { depCrate = mkHostCrate {
crateName = "bar"; crateName = "bar";
src = symlinkJoin { src = symlinkJoin {
name = "build-script-and-include-dir-bar"; name = "build-script-and-include-dir-bar";
@ -460,7 +471,7 @@ let
mkdir -p $out/lib mkdir -p $out/lib
# Note: On darwin (which defaults to clang) we have to add # Note: On darwin (which defaults to clang) we have to add
# `-undefined dynamic_lookup` as otherwise the compilation fails. # `-undefined dynamic_lookup` as otherwise the compilation fails.
cc -shared \ $CC -shared \
${lib.optionalString stdenv.isDarwin "-undefined dynamic_lookup"} \ ${lib.optionalString stdenv.isDarwin "-undefined dynamic_lookup"} \
-o $out/lib/${name}${stdenv.hostPlatform.extensions.sharedLibrary} ${src} -o $out/lib/${name}${stdenv.hostPlatform.extensions.sharedLibrary} ${src}
''; '';
@ -609,9 +620,11 @@ let
pkg = brotliCrates.brotli_2_5_0 {}; pkg = brotliCrates.brotli_2_5_0 {};
in runCommand "run-brotli-test-cmd" { in runCommand "run-brotli-test-cmd" {
nativeBuildInputs = [ pkg ]; nativeBuildInputs = [ pkg ];
} '' } (if stdenv.hostPlatform == stdenv.buildPlatform then ''
${pkg}/bin/brotli -c ${pkg}/bin/brotli > /dev/null && touch $out ${pkg}/bin/brotli -c ${pkg}/bin/brotli > /dev/null && touch $out
''; '' else ''
test -x '${pkg}/bin/brotli' && touch $out
'');
allocNoStdLibTest = let allocNoStdLibTest = let
pkg = brotliCrates.alloc_no_stdlib_1_3_0 {}; pkg = brotliCrates.alloc_no_stdlib_1_3_0 {};
in runCommand "run-alloc-no-stdlib-test-cmd" { in runCommand "run-alloc-no-stdlib-test-cmd" {

View File

@ -13,12 +13,23 @@
, llvmPackages_5 , llvmPackages_5
, pkgsBuildTarget, pkgsBuildBuild , pkgsBuildTarget, pkgsBuildBuild
}: rec { }: rec {
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
toTargetArch = platform:
if platform.isAarch32 then "arm"
else platform.parsed.cpu.name;
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_os
toTargetOs = platform:
if platform.isDarwin then "macos"
else platform.parsed.kernel.name;
# Target triple. Rust has slightly different naming conventions than we use.
toRustTarget = platform: with platform.parsed; let toRustTarget = platform: with platform.parsed; let
cpu_ = { cpu_ = platform.rustc.arch or {
"armv7a" = "armv7"; "armv7a" = "armv7";
"armv7l" = "armv7"; "armv7l" = "armv7";
"armv6l" = "arm"; "armv6l" = "arm";
}.${cpu.name} or platform.rustc.arch or cpu.name; }.${cpu.name} or cpu.name;
in platform.rustc.config in platform.rustc.config
or "${cpu_}-${vendor.name}-${kernel.name}${lib.optionalString (abi.name != "unknown") "-${abi.name}"}"; or "${cpu_}-${vendor.name}-${kernel.name}${lib.optionalString (abi.name != "unknown") "-${abi.name}"}";