summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2020-10-14 03:37:29 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2020-10-14 04:20:23 +0000
commitc0df12de5d938e1c263c992ebd648c4100e8c0a2 (patch)
tree535a18403402fb116a4db93c3aabf79e2e60774b
parent6866f26c89dc7b2cf2e61aed461da36447ffd4be (diff)
downloadnixpkgs-c0df12de5d938e1c263c992ebd648c4100e8c0a2.tar
nixpkgs-c0df12de5d938e1c263c992ebd648c4100e8c0a2.tar.gz
nixpkgs-c0df12de5d938e1c263c992ebd648c4100e8c0a2.tar.bz2
nixpkgs-c0df12de5d938e1c263c992ebd648c4100e8c0a2.tar.lz
nixpkgs-c0df12de5d938e1c263c992ebd648c4100e8c0a2.tar.xz
nixpkgs-c0df12de5d938e1c263c992ebd648c4100e8c0a2.tar.zst
nixpkgs-c0df12de5d938e1c263c992ebd648c4100e8c0a2.zip
rust: Add support for managing target JSON in Nix
-rw-r--r--doc/languages-frameworks/rust.section.md55
-rw-r--r--pkgs/build-support/rust/build-rust-crate/build-crate.nix2
-rw-r--r--pkgs/build-support/rust/build-rust-crate/configure-crate.nix4
-rw-r--r--pkgs/build-support/rust/default.nix2
-rw-r--r--pkgs/build-support/rust/sysroot/default.nix4
-rw-r--r--pkgs/development/compilers/rust/default.nix10
-rw-r--r--pkgs/development/compilers/rust/rustc.nix6
-rw-r--r--pkgs/development/libraries/relibc/default.nix3
8 files changed, 72 insertions, 14 deletions
diff --git a/doc/languages-frameworks/rust.section.md b/doc/languages-frameworks/rust.section.md
index 0e1d59e1a95..0f3cc5d8efb 100644
--- a/doc/languages-frameworks/rust.section.md
+++ b/doc/languages-frameworks/rust.section.md
@@ -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
 directory into a tar.gz archive.
 
-### Building a crate for a different target
-
-To build your crate with a different cargo `--target` simply specify the `target` attribute:
+### Cross compilation
+
+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
 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
 
 When using `buildRustPackage`, the `checkPhase` is enabled by default and runs
diff --git a/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/pkgs/build-support/rust/build-rust-crate/build-crate.nix
index 142109cef49..84d1b2300f1 100644
--- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix
@@ -15,7 +15,7 @@
       ++ [(mkRustcDepArgs dependencies crateRenames)]
       ++ [(mkRustcFeatureArgs crateFeatures)]
       ++ 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
       # https://github.com/rust-lang/cargo/commit/4d64eb99a4#diff-7f98585dbf9d30aa100c8318e2c77e79R1021-R1022
       ++ lib.optional (lib.elem "proc-macro" crateType) "--extern proc_macro"
diff --git a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
index 18587f7047c..5ada40b3b9b 100644
--- a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix
@@ -135,8 +135,8 @@ in ''
   export CARGO_MANIFEST_DIR=$(pwd)
   export DEBUG="${toString (!release)}"
   export OPT_LEVEL="${toString optLevel}"
-  export TARGET="${rust.toRustTarget stdenv.hostPlatform}"
-  export HOST="${rust.toRustTarget stdenv.buildPlatform}"
+  export TARGET="${rust.toRustTargetSpec stdenv.hostPlatform}"
+  export HOST="${rust.toRustTargetSpec stdenv.buildPlatform}"
   export PROFILE=${if release then "release" else "debug"}
   export OUT_DIR=$(pwd)/target/build/${crateName}.out
   export CARGO_PKG_VERSION_MAJOR=${lib.elemAt version 0}
diff --git a/pkgs/build-support/rust/default.nix b/pkgs/build-support/rust/default.nix
index 0f3ff2b70e6..3f6a84b8aed 100644
--- a/pkgs/build-support/rust/default.nix
+++ b/pkgs/build-support/rust/default.nix
@@ -30,7 +30,7 @@
 , cargoBuildFlags ? []
 , buildType ? "release"
 , meta ? {}
-, target ? rust.toRustTarget stdenv.hostPlatform
+, target ? rust.toRustTargetSpec stdenv.hostPlatform
 , cargoVendorDir ? null
 , checkType ? buildType
 , depsExtraArgs ? {}
diff --git a/pkgs/build-support/rust/sysroot/default.nix b/pkgs/build-support/rust/sysroot/default.nix
index 8cfe2d55152..2625306b246 100644
--- a/pkgs/build-support/rust/sysroot/default.nix
+++ b/pkgs/build-support/rust/sysroot/default.nix
@@ -41,7 +41,7 @@ in rustPlatform.buildRustPackage {
     done
 
     export RUST_SYSROOT=$(rustc --print=sysroot)
-    export HOST=${rust.toRustTarget stdenv.buildPlatform}
-    cp -r $RUST_SYSROOT/lib/rustlib/$HOST $out
+    host=${rust.toRustTarget stdenv.buildPlatform}
+    cp -r $RUST_SYSROOT/lib/rustlib/$host $out
   '';
 }
diff --git a/pkgs/development/compilers/rust/default.nix b/pkgs/development/compilers/rust/default.nix
index 0fbe5b8c0ed..fc1af5a3f94 100644
--- a/pkgs/development/compilers/rust/default.nix
+++ b/pkgs/development/compilers/rust/default.nix
@@ -24,7 +24,8 @@
     if platform.isDarwin then "macos"
     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
     cpu_ = platform.rustc.arch or {
       "armv7a" = "armv7";
@@ -34,6 +35,13 @@
   in platform.rustc.config
     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
   # 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
diff --git a/pkgs/development/compilers/rust/rustc.nix b/pkgs/development/compilers/rust/rustc.nix
index 65d8920c4a4..a5a49f8c3c0 100644
--- a/pkgs/development/compilers/rust/rustc.nix
+++ b/pkgs/development/compilers/rust/rustc.nix
@@ -70,9 +70,9 @@ in stdenv.mkDerivation rec {
     "--set=build.cargo=${rustPlatform.rust.cargo}/bin/cargo"
     "--enable-rpath"
     "--enable-vendor"
-    "--build=${rust.toRustTarget stdenv.buildPlatform}"
-    "--host=${rust.toRustTarget stdenv.hostPlatform}"
-    "--target=${rust.toRustTarget stdenv.targetPlatform}"
+    "--build=${rust.toRustTargetSpec stdenv.buildPlatform}"
+    "--host=${rust.toRustTargetSpec stdenv.hostPlatform}"
+    "--target=${rust.toRustTargetSpec stdenv.targetPlatform}"
 
     "${setBuild}.cc=${ccForBuild}"
     "${setHost}.cc=${ccForHost}"
diff --git a/pkgs/development/libraries/relibc/default.nix b/pkgs/development/libraries/relibc/default.nix
index 43e02fc8758..24d434bf715 100644
--- a/pkgs/development/libraries/relibc/default.nix
+++ b/pkgs/development/libraries/relibc/default.nix
@@ -63,7 +63,8 @@ redoxRustPlatform.buildRustPackage rec {
     DESTDIR=$out make install
   '';
 
-  TARGET = buildPackages.rust.toRustTarget stdenvNoCC.targetPlatform;
+  # TODO: should be hostPlatform
+  TARGET = buildPackages.rust.toRustTargetSpec stdenvNoCC.targetPlatform;
 
   cargoSha256 = "1fzz7ba3ga57x1cbdrcfrdwwjr70nh4skrpxp4j2gak2c3scj6rz";