about summary refs log tree commit diff
diff options
context:
space:
mode:
authorIlan Joselevich <personal@ilanjoselevich.com>2024-06-15 01:28:21 +0300
committerIlan Joselevich <personal@ilanjoselevich.com>2024-06-24 19:28:33 +0300
commitcf5e2c2c9adb9ae2db58c75a50453ee7d5d6a699 (patch)
tree09554d5b23a94a8886e3151895180fb691ebfb3a
parent957116419de7e473dbc29ec92aae3ef083e2d163 (diff)
buildRustCrate: support cross compiling to wasm32-unknown-unknown
With this change you will finally be able to use
buildRustCrate/crate2nix to build your wasm32-unknown-unknown
rust projects.

Simply import nixpkgs like so:
```
lib = <nixpkgs/lib>;
pkgsForWasm32 = import <nixpkgs> {
  crossSystem = lib.examples.wasm32-unknown-none;
}
```
or use pkgsCross directly with
```
pkgsCross.wasm32-unknown-none.callPackage ./. { };
```
-rw-r--r--pkgs/build-support/rust/build-rust-crate/build-crate.nix11
-rw-r--r--pkgs/build-support/rust/build-rust-crate/default.nix16
-rw-r--r--pkgs/top-level/all-packages.nix4
3 files changed, 23 insertions, 8 deletions
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 7484b3ad0290e..3af13fe70a7de 100644
--- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix
+++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix
@@ -1,5 +1,5 @@
 { lib, stdenv
-, mkRustcDepArgs, mkRustcFeatureArgs, needUnstableCLI
+, mkRustcDepArgs, mkRustcFeatureArgs, needUnstableCLI, rustc
 }:
 
 { crateName,
@@ -27,6 +27,10 @@
       # 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"
+      ++ lib.optional (stdenv.hostPlatform.linker == "lld") # Needed when building for targets that use lld. e.g. 'wasm32-unknown-unknown'
+        "-C linker=${rustc.llvmPackages.lld}/bin/lld"
+      ++ lib.optional (stdenv.hasCC && stdenv.hostPlatform.linker != "lld")
+        "-C linker=${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"
     ;
     rustcMeta = "-C metadata=${metadata} -C extra-filename=-${metadata}";
 
@@ -39,10 +43,7 @@
       ++ (map (x: "--crate-type ${x}") crateType)
     );
 
-    binRustcOpts = lib.concatStringsSep " " (
-      [ "-C linker=${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc" ] ++
-      baseRustcOpts
-    );
+    binRustcOpts = lib.concatStringsSep " " baseRustcOpts;
 
     build_bin = if buildTests then "build_bin_test" else "build_bin";
   in ''
diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix
index 9ceda041b6653..68f0d7ffe649d 100644
--- a/pkgs/build-support/rust/build-rust-crate/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/default.nix
@@ -16,6 +16,16 @@
 }:
 
 let
+  # Returns a true if the builder's rustc was built with support for the target.
+  targetAlreadyIncluded = lib.elem stdenv.hostPlatform.rust.rustcTarget
+    (lib.splitString "," (lib.removePrefix "--target=" (
+      lib.elemAt (lib.filter (f: lib.hasPrefix "--target=" f) pkgsBuildBuild.rustc.unwrapped.configureFlags) 0)
+    ));
+
+  # If the build's rustc was built with support for the target then reuse it. (Avoids uneeded compilation for targets like `wasm32-unknown-unknown`)
+  rustc' = if targetAlreadyIncluded then pkgsBuildBuild.rustc else rustc;
+  cargo' = if targetAlreadyIncluded then pkgsBuildBuild.cargo else cargo;
+
   # Create rustc arguments to link against the given list of dependencies
   # and renames.
   #
@@ -75,6 +85,7 @@ let
 
   buildCrate = import ./build-crate.nix {
     inherit lib stdenv mkRustcDepArgs mkRustcFeatureArgs needUnstableCLI;
+    rustc = rustc';
   };
 
   installCrate = import ./install-crate.nix { inherit stdenv; };
@@ -272,7 +283,8 @@ crate_: lib.makeOverridable
       name = "rust_${crate.crateName}-${crate.version}${lib.optionalString buildTests_ "-test"}";
       version = crate.version;
       depsBuildBuild = [ pkgsBuildBuild.stdenv.cc ];
-      nativeBuildInputs = [ rust stdenv.cc cargo jq ]
+      nativeBuildInputs = [ rustc' cargo' jq ]
+        ++ lib.optionals stdenv.hasCC [ stdenv.cc ]
         ++ lib.optionals stdenv.buildPlatform.isDarwin [ libiconv ]
         ++ (crate.nativeBuildInputs or [ ]) ++ nativeBuildInputs_;
       buildInputs = lib.optionals stdenv.isDarwin [ libiconv ] ++ (crate.buildInputs or [ ]) ++ buildInputs_;
@@ -378,7 +390,7 @@ crate_: lib.makeOverridable
     )
   )
 {
-  rust = rustc;
+  rust = rustc';
   release = crate_.release or true;
   verbose = crate_.verbose or true;
   extraRustcOpts = [ ];
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 3168d602e1b96..627626d7d25e8 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -16545,7 +16545,9 @@ with pkgs;
 
   makeRustPlatform = callPackage ../development/compilers/rust/make-rust-platform.nix { };
 
-  buildRustCrate = callPackage ../build-support/rust/build-rust-crate { };
+  buildRustCrate = callPackage ../build-support/rust/build-rust-crate ({ } // lib.optionalAttrs (stdenv.hostPlatform.libc == null) {
+    stdenv = stdenvNoCC; # Some build targets without libc will fail to evaluate with a normal stdenv.
+  });
   buildRustCrateHelpers = callPackage ../build-support/rust/build-rust-crate/helpers.nix { };
 
   cargo2junit = callPackage ../development/tools/rust/cargo2junit { };