1
0
Fork 1
mirror of https://github.com/NixOS/nixpkgs.git synced 2024-11-26 23:52:33 +00:00

rust: Add support for managing target JSON in Nix

This commit is contained in:
John Ericson 2020-10-14 03:37:29 +00:00
parent 6866f26c89
commit c0df12de5d
8 changed files with 71 additions and 13 deletions

View file

@ -63,9 +63,52 @@ The fetcher will verify that the `Cargo.lock` file is in sync with the `src`
attribute, and fail the build if not. It will also will compress the vendor attribute, and fail the build if not. It will also will compress the vendor
directory into a tar.gz archive. directory into a tar.gz archive.
### Building a crate for a different target ### Cross compilation
To build your crate with a different cargo `--target` simply specify the `target` attribute: By default, Rust packages are compiled for the host platform, just like any
other package is. The `--target` passed to rust tools is computed from this.
By default, it takes the `stdenv.hostPlatform.config` and replaces components
where they are known to differ. But there are ways to customize the argument:
- To choose a different target by name, define
`stdenv.hostPlatform.rustc.arch.config` as that name (a string), and that
name will be used instead.
For example:
```nix
import <nixpkgs> {
crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // {
rustc.arch.config = "thumbv7em-none-eabi";
};
}
```
will result in:
```shell
--target thumbv7em-none-eabi
```
- To pass a completely custom target, define
`stdenv.hostPlatform.rustc.arch.config` with its name, and
`stdenv.hostPlatform.rustc.arch.custom` with the value. The value will be
serialized to JSON in a file called
`${stdenv.hostPlatform.rustc.arch.config}.json`, and the path of that file
will be used instead.
For example:
```nix
import <nixpkgs> {
crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // {
rustc.arch.config = "thumb-crazy";
rustc.arch.custom = { foo = ""; bar = ""; };
};
}
will result in:
```shell
--target /nix/store/asdfasdfsadf-thumb-crazy.json # contains {"foo":"","bar":""}
```
Finally, as an ad-hoc escape hatch, a computed target (string or JSON file
path) can be passed directly to `buildRustPackage`:
```nix ```nix
pkgs.rustPlatform.buildRustPackage { pkgs.rustPlatform.buildRustPackage {
@ -74,6 +117,12 @@ pkgs.rustPlatform.buildRustPackage {
} }
``` ```
This is useful to avoid rebuilding Rust tools, since they are actually target
agnostic and don't need to be rebuilt. But in the future, we should always
build the Rust tools and standard library crates separately so there is no
reason not to take the `stdenv.hostPlatform.rustc`-modifying approach, and the
ad-hoc escape hatch to `buildRustPackage` can be removed.
### Running package tests ### Running package tests
When using `buildRustPackage`, the `checkPhase` is enabled by default and runs When using `buildRustPackage`, the `checkPhase` is enabled by default and runs

View file

@ -15,7 +15,7 @@
++ [(mkRustcDepArgs dependencies crateRenames)] ++ [(mkRustcDepArgs dependencies crateRenames)]
++ [(mkRustcFeatureArgs crateFeatures)] ++ [(mkRustcFeatureArgs crateFeatures)]
++ extraRustcOpts ++ extraRustcOpts
++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTarget stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc" ++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) "--target ${rust.toRustTargetSpec stdenv.hostPlatform} -C linker=${stdenv.hostPlatform.config}-gcc"
# since rustc 1.42 the "proc_macro" crate is part of the default crate prelude # since rustc 1.42 the "proc_macro" crate is part of the default crate prelude
# https://github.com/rust-lang/cargo/commit/4d64eb99a4#diff-7f98585dbf9d30aa100c8318e2c77e79R1021-R1022 # https://github.com/rust-lang/cargo/commit/4d64eb99a4#diff-7f98585dbf9d30aa100c8318e2c77e79R1021-R1022
++ lib.optional (lib.elem "proc-macro" crateType) "--extern proc_macro" ++ lib.optional (lib.elem "proc-macro" crateType) "--extern proc_macro"

View file

@ -135,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="${rust.toRustTarget stdenv.hostPlatform}" export TARGET="${rust.toRustTargetSpec stdenv.hostPlatform}"
export HOST="${rust.toRustTarget stdenv.buildPlatform}" export HOST="${rust.toRustTargetSpec 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

@ -30,7 +30,7 @@
, cargoBuildFlags ? [] , cargoBuildFlags ? []
, buildType ? "release" , buildType ? "release"
, meta ? {} , meta ? {}
, target ? rust.toRustTarget stdenv.hostPlatform , target ? rust.toRustTargetSpec stdenv.hostPlatform
, cargoVendorDir ? null , cargoVendorDir ? null
, checkType ? buildType , checkType ? buildType
, depsExtraArgs ? {} , depsExtraArgs ? {}

View file

@ -41,7 +41,7 @@ in rustPlatform.buildRustPackage {
done done
export RUST_SYSROOT=$(rustc --print=sysroot) export RUST_SYSROOT=$(rustc --print=sysroot)
export HOST=${rust.toRustTarget stdenv.buildPlatform} host=${rust.toRustTarget stdenv.buildPlatform}
cp -r $RUST_SYSROOT/lib/rustlib/$HOST $out cp -r $RUST_SYSROOT/lib/rustlib/$host $out
''; '';
} }

View file

@ -24,7 +24,8 @@
if platform.isDarwin then "macos" if platform.isDarwin then "macos"
else platform.parsed.kernel.name; else platform.parsed.kernel.name;
# Target triple. Rust has slightly different naming conventions than we use. # Returns the name of the rust target, even if it is custom. Adjustments are
# because rust has slightly different naming conventions than we do.
toRustTarget = platform: with platform.parsed; let toRustTarget = platform: with platform.parsed; let
cpu_ = platform.rustc.arch or { cpu_ = platform.rustc.arch or {
"armv7a" = "armv7"; "armv7a" = "armv7";
@ -34,6 +35,13 @@
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}"}";
# Returns the name of the rust target if it is standard, or the json file
# containing the custom target spec.
toRustTargetSpec = platform:
if (platform.rustc.arch or {}) ? custom
then builtins.toFile (platform.rustc.config + ".json") (builtins.toJSON platform.rustc.arch.custom)
else toRustTarget platform;
# This just contains tools for now. But it would conceivably contain # This just contains tools for now. But it would conceivably contain
# libraries too, say if we picked some default/recommended versions from # libraries too, say if we picked some default/recommended versions from
# `cratesIO` to build by Hydra and/or try to prefer/bias in Cargo.lock for # `cratesIO` to build by Hydra and/or try to prefer/bias in Cargo.lock for

View file

@ -70,9 +70,9 @@ in stdenv.mkDerivation rec {
"--set=build.cargo=${rustPlatform.rust.cargo}/bin/cargo" "--set=build.cargo=${rustPlatform.rust.cargo}/bin/cargo"
"--enable-rpath" "--enable-rpath"
"--enable-vendor" "--enable-vendor"
"--build=${rust.toRustTarget stdenv.buildPlatform}" "--build=${rust.toRustTargetSpec stdenv.buildPlatform}"
"--host=${rust.toRustTarget stdenv.hostPlatform}" "--host=${rust.toRustTargetSpec stdenv.hostPlatform}"
"--target=${rust.toRustTarget stdenv.targetPlatform}" "--target=${rust.toRustTargetSpec stdenv.targetPlatform}"
"${setBuild}.cc=${ccForBuild}" "${setBuild}.cc=${ccForBuild}"
"${setHost}.cc=${ccForHost}" "${setHost}.cc=${ccForHost}"

View file

@ -63,7 +63,8 @@ redoxRustPlatform.buildRustPackage rec {
DESTDIR=$out make install DESTDIR=$out make install
''; '';
TARGET = buildPackages.rust.toRustTarget stdenvNoCC.targetPlatform; # TODO: should be hostPlatform
TARGET = buildPackages.rust.toRustTargetSpec stdenvNoCC.targetPlatform;
cargoSha256 = "1fzz7ba3ga57x1cbdrcfrdwwjr70nh4skrpxp4j2gak2c3scj6rz"; cargoSha256 = "1fzz7ba3ga57x1cbdrcfrdwwjr70nh4skrpxp4j2gak2c3scj6rz";