From 4d76556fcafec46b134296418cca595abf8c40ef Mon Sep 17 00:00:00 2001 From: Julius Michaelis Date: Thu, 10 Oct 2024 11:00:30 +0900 Subject: [PATCH 1/5] rustc: do not use clang-built llvm on wasi, as it doesn't build and is unnecessary --- pkgs/development/compilers/rust/1_81.nix | 29 +++++++++++++----------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/pkgs/development/compilers/rust/1_81.nix b/pkgs/development/compilers/rust/1_81.nix index b433504c81541..c482e23099c59 100644 --- a/pkgs/development/compilers/rust/1_81.nix +++ b/pkgs/development/compilers/rust/1_81.nix @@ -32,18 +32,21 @@ let llvmSharedFor = pkgSet: - pkgSet.llvmPackages_18.libllvm.override ( - { - enableSharedLibraries = true; - } - // lib.optionalAttrs (stdenv.targetPlatform.useLLVM or false) { - # Force LLVM to compile using clang + LLVM libs when targeting pkgsLLVM - stdenv = pkgSet.stdenv.override { - allowedRequisites = null; - cc = pkgSet.llvmPackages_18.clangUseLLVM; - }; - } - ); + if !stdenv.targetPlatform.isWasi then + pkgSet.llvmPackages_18.libllvm.override ( + { + enableSharedLibraries = true; + } + // lib.optionalAttrs (stdenv.targetPlatform.useLLVM or false) { + # Force LLVM to compile using clang + LLVM libs when targeting pkgsLLVM + stdenv = pkgSet.stdenv.override { + allowedRequisites = null; + cc = pkgSet.llvmPackages_18.clangUseLLVM; + }; + } + ) + else + pkgSet.llvmPackages_18.libllvm; in import ./default.nix { @@ -59,7 +62,7 @@ import ./default.nix # Expose llvmPackages used for rustc from rustc via passthru for LTO in Firefox llvmPackages = - if (stdenv.targetPlatform.useLLVM or false) then + if ((stdenv.targetPlatform.useLLVM or false) && !stdenv.targetPlatform.isWasi) then callPackage ( { pkgs, From b6e6f6f16e9cd79c1dfda7da307fb5f482efd629 Mon Sep 17 00:00:00 2001 From: Julius Michaelis Date: Thu, 13 Jun 2024 22:44:59 +0900 Subject: [PATCH 2/5] rustc: set up sysroot for wasm32-wasi and fix build --- lib/systems/examples.nix | 1 + pkgs/development/compilers/rust/rustc.nix | 4 +++- pkgs/development/libraries/wasilibc/default.nix | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix index 5059f6e0c8384..ee44f50134542 100644 --- a/lib/systems/examples.nix +++ b/lib/systems/examples.nix @@ -353,6 +353,7 @@ rec { wasi32 = { config = "wasm32-unknown-wasi"; + rustc.config = "wasm32-wasip1"; useLLVM = true; }; diff --git a/pkgs/development/compilers/rust/rustc.nix b/pkgs/development/compilers/rust/rustc.nix index f22add43a6d8c..7b6781a620cf7 100644 --- a/pkgs/development/compilers/rust/rustc.nix +++ b/pkgs/development/compilers/rust/rustc.nix @@ -167,6 +167,8 @@ in stdenv.mkDerivation (finalAttrs: { "${setHost}.musl-root=${pkgsBuildHost.targetPackages.stdenv.cc.libc}" ] ++ optionals stdenv.targetPlatform.isMusl [ "${setTarget}.musl-root=${pkgsBuildTarget.targetPackages.stdenv.cc.libc}" + ] ++ optionals stdenv.targetPlatform.isWasi [ + "${setTarget}.wasi-root=${pkgsBuildTarget.targetPackages.stdenv.cc.libc}" ] ++ optionals stdenv.targetPlatform.rust.isNoStdTarget [ "--disable-docs" ] ++ optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) [ @@ -262,7 +264,7 @@ in stdenv.mkDerivation (finalAttrs: { buildInputs = [ openssl ] ++ optionals stdenv.hostPlatform.isDarwin [ libiconv Security zlib ] ++ optional (!withBundledLLVM) llvmShared.lib - ++ optional (useLLVM && !withBundledLLVM) [ + ++ optional (useLLVM && !withBundledLLVM && !stdenv.targetPlatform.isWasi) [ llvmPackages.libunwind # Hack which is used upstream https://github.com/gentoo/gentoo/blob/master/dev-lang/rust/rust-1.78.0.ebuild#L284 (runCommandLocal "libunwind-libgcc" {} '' diff --git a/pkgs/development/libraries/wasilibc/default.nix b/pkgs/development/libraries/wasilibc/default.nix index c0714a78556a3..83d990e5b94aa 100644 --- a/pkgs/development/libraries/wasilibc/default.nix +++ b/pkgs/development/libraries/wasilibc/default.nix @@ -51,6 +51,11 @@ stdenv.mkDerivation { preFixup = '' ln -s $share/share/undefined-symbols.txt $out/lib/wasi.imports + # rustc build expects lib at the path where a make install would put them without the SYSROOT_* overrides + TARGET_TRIPLE=wasm32-wasip1 + ln -s $out/lib/ $out/lib/$TARGET_TRIPLE + ln -s $dev/include $dev/include/$TARGET_TRIPLE + ln -s $share/share $share/share/$TARGET_TRIPLE ''; passthru.tests = { From b843ef10197f43397a529b9d25e9631040e28699 Mon Sep 17 00:00:00 2001 From: Julius Michaelis Date: Mon, 7 Oct 2024 15:47:58 +0900 Subject: [PATCH 3/5] rustc,rustPlatform: adjust compiler and linker names to match and be recognizable by rust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rustc infers the linker flavor from the name of the linker, but refuses to recognize "cc" as anything. The reasons for this are not well documented, but are hinted at in a comment: https://github.com/rust-lang/rust/blob/18deb53874ac4701ba10ebc016cb8cde7a049b82/compiler/rustc_codegen_ssa/src/back/link.rs#L1392-L1397 In short, "cc" could be (or at least historically could have been) anything, and there's no way to know what flags to pass to it. This is a problem because nixpkgs insists to on overriding CARG_TARGET_…_LINKER to gcc or clang always, but rustc defaults to expecting ldd directly (not wrapped in a compiler) for some targets (e.g. wasi). Since rustc did not detec this override changing the flaver, linking has so far been broken for these targets. Adjusting rustc itself is not absolutely necessary, but a matter of sanity. --- pkgs/build-support/rust/lib/default.nix | 17 +++++++++++------ pkgs/development/compilers/rust/rustc.nix | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/pkgs/build-support/rust/lib/default.nix b/pkgs/build-support/rust/lib/default.nix index c23f779bfe5d9..bbd01721ad5ea 100644 --- a/pkgs/build-support/rust/lib/default.nix +++ b/pkgs/build-support/rust/lib/default.nix @@ -14,18 +14,23 @@ rec { # passed on a build=x86_64/host=aarch64 compilation. envVars = let - ccForBuild = "${pkgsBuildHost.stdenv.cc}/bin/${pkgsBuildHost.stdenv.cc.targetPrefix}cc"; - cxxForBuild = "${pkgsBuildHost.stdenv.cc}/bin/${pkgsBuildHost.stdenv.cc.targetPrefix}c++"; + # should match pkgs/development/compilers/rust/rustc.nix + prefixForStdenv = stdenv: "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}"; + ccForStdenv = stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang" else "gcc"}"; + cxxForStdenv = stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang++" else "g++"}"; - ccForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"; - cxxForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++"; + ccForBuild = ccForStdenv pkgsBuildHost.stdenv; + cxxForBuild = cxxForStdenv pkgsBuildHost.stdenv; + + ccForHost = ccForStdenv stdenv; + cxxForHost = cxxForStdenv stdenv; # Unfortunately we must use the dangerous `pkgsTargetTarget` here # because hooks are artificially phase-shifted one slot earlier # (they go in nativeBuildInputs, so the hostPlatform looks like # a targetPlatform to them). - ccForTarget = "${pkgsTargetTarget.stdenv.cc}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}cc"; - cxxForTarget = "${pkgsTargetTarget.stdenv.cc}/bin/${pkgsTargetTarget.stdenv.cc.targetPrefix}c++"; + ccForTarget = ccForStdenv pkgsTargetTarget.stdenv; + cxxForTarget = cxxForStdenv pkgsTargetTarget.stdenv; rustBuildPlatform = stdenv.buildPlatform.rust.rustcTarget; rustBuildPlatformSpec = stdenv.buildPlatform.rust.rustcTargetSpec; diff --git a/pkgs/development/compilers/rust/rustc.nix b/pkgs/development/compilers/rust/rustc.nix index 7b6781a620cf7..a84698614e5c1 100644 --- a/pkgs/development/compilers/rust/rustc.nix +++ b/pkgs/development/compilers/rust/rustc.nix @@ -84,8 +84,8 @@ in stdenv.mkDerivation (finalAttrs: { # Reference: https://github.com/rust-lang/rust/blob/master/src/bootstrap/configure.py configureFlags = let prefixForStdenv = stdenv: "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}"; - ccPrefixForStdenv = stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang" else "cc"}"; - cxxPrefixForStdenv = stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang++" else "c++"}"; + ccPrefixForStdenv = stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang" else "gcc"}"; + cxxPrefixForStdenv = stdenv: "${prefixForStdenv stdenv}${if (stdenv.cc.isClang or false) then "clang++" else "g++"}"; setBuild = "--set=target.${stdenv.buildPlatform.rust.rustcTarget}"; setHost = "--set=target.${stdenv.hostPlatform.rust.rustcTarget}"; setTarget = "--set=target.${stdenv.targetPlatform.rust.rustcTarget}"; From 4cba6c3a5b5657deb30c9cc71e05e7e224c86ad6 Mon Sep 17 00:00:00 2001 From: Julius Michaelis Date: Thu, 10 Oct 2024 10:56:05 +0900 Subject: [PATCH 4/5] rustc: wasi32: disable expecting self-contained linker, the nixpkgs derivation does not supply one --- pkgs/development/compilers/rust/rustc.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/development/compilers/rust/rustc.nix b/pkgs/development/compilers/rust/rustc.nix index a84698614e5c1..5352e845d9ad7 100644 --- a/pkgs/development/compilers/rust/rustc.nix +++ b/pkgs/development/compilers/rust/rustc.nix @@ -225,6 +225,10 @@ in stdenv.mkDerivation (finalAttrs: { substituteInPlace compiler/rustc_target/src/spec/*/*.rs \ --replace-quiet '"rust-lld"' '"lld"' + # Figuring out when this should be False is a rustc FIXME. Nixpkgs needs it false. + substituteInPlace compiler/rustc_target/src/spec/targets/wasm32_wasi*.rs \ + --replace LinkSelfContainedDefault::True LinkSelfContainedDefault::False + ${optionalString (!withBundledLLVM) "rm -rf src/llvm"} # Useful debugging parameter From e5a2e633f39d9e1e7cdd831041c06abe2ede04f6 Mon Sep 17 00:00:00 2001 From: Julius Michaelis Date: Fri, 19 Jul 2024 13:29:29 +0900 Subject: [PATCH 5/5] wasi32: fix linking with clang invoked from rustc --- pkgs/build-support/bintools-wrapper/default.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix index b4736bc960fa4..cc0e699d15bfd 100644 --- a/pkgs/build-support/bintools-wrapper/default.nix +++ b/pkgs/build-support/bintools-wrapper/default.nix @@ -235,6 +235,12 @@ stdenvNoCC.mkDerivation { basename=$(basename "$variant") wrap $basename ${./ld-wrapper.sh} $variant done + '' + optionalString targetPlatform.isWasi '' + wrap ${targetPrefix}wasm-ld ${./ld-wrapper.sh} $ldPath/${targetPrefix}wasm-ld + # clang doesn't properly normalize the target triple[1] before using it as a search path, + # and rustc passes wasm32-wasi as `-target`, which gets used as is. Work around. + # [1] https://github.com/llvm/llvm-project/blob/ad7aeb0ff58ebd29f68adb85c64e8010639e2a76/clang/lib/Driver/Driver.cpp#L6187 + ln -s $out/bin/${targetPrefix}wasm-ld $out/bin/wasm32-wasi-wasm-ld ''; strictDeps = true;