diff options
author | Florian Klink <flokli@flokli.de> | 2024-06-30 14:05:33 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-30 14:05:33 +0300 |
commit | 641b2f29b62ef1e809e9d3d4cfd4cb419fac2275 (patch) | |
tree | 58fd619e9765f62d5a2228365270af289251f207 | |
parent | 3a1c0f02db82b5d7857337baf24233b6c1837e04 (diff) | |
parent | cc379b60f0af632aeb8c4e0f42820a03d90d673a (diff) |
Merge pull request #319153 from Kranzes/buildRustCrate-wasm
buildRustCrate: add support for compiling to wasm32-unknown-unknown
-rw-r--r-- | lib/systems/default.nix | 35 | ||||
-rw-r--r-- | lib/systems/examples.nix | 6 | ||||
-rw-r--r-- | lib/systems/parse.nix | 5 | ||||
-rw-r--r-- | pkgs/build-support/rust/build-rust-crate/build-crate.nix | 11 | ||||
-rw-r--r-- | pkgs/build-support/rust/build-rust-crate/default.nix | 16 | ||||
-rw-r--r-- | pkgs/build-support/rust/build-rust-crate/test/default.nix | 33 | ||||
-rw-r--r-- | pkgs/top-level/all-packages.nix | 4 |
7 files changed, 78 insertions, 32 deletions
diff --git a/lib/systems/default.nix b/lib/systems/default.nix index 0981122388bb1..074239b3fb6f1 100644 --- a/lib/systems/default.nix +++ b/lib/systems/default.nix @@ -84,20 +84,21 @@ let useLLVM = final.isFreeBSD || final.isOpenBSD; libc = - /**/ if final.isDarwin then "libSystem" - else if final.isMinGW then "msvcrt" - else if final.isWasi then "wasilibc" - else if final.isRedox then "relibc" - else if final.isMusl then "musl" - else if final.isUClibc then "uclibc" - else if final.isAndroid then "bionic" - else if final.isLinux /* default */ then "glibc" - else if final.isFreeBSD then "fblibc" - else if final.isOpenBSD then "oblibc" - else if final.isNetBSD then "nblibc" - else if final.isAvr then "avrlibc" - else if final.isGhcjs then null - else if final.isNone then "newlib" + /**/ if final.isDarwin then "libSystem" + else if final.isMinGW then "msvcrt" + else if final.isWasi then "wasilibc" + else if final.isWasm && !final.isWasi then null + else if final.isRedox then "relibc" + else if final.isMusl then "musl" + else if final.isUClibc then "uclibc" + else if final.isAndroid then "bionic" + else if final.isLinux /* default */ then "glibc" + else if final.isFreeBSD then "fblibc" + else if final.isOpenBSD then "oblibc" + else if final.isNetBSD then "nblibc" + else if final.isAvr then "avrlibc" + else if final.isGhcjs then null + else if final.isNone then "newlib" # TODO(@Ericson2314) think more about other operating systems else "native/impure"; # Choose what linker we wish to use by default. Someday we might also @@ -179,6 +180,7 @@ let (isAndroid || isGnu || isMusl # Linux (allows multiple libcs) || isDarwin || isSunOS || isOpenBSD || isFreeBSD || isNetBSD # BSDs || isCygwin || isMinGW # Windows + || isWasm # WASM ) && !isStatic; # The difference between `isStatic` and `hasSharedLibraries` is mainly the @@ -187,7 +189,7 @@ let # don't support dynamic linking, but don't get the `staticMarker`. # `pkgsStatic` sets `isStatic=true`, so `pkgsStatic.hostPlatform` always # has the `staticMarker`. - isStatic = final.isWasm || final.isRedox; + isStatic = final.isWasi || final.isRedox; # Just a guess, based on `system` inherit @@ -337,7 +339,8 @@ let if isList f then f else [ f ] ) else optional final.isUnix "unix" - ++ optional final.isWindows "windows"; + ++ optional final.isWindows "windows" + ++ optional final.isWasm "wasm"; # https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor vendor = let diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix index 7e50266748434..178536efb0091 100644 --- a/lib/systems/examples.nix +++ b/lib/systems/examples.nix @@ -356,6 +356,12 @@ rec { useLLVM = true; }; + wasm32-unknown-none = { + config = "wasm32-unknown-none"; + rust.rustcTarget = "wasm32-unknown-unknown"; + useLLVM = true; + }; + # Ghcjs ghcjs = { # This triple is special to GHC/Cabal/GHCJS and not recognized by autotools diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix index 1d7c95943a794..a2ee288f2c1f8 100644 --- a/lib/systems/parse.nix +++ b/lib/systems/parse.nix @@ -466,11 +466,12 @@ rec { } # cpu-vendor-os else if elemAt l 1 == "apple" || - elem (elemAt l 2) [ "wasi" "redox" "mmixware" "ghcjs" "mingw32" ] || + elem (elemAt l 2) [ "redox" "mmixware" "ghcjs" "mingw32" ] || hasPrefix "freebsd" (elemAt l 2) || hasPrefix "netbsd" (elemAt l 2) || hasPrefix "openbsd" (elemAt l 2) || - hasPrefix "genode" (elemAt l 2) + hasPrefix "genode" (elemAt l 2) || + hasPrefix "wasm32" (elemAt l 0) then { cpu = elemAt l 0; vendor = elemAt l 1; 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 dfe28cc334b5e..d6369055cc53b 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. # @@ -77,6 +87,7 @@ let buildCrate = import ./build-crate.nix { inherit lib stdenv mkRustcDepArgs mkRustcFeatureArgs needUnstableCLI; + rustc = rustc'; }; installCrate = import ./install-crate.nix { inherit stdenv; }; @@ -274,7 +285,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_; @@ -380,7 +392,7 @@ crate_: lib.makeOverridable ) ) { - rust = rustc; + rust = rustc'; release = crate_.release or true; verbose = crate_.verbose or true; extraRustcOpts = [ ]; diff --git a/pkgs/build-support/rust/build-rust-crate/test/default.nix b/pkgs/build-support/rust/build-rust-crate/test/default.nix index d020031a92f93..dd135af919654 100644 --- a/pkgs/build-support/rust/build-rust-crate/test/default.nix +++ b/pkgs/build-support/rust/build-rust-crate/test/default.nix @@ -8,6 +8,7 @@ , stdenv , symlinkJoin , writeTextFile +, pkgsCross }: let @@ -120,7 +121,10 @@ let `name` is used as part of the derivation name that performs the checking. - `crateArgs` is passed to `mkHostCrate` to build the crate with `buildRustCrate`. + `mkCrate` can be used to override the `mkCrate` call/implementation to use to + override the `buildRustCrate`, useful for cross compilation. Uses `mkHostCrate` by default. + + `crateArgs` is passed to `mkCrate` to build the crate with `buildRustCrate` `expectedFiles` contains a list of expected file paths in the output. E.g. `[ "./bin/my_binary" ]`. @@ -129,13 +133,13 @@ let output is used but e.g. `output = "lib";` will cause the lib output to be checked instead. You do not need to specify any directories. */ - assertOutputs = { name, crateArgs, expectedFiles, output? null }: + assertOutputs = { name, mkCrate ? mkHostCrate, crateArgs, expectedFiles, output? null, }: assert (builtins.isString name); assert (builtins.isAttrs crateArgs); assert (builtins.isList expectedFiles); let - crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]); + crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]); crateOutput = if output == null then crate else crate."${output}"; expectedFilesFile = writeTextFile { name = "expected-files-${name}"; @@ -155,7 +159,7 @@ let '' # sed out the hash because it differs per platform + '' - | sed -E -e 's/-[0-9a-fA-F]{10}\.rlib/-HASH.rlib/g' \ + | sed 's/-${crate.metadata}//g' \ > "$actualFiles" diff -q ${expectedFilesFile} "$actualFiles" > /dev/null || { echo -e "\033[0;1;31mERROR: Difference in expected output files in ${crateOutput} \033[0m" >&2 @@ -651,7 +655,7 @@ let }; expectedFiles = [ "./nix-support/propagated-build-inputs" - "./lib/libtest_lib-HASH.rlib" + "./lib/libtest_lib.rlib" "./lib/link" ]; }; @@ -668,7 +672,24 @@ let }; expectedFiles = [ "./nix-support/propagated-build-inputs" - "./lib/libtest_lib-HASH.rlib" + "./lib/libtest_lib.rlib" + "./lib/link" + ]; + }; + + crateLibOutputsWasm32 = assertOutputs { + name = "wasm32-crate-lib"; + output = "lib"; + mkCrate = mkCrate pkgsCross.wasm32-unknown-none.buildRustCrate; + crateArgs = { + libName = "test_lib"; + type = [ "cdylib" ]; + libPath = "src/lib.rs"; + src = mkLib "src/lib.rs"; + }; + expectedFiles = [ + "./nix-support/propagated-build-inputs" + "./lib/test_lib.wasm" "./lib/link" ]; }; diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index d9ad333fae540..ebe4c42c358cd 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -16443,7 +16443,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 { }; |