about summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorAdam Joseph <adam@westernsemico.com>2023-08-06 15:06:54 -0700
committerAlyssa Ross <hi@alyssa.is>2023-09-26 06:30:44 +0000
commitc1df604e9fbae74f7aa7530ec13e14a85758be61 (patch)
treecdd153e6887c1ebcc03ea50689ae2e82514ba606 /pkgs
parentaa53f325374cde77bcad69696616d0e9a7b923e5 (diff)
rust: add rust.envVars
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/build-support/rust/lib/default.nix77
-rw-r--r--pkgs/development/compilers/rust/1_72.nix1
-rw-r--r--pkgs/development/compilers/rust/default.nix5
3 files changed, 80 insertions, 3 deletions
diff --git a/pkgs/build-support/rust/lib/default.nix b/pkgs/build-support/rust/lib/default.nix
index aa5ba14c1397b..8ca3758e51477 100644
--- a/pkgs/build-support/rust/lib/default.nix
+++ b/pkgs/build-support/rust/lib/default.nix
@@ -1,4 +1,8 @@
-{ lib }:
+{ lib
+, stdenv
+, buildPackages
+, targetPackages
+}:
 
 rec {
   # https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
@@ -59,8 +63,79 @@ rec {
     then builtins.toFile (toRustTarget platform + ".json") (builtins.toJSON platform.rustc.platform)
     else toRustTarget platform;
 
+  # When used as part of an environment variable name, triples are
+  # uppercased and have all hyphens replaced by underscores:
+  #
+  # https://github.com/rust-lang/cargo/pull/9169
+  # https://github.com/rust-lang/cargo/issues/8285#issuecomment-634202431
+  #
+  toRustTargetForUseInEnvVars = platform:
+    lib.strings.replaceStrings ["-"] ["_"]
+      (lib.strings.toUpper
+        (toRustTarget platform));
+
   # Returns true if the target is no_std
   # https://github.com/rust-lang/rust/blob/2e44c17c12cec45b6a682b1e53a04ac5b5fcc9d2/src/bootstrap/config.rs#L415-L421
   IsNoStdTarget = platform: let rustTarget = toRustTarget platform; in
     builtins.any (t: lib.hasInfix t rustTarget) ["-none" "nvptx" "switch" "-uefi"];
+
+  # These environment variables must be set when using `cargo-c` and
+  # several other tools which do not deal well with cross
+  # compilation.  The symptom of the problem they fix is errors due
+  # to buildPlatform CFLAGS being passed to the
+  # hostPlatform-targeted compiler -- for example, `-m64` being
+  # passed on a build=x86_64/host=aarch64 compilation.
+  envVars = let
+    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++";
+
+    # Unfortunately we must use the dangerous `targetPackages` here
+    # because hooks are artificially phase-shifted one slot earlier
+    # (they go in nativeBuildInputs, so the hostPlatform looks like
+    # a targetPlatform to them).
+    ccForTarget = "${targetPackages.stdenv.cc}/bin/${targetPackages.stdenv.cc.targetPrefix}cc";
+    cxxForTarget = "${targetPackages.stdenv.cc}/bin/${targetPackages.stdenv.cc.targetPrefix}c++";
+
+    rustBuildPlatform = toRustTarget stdenv.buildPlatform;
+    rustBuildPlatformSpec = toRustTargetSpec stdenv.buildPlatform;
+    rustHostPlatform = toRustTarget stdenv.hostPlatform;
+    rustHostPlatformSpec = toRustTargetSpec stdenv.hostPlatform;
+    rustTargetPlatform = toRustTarget stdenv.targetPlatform;
+    rustTargetPlatformSpec = toRustTargetSpec stdenv.targetPlatform;
+  in {
+    inherit
+      ccForBuild  cxxForBuild  rustBuildPlatform   rustBuildPlatformSpec
+      ccForHost   cxxForHost   rustHostPlatform    rustHostPlatformSpec
+      ccForTarget cxxForTarget rustTargetPlatform  rustTargetPlatformSpec;
+
+    # Prefix this onto a command invocation in order to set the
+    # variables needed by cargo.
+    #
+    setEnv = ''
+    env \
+    ''
+    # Due to a bug in how splicing and targetPackages works, in
+    # situations where targetPackages is irrelevant
+    # targetPackages.stdenv.cc is often simply wrong.  We must omit
+    # the following lines when rustTargetPlatform collides with
+    # rustHostPlatform.
+    + lib.optionalString (rustTargetPlatform != rustHostPlatform) ''
+      "CC_${toRustTargetForUseInEnvVars stdenv.targetPlatform}=${ccForTarget}" \
+      "CXX_${toRustTargetForUseInEnvVars stdenv.targetPlatform}=${cxxForTarget}" \
+      "CARGO_TARGET_${toRustTargetForUseInEnvVars stdenv.targetPlatform}_LINKER=${ccForTarget}" \
+    '' + ''
+      "CC_${toRustTargetForUseInEnvVars stdenv.hostPlatform}=${ccForHost}" \
+      "CXX_${toRustTargetForUseInEnvVars stdenv.hostPlatform}=${cxxForHost}" \
+      "CARGO_TARGET_${toRustTargetForUseInEnvVars stdenv.hostPlatform}_LINKER=${ccForHost}" \
+    '' + ''
+      "CC_${toRustTargetForUseInEnvVars stdenv.buildPlatform}=${ccForBuild}" \
+      "CXX_${toRustTargetForUseInEnvVars stdenv.buildPlatform}=${cxxForBuild}" \
+      "CARGO_TARGET_${toRustTargetForUseInEnvVars stdenv.buildPlatform}_LINKER=${ccForBuild}" \
+      "CARGO_BUILD_TARGET=${rustBuildPlatform}" \
+      "HOST_CC=${buildPackages.stdenv.cc}/bin/cc" \
+      "HOST_CXX=${buildPackages.stdenv.cc}/bin/c++" \
+    '';
+  };
 }
diff --git a/pkgs/development/compilers/rust/1_72.nix b/pkgs/development/compilers/rust/1_72.nix
index 60eef6d44ec87..f540c229c6ff6 100644
--- a/pkgs/development/compilers/rust/1_72.nix
+++ b/pkgs/development/compilers/rust/1_72.nix
@@ -11,6 +11,7 @@
 
 { stdenv, lib
 , buildPackages
+, targetPackages
 , newScope, callPackage
 , CoreFoundation, Security, SystemConfiguration
 , pkgsBuildTarget, pkgsBuildBuild, pkgsBuildHost
diff --git a/pkgs/development/compilers/rust/default.nix b/pkgs/development/compilers/rust/default.nix
index 90e921651f140..0a0af7832366b 100644
--- a/pkgs/development/compilers/rust/default.nix
+++ b/pkgs/development/compilers/rust/default.nix
@@ -13,6 +13,7 @@
 }:
 { stdenv, lib
 , buildPackages
+, targetPackages
 , newScope, callPackage
 , CoreFoundation, Security, SystemConfiguration
 , pkgsBuildBuild
@@ -21,7 +22,7 @@
 
 let
   # Use `import` to make sure no packages sneak in here.
-  lib' = import ../../../build-support/rust/lib { inherit lib; };
+  lib' = import ../../../build-support/rust/lib { inherit lib stdenv buildPackages targetPackages; };
   # Allow faster cross compiler generation by reusing Build artifacts
   fastCross = (stdenv.buildPlatform == stdenv.hostPlatform) && (stdenv.hostPlatform != stdenv.targetPlatform);
 in
@@ -29,7 +30,7 @@ in
   lib = lib';
 
   # Backwards compat before `lib` was factored out.
-  inherit (lib') toTargetArch toTargetOs toRustTarget toRustTargetSpec IsNoStdTarget;
+  inherit (lib') toTargetArch toTargetOs toRustTarget toRustTargetSpec IsNoStdTarget toRustTargetForUseInEnvVars envVars;
 
   # This just contains tools for now. But it would conceivably contain
   # libraries too, say if we picked some default/recommended versions to build