From 9abff4af4f07c16aecd89bf82051afbc3228d6fd Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 29 Jan 2019 21:01:24 -0500 Subject: [PATCH] wasm: init cross target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds pkgsCross.wasm32 and pkgsCross.wasm64. Use it to build Nixpkgs with a WebAssembly toolchain. stdenv/cross: use static overlay on isWasm isWasm doesn’t make sense dynamically linked. --- lib/systems/default.nix | 3 +- lib/systems/doubles.nix | 3 ++ lib/systems/examples.nix | 14 ++++++++-- lib/systems/for-meta.nix | 1 + lib/systems/inspect.nix | 3 +- lib/systems/parse.nix | 4 +++ .../bintools-wrapper/default.nix | 3 +- pkgs/build-support/cc-wrapper/default.nix | 6 ++++ .../compilers/llvm/8/compiler-rt.nix | 4 +++ pkgs/development/compilers/llvm/8/default.nix | 2 ++ .../compilers/llvm/8/libc++/default.nix | 11 ++++++-- .../compilers/llvm/8/libc++abi.nix | 17 ++++++++--- .../llvm/8/libcxxabi-no-threads.patch | 12 ++++++++ .../libraries/wasilibc/default.nix | 28 +++++++++++++++++++ pkgs/stdenv/cross/default.nix | 3 +- pkgs/stdenv/generic/default.nix | 3 ++ pkgs/test/cross/default.nix | 9 +++--- pkgs/top-level/all-packages.nix | 7 ++++- pkgs/top-level/static.nix | 12 ++++++++ 19 files changed, 126 insertions(+), 19 deletions(-) create mode 100644 pkgs/development/compilers/llvm/8/libcxxabi-no-threads.patch create mode 100644 pkgs/development/libraries/wasilibc/default.nix diff --git a/lib/systems/default.nix b/lib/systems/default.nix index b45a5fd8d2b..c408fe46be6 100644 --- a/lib/systems/default.nix +++ b/lib/systems/default.nix @@ -30,6 +30,7 @@ rec { libc = /**/ if final.isDarwin then "libSystem" else if final.isMinGW then "msvcrt" + else if final.isWasi then "wasilibc" else if final.isMusl then "musl" else if final.isUClibc then "uclibc" else if final.isAndroid then "bionic" @@ -62,7 +63,7 @@ rec { "netbsd" = "NetBSD"; "freebsd" = "FreeBSD"; "openbsd" = "OpenBSD"; - "wasm" = "Wasm"; + "wasi" = "Wasi"; }.${final.parsed.kernel.name} or null; # uname -p diff --git a/lib/systems/doubles.nix b/lib/systems/doubles.nix index 2cf06b6ac1c..c6877ebef0b 100644 --- a/lib/systems/doubles.nix +++ b/lib/systems/doubles.nix @@ -17,6 +17,8 @@ let "x86_64-netbsd" "x86_64-openbsd" "x86_64-solaris" "x86_64-windows" "i686-windows" + + "wasm64-wasi" "wasm32-wasi" ]; allParsed = map parse.mkSystemFromString all; @@ -45,6 +47,7 @@ in rec { netbsd = filterDoubles predicates.isNetBSD; openbsd = filterDoubles predicates.isOpenBSD; unix = filterDoubles predicates.isUnix; + wasi = filterDoubles predicates.isWasi; windows = filterDoubles predicates.isWindows; mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64le-linux"]; diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix index 1a5b80449bf..94c7cfd7570 100644 --- a/lib/systems/examples.nix +++ b/lib/systems/examples.nix @@ -116,7 +116,7 @@ rec { config = "aarch64-none-elf"; libc = "newlib"; }; - + aarch64be-embedded = { config = "aarch64_be-none-elf"; libc = "newlib"; @@ -126,7 +126,7 @@ rec { config = "powerpc-none-eabi"; libc = "newlib"; }; - + ppcle-embedded = { config = "powerpcle-none-eabi"; libc = "newlib"; @@ -211,4 +211,14 @@ rec { config = "x86_64-unknown-netbsd"; libc = "nblibc"; }; + + # + # WASM + # + + wasi32 = { + config = "wasm32-unknown-wasi"; + useLLVM = true; + }; + } diff --git a/lib/systems/for-meta.nix b/lib/systems/for-meta.nix index 51fb6ae760d..17ae94deb7d 100644 --- a/lib/systems/for-meta.nix +++ b/lib/systems/for-meta.nix @@ -32,6 +32,7 @@ in rec { openbsd = [ patterns.isOpenBSD ]; unix = patterns.isUnix; # Actually a list windows = [ patterns.isWindows ]; + wasi = [ patterns.isWasi ]; inherit (lib.systems.doubles) mesaPlatforms; } diff --git a/lib/systems/inspect.nix b/lib/systems/inspect.nix index f8d5ca84d7a..b88af55e46b 100644 --- a/lib/systems/inspect.nix +++ b/lib/systems/inspect.nix @@ -43,9 +43,10 @@ rec { isWindows = { kernel = kernels.windows; }; isCygwin = { kernel = kernels.windows; abi = abis.cygnus; }; isMinGW = { kernel = kernels.windows; abi = abis.gnu; }; + isWasi = { kernel = kernels.wasi; }; isAndroid = [ { abi = abis.android; } { abi = abis.androideabi; } ]; - isMusl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ]; + isMusl = (with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ]) ++ [{ kernel = kernels.wasi; }]; isUClibc = with abis; map (a: { abi = a; }) [ uclibc uclibceabi uclibceabihf ]; isEfi = map (family: { cpu.family = family; }) diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix index 3e23a721f0d..522a3bf71af 100644 --- a/lib/systems/parse.nix +++ b/lib/systems/parse.nix @@ -226,6 +226,7 @@ rec { elf = {}; macho = {}; pe = {}; + wasm = {}; unknown = {}; }; @@ -268,6 +269,7 @@ rec { none = { execFormat = unknown; families = { }; }; openbsd = { execFormat = elf; families = { inherit bsd; }; }; solaris = { execFormat = elf; families = { }; }; + wasi = { execFormat = wasm; families = { }; }; windows = { execFormat = pe; families = { }; }; } // { # aliases # 'darwin' is the kernel for all of them. We choose macOS by default. @@ -376,6 +378,8 @@ rec { then { cpu = elemAt l 0; kernel = elemAt l 1; abi = elemAt l 2; } else if (elemAt l 2 == "mingw32") # autotools breaks on -gnu for window then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows"; } + else if (elemAt l 2 == "wasi") + then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "wasi"; } else if hasPrefix "netbsd" (elemAt l 2) then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; } else if (elem (elemAt l 2) ["eabi" "eabihf" "elf"]) diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix index 964ff117553..e1ec09bc95a 100644 --- a/pkgs/build-support/bintools-wrapper/default.nix +++ b/pkgs/build-support/bintools-wrapper/default.nix @@ -191,7 +191,8 @@ stdenv.mkDerivation { else if targetPlatform.isAvr then "avr" else if targetPlatform.isAlpha then "alpha" else throw "unknown emulation for platform: ${targetPlatform.config}"; - in targetPlatform.platform.bfdEmulation or (fmt + sep + arch); + in if targetPlatform.useLLVM or false then "" + else targetPlatform.platform.bfdEmulation or (fmt + sep + arch); strictDeps = true; depsTargetTargetPropagated = extraPackages; diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index 9569c6e78c8..ddec3d0931f 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -299,6 +299,12 @@ stdenv.mkDerivation { hardening_unsupported_flags+=" stackprotector fortify pie pic" '' + + optionalString targetPlatform.isWasm '' + hardening_unsupported_flags+=" stackprotector fortify pie pic" + '' + optionalString (targetPlatform.isWasm && libc != null) '' + echo "--allow-undefined-file=${libc}/share/wasm32-wasi/undefined-symbols.txt" >> $out/nix-support/cc-ldflags + '' + + optionalString (libc != null && targetPlatform.isAvr) '' for isa in avr5 avr3 avr4 avr6 avr25 avr31 avr35 avr51 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack; do echo "-B${getLib libc}/avr/lib/$isa" >> $out/nix-support/libc-cflags diff --git a/pkgs/development/compilers/llvm/8/compiler-rt.nix b/pkgs/development/compilers/llvm/8/compiler-rt.nix index 47c8b7bd59f..3e225626aa6 100644 --- a/pkgs/development/compilers/llvm/8/compiler-rt.nix +++ b/pkgs/development/compilers/llvm/8/compiler-rt.nix @@ -60,7 +60,11 @@ stdenv.mkDerivation rec { ln -s $out/lib/*/clang_rt.crtend-*.o $out/lib/crtend.o ln -s $out/lib/*/clang_rt.crtbegin_shared-*.o $out/lib/crtbeginS.o ln -s $out/lib/*/clang_rt.crtend_shared-*.o $out/lib/crtendS.o + '' + stdenv.lib.optionalString stdenv.hostPlatform.isWasm '' + ln -s $out/lib/*/* $out/lib ''; + NIX_LDFLAGS = stdenv.lib.optionalString stdenv.hostPlatform.isWasm "--allow-undefined --no-entry"; + enableParallelBuilding = true; } diff --git a/pkgs/development/compilers/llvm/8/default.nix b/pkgs/development/compilers/llvm/8/default.nix index 3503e6b83d2..c528f8417cf 100644 --- a/pkgs/development/compilers/llvm/8/default.nix +++ b/pkgs/development/compilers/llvm/8/default.nix @@ -97,12 +97,14 @@ let targetLlvmLibraries.libcxx targetLlvmLibraries.libcxxabi targetLlvmLibraries.compiler-rt + ] ++ stdenv.lib.optionals (!stdenv.targetPlatform.isWasm) [ targetLlvmLibraries.libunwind ]; extraBuildCommands = '' echo "-target ${stdenv.targetPlatform.config}" >> $out/nix-support/cc-cflags echo "-rtlib=compiler-rt -Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags + '' + stdenv.lib.optionalString (!stdenv.targetPlatform.isWasm) '' echo "--unwindlib=libunwind" >> $out/nix-support/cc-cflags '' + mkExtraBuildCommands cc; }; diff --git a/pkgs/development/compilers/llvm/8/libc++/default.nix b/pkgs/development/compilers/llvm/8/libc++/default.nix index d0a5c37c414..8b4452a6de2 100644 --- a/pkgs/development/compilers/llvm/8/libc++/default.nix +++ b/pkgs/development/compilers/llvm/8/libc++/default.nix @@ -1,4 +1,5 @@ -{ lib, stdenv, fetch, cmake, python, libcxxabi, fixDarwinDylibNames, version }: +{ lib, stdenv, fetch, cmake, python, libcxxabi, fixDarwinDylibNames, version +, enableShared ? true }: stdenv.mkDerivation rec { name = "libc++-${version}"; @@ -31,7 +32,11 @@ stdenv.mkDerivation rec { "-DLIBCXX_LIBCPPABI_VERSION=2" "-DLIBCXX_CXX_ABI=libcxxabi" ] ++ stdenv.lib.optional stdenv.hostPlatform.isMusl "-DLIBCXX_HAS_MUSL_LIBC=1" - ++ stdenv.lib.optional (stdenv.hostPlatform.useLLVM or false) "-DLIBCXX_USE_COMPILER_RT=ON"; + ++ stdenv.lib.optional (stdenv.hostPlatform.useLLVM or false) "-DLIBCXX_USE_COMPILER_RT=ON" + ++ stdenv.lib.optional stdenv.hostPlatform.isWasm [ + "-DLIBCXX_ENABLE_THREADS=OFF" + "-DLIBCXX_ENABLE_FILESYSTEM=OFF" + ] ++ stdenv.lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF"; enableParallelBuilding = true; @@ -46,6 +51,6 @@ stdenv.mkDerivation rec { homepage = http://libcxx.llvm.org/; description = "A new implementation of the C++ standard library, targeting C++11"; license = with stdenv.lib.licenses; [ ncsa mit ]; - platforms = stdenv.lib.platforms.unix; + platforms = stdenv.lib.platforms.all; }; } diff --git a/pkgs/development/compilers/llvm/8/libc++abi.nix b/pkgs/development/compilers/llvm/8/libc++abi.nix index 0eb5ebca515..e264a384941 100644 --- a/pkgs/development/compilers/llvm/8/libc++abi.nix +++ b/pkgs/development/compilers/llvm/8/libc++abi.nix @@ -1,4 +1,5 @@ -{ stdenv, cmake, fetch, libcxx, libunwind, llvm, version }: +{ stdenv, cmake, fetch, libcxx, libunwind, llvm, version +, enableShared ? true }: stdenv.mkDerivation { name = "libc++abi-${version}"; @@ -6,13 +7,20 @@ stdenv.mkDerivation { src = fetch "libcxxabi" "1k875f977ybdkpdnr9105wa6hccy9qvpd9xd42n75h7p56bdxmn2"; nativeBuildInputs = [ cmake ]; - buildInputs = stdenv.lib.optional (!stdenv.isDarwin && !stdenv.isFreeBSD) libunwind; + buildInputs = stdenv.lib.optional (!stdenv.isDarwin && !stdenv.isFreeBSD && !stdenv.hostPlatform.isWasm) libunwind; cmakeFlags = stdenv.lib.optionals (stdenv.hostPlatform.useLLVM or false) [ "-DLLVM_ENABLE_LIBCXX=ON" "-DLIBCXXABI_USE_LLVM_UNWINDER=ON" + ] ++ stdenv.lib.optionals stdenv.hostPlatform.isWasm [ + "-DUNIX=ON" + "-DLIBCXXABI_ENABLE_THREADS=OFF" + ] ++ stdenv.lib.optionals (!enableShared) [ + "-DLIBCXXABI_ENABLE_SHARED=OFF" ]; + patches = [ ./libcxxabi-no-threads.patch ]; + postUnpack = '' unpackFile ${libcxx.src} unpackFile ${llvm.src} @@ -39,8 +47,9 @@ stdenv.mkDerivation { else '' install -d -m 755 $out/include $out/lib install -m 644 lib/libc++abi.a $out/lib - install -m 644 lib/libc++abi.so.1.0 $out/lib install -m 644 ../include/cxxabi.h $out/include + '' + stdenv.lib.optionalString enableShared '' + install -m 644 lib/libc++abi.so.1.0 $out/lib ln -s libc++abi.so.1.0 $out/lib/libc++abi.so ln -s libc++abi.so.1.0 $out/lib/libc++abi.so.1 ''; @@ -50,6 +59,6 @@ stdenv.mkDerivation { description = "A new implementation of low level support for a standard C++ library"; license = with stdenv.lib.licenses; [ ncsa mit ]; maintainers = with stdenv.lib.maintainers; [ vlstill ]; - platforms = stdenv.lib.platforms.unix; + platforms = stdenv.lib.platforms.all; }; } diff --git a/pkgs/development/compilers/llvm/8/libcxxabi-no-threads.patch b/pkgs/development/compilers/llvm/8/libcxxabi-no-threads.patch new file mode 100644 index 00000000000..787f3e16500 --- /dev/null +++ b/pkgs/development/compilers/llvm/8/libcxxabi-no-threads.patch @@ -0,0 +1,12 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 4138acf..41b4763 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -362,6 +362,7 @@ if (NOT LIBCXXABI_ENABLE_THREADS) + " is also set to ON.") + endif() + add_definitions(-D_LIBCXXABI_HAS_NO_THREADS) ++ add_definitions(-D_LIBCPP_HAS_NO_THREADS) + endif() + + if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) diff --git a/pkgs/development/libraries/wasilibc/default.nix b/pkgs/development/libraries/wasilibc/default.nix new file mode 100644 index 00000000000..f783540797c --- /dev/null +++ b/pkgs/development/libraries/wasilibc/default.nix @@ -0,0 +1,28 @@ +{ stdenv, fetchFromGitHub, lib }: + +stdenv.mkDerivation { + name = "wasilibc-20190413"; + src = fetchFromGitHub { + owner = "CraneStation"; + repo = "wasi-sysroot"; + rev = "079d7bda78bc0ad8f69c1594444b54786545ce57"; + sha256 = "09s906bc9485wzkgibnpfh0mii7jkldzr1a6g8k7ch0si8rshi5r"; + }; + makeFlags = [ + "WASM_CC=${stdenv.cc.targetPrefix}cc" + "WASM_NM=${stdenv.cc.targetPrefix}nm" + "WASM_AR=${stdenv.cc.targetPrefix}ar" + "INSTALL_DIR=${placeholder "out"}" + ]; + + postInstall = '' + mv $out/lib/*/* $out/lib + ''; + + meta = { + description = "WASI libc implementation for WebAssembly"; + homepage = "https://wasi.dev"; + platforms = lib.platforms.wasi; + maintainers = [ lib.maintainers.matthewbauer ]; + }; +} diff --git a/pkgs/stdenv/cross/default.nix b/pkgs/stdenv/cross/default.nix index fc9a585cf4d..479213f3a56 100644 --- a/pkgs/stdenv/cross/default.nix +++ b/pkgs/stdenv/cross/default.nix @@ -37,7 +37,8 @@ in lib.init bootStages ++ [ # Run Packages (buildPackages: { inherit config; - overlays = overlays ++ crossOverlays; + overlays = overlays ++ crossOverlays + ++ (if crossSystem.isWasm then [(import ../../top-level/static.nix)] else []); selfBuild = false; stdenv = buildPackages.stdenv.override (old: rec { buildPlatform = localSystem; diff --git a/pkgs/stdenv/generic/default.nix b/pkgs/stdenv/generic/default.nix index 04117de3269..ed022422c26 100644 --- a/pkgs/stdenv/generic/default.nix +++ b/pkgs/stdenv/generic/default.nix @@ -91,6 +91,9 @@ let '' + lib.optionalString hostPlatform.isDarwin '' export NIX_DONT_SET_RPATH=1 export NIX_NO_SELF_RPATH=1 + '' + lib.optionalString (hostPlatform.parsed.kernel.execFormat != lib.systems.parse.execFormats.elf && hostPlatform.parsed.kernel.execFormat != lib.systems.parse.execFormats.macho) '' + export NIX_DONT_SET_RPATH=1 + export NIX_NO_SELF_RPATH=1 '' # TODO this should be uncommented, but it causes stupid mass rebuilds. I # think the best solution would just be to fixup linux RPATHs so we don't diff --git a/pkgs/test/cross/default.nix b/pkgs/test/cross/default.nix index 5d9c120c501..6c31a16f2fd 100644 --- a/pkgs/test/cross/default.nix +++ b/pkgs/test/cross/default.nix @@ -93,8 +93,7 @@ let }; -in (lib.mapAttrs (_: mapMultiPlatformTest builtins.id) tests) -// (lib.mapAttrs' (name: test: { - name = "${name}-llvm"; - value = mapMultiPlatformTest (system: system // {useLLVM = true;}) test; - }) tests) +in { + gcc = (lib.mapAttrs (_: mapMultiPlatformTest (system: system // {useLLVM = false;})) tests); + llvm = (lib.mapAttrs (_: mapMultiPlatformTest (system: system // {useLLVM = true;})) tests); +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 13bc8ebfaf0..c07533522a8 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -10311,10 +10311,15 @@ in else if stdenv.targetPlatform.useiOSPrebuilt then targetPackages.darwin.iosSdkPkgs.libraries or darwin.iosSdkPkgs.libraries else if name == "libSystem" then targetPackages.darwin.xcode else if name == "nblibc" then targetPackages.netbsdCross.libc - else throw "Unknown libc"; + else if name == "wasilibc" then targetPackages.wasilibc + else throw "Unknown libc ${name}"; libcCross = assert stdenv.targetPlatform != stdenv.buildPlatform; libcCrossChooser stdenv.targetPlatform.libc; + wasilibc = callPackages ../development/libraries/wasilibc { + stdenv = crossLibcStdenv; + }; + # Only supported on Linux, using glibc glibcLocales = if stdenv.hostPlatform.libc == "glibc" then callPackage ../development/libraries/glibc/locales.nix { } else null; diff --git a/pkgs/top-level/static.nix b/pkgs/top-level/static.nix index fe9c04de04c..dea30fe7b59 100644 --- a/pkgs/top-level/static.nix +++ b/pkgs/top-level/static.nix @@ -148,4 +148,16 @@ in { }; }; + llvmPackages_8 = super.llvmPackages_8 // { + libraries = super.llvmPackages_8.libraries // rec { + libcxxabi = super.llvmPackages_8.libraries.libcxxabi.override { + enableShared = false; + }; + libcxx = super.llvmPackages_8.libraries.libcxx.override { + enableShared = false; + inherit libcxxabi; + }; + }; + }; + }