Skip to content
7 changes: 6 additions & 1 deletion pkgs/development/compilers/emscripten/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ stdenv.mkDerivation rec {
# HACK: Make emscripten look more like a cc-wrapper to GHC
# when building the javascript backend.
targetPrefix = "em";
bintools = emscripten;
bintools = emscripten.overrideAttrs (old: {
passthru = old.passthru // {
# emscripten wraps LLVM bintools, GHC checks for this fact
isLLVM = true;
};
});
};

meta = with lib; {
Expand Down
31 changes: 24 additions & 7 deletions pkgs/development/compilers/ghc/common-hadrian.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

{ lib
, stdenv
, pkgsBuildBuild
, pkgsBuildTarget
, pkgsHostTarget
, targetPackages
Expand All @@ -36,11 +37,15 @@
, # GHC can be built with system libffi or a bundled one.
libffi ? null

, # TODO(@sternenseemann): this is ugly as hell
libffiAttr ? "libffi"

, useLLVM ? !(stdenv.targetPlatform.isx86
|| stdenv.targetPlatform.isPower
|| stdenv.targetPlatform.isSparc
|| (stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin)
|| stdenv.targetPlatform.isGhcjs)
|| stdenv.targetPlatform.isGhcjs
|| stdenv.targetPlatform.isWasm)
, # LLVM is conceptually a run-time-only dependency, but for
# non-x86, we need LLVM to bootstrap later stages, so it becomes a
# build-time dependency too.
Expand All @@ -52,6 +57,7 @@
enableNativeBignum ? !(lib.meta.availableOn stdenv.hostPlatform gmp
&& lib.meta.availableOn stdenv.targetPlatform gmp)
|| stdenv.targetPlatform.isGhcjs
|| stdenv.targetPlatform.isWasm
, gmp

, # If enabled, use -fPIC when compiling static libs.
Expand All @@ -62,11 +68,12 @@

, # Whether to build dynamic libs for the standard library (on the target
# platform). Static libs are always built.
enableShared ? with stdenv.targetPlatform; !isWindows && !useiOSPrebuilt && !isStatic && !isGhcjs
enableShared ? with stdenv.targetPlatform; !isWindows && !useiOSPrebuilt && !isStatic && !isGhcjs && !isWasm

, # Whether to build terminfo.
enableTerminfo ? !(stdenv.targetPlatform.isWindows
|| stdenv.targetPlatform.isGhcjs)
|| stdenv.targetPlatform.isGhcjs
|| stdenv.targetPlatform.isWasm)

, # Libdw.c only supports x86_64, i686 and s390x as of 2022-08-04
enableDwarf ? (stdenv.targetPlatform.isx86 ||
Expand Down Expand Up @@ -203,7 +210,7 @@ let
# https://gitlab.haskell.org/ghc/ghc/-/issues/22081
++ lib.optional enableDwarf elfutils
++ lib.optional (!enableNativeBignum) gmp
++ lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows && !targetPlatform.isGhcjs) libiconv;
++ lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows && !targetPlatform.isGhcjs && !targetPlatform.isWasm) libiconv;

# TODO(@sternenseemann): is buildTarget LLVM unnecessary?
# GHC doesn't seem to have {LLC,OPT}_HOST
Expand All @@ -226,9 +233,11 @@ let
then targetCC.bintools
else targetCC.bintools.bintools;
# Same goes for strip.
# Additionally, if we are using LLVM bintools, they will be always wrapped.
strip =
# TODO(@sternenseemann): also use wrapper if linker == "bfd" or "gold"
if stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin
if (stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin)
|| targetCC.bintools.isLLVM
then targetCC.bintools
else targetCC.bintools.bintools;
};
Expand Down Expand Up @@ -287,6 +296,10 @@ stdenv.mkDerivation ({
export RANLIB="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}ranlib"
export READELF="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}readelf"
export STRIP="${bintoolsFor.strip}/bin/${bintoolsFor.strip.targetPrefix}strip"
# CC_FOR_BUILD etc. become CC_STAGE0
export CC_STAGE0="$CC_FOR_BUILD"
export AR_STAGE0="$AR_FOR_BUILD"
export LD_STAGE0="$LD_FOR_BUILD"
'' + lib.optionalString (stdenv.targetPlatform.linker == "cctools") ''
export OTOOL="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}otool"
export INSTALL_NAME_TOOL="${bintoolsFor.install_name_tool}/bin/${bintoolsFor.install_name_tool.targetPrefix}install_name_tool"
Expand Down Expand Up @@ -365,8 +378,8 @@ stdenv.mkDerivation ({
"--with-curses-includes=${ncurses.dev}/include" "--with-curses-libraries=${ncurses.out}/lib"
] ++ lib.optionals (libffi != null && !targetPlatform.isGhcjs) [
"--with-system-libffi"
"--with-ffi-includes=${targetPackages.libffi.dev}/include"
"--with-ffi-libraries=${targetPackages.libffi.out}/lib"
"--with-ffi-includes=${targetPackages.${libffiAttr}.dev}/include"
"--with-ffi-libraries=${targetPackages.${libffiAttr}.out}/lib"
] ++ lib.optionals (targetPlatform == hostPlatform && !enableNativeBignum) [
"--with-gmp-includes=${targetPackages.gmp.dev}/include"
"--with-gmp-libraries=${targetPackages.gmp.out}/lib"
Expand Down Expand Up @@ -408,6 +421,10 @@ stdenv.mkDerivation ({
# For building runtime libs
depsBuildTarget = toolsForTarget;

depsBuildBuild = [
pkgsBuildBuild.targetPackages.stdenv.cc
];

buildInputs = [ perl bash ] ++ (libDeps hostPlatform);

depsTargetTarget = map lib.getDev (libDeps targetPlatform);
Expand Down
6 changes: 4 additions & 2 deletions pkgs/development/compilers/llvm/16/libcxx/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ stdenv.mkDerivation rec {
outputs = [ "out" ] ++ lib.optional (!headersOnly) "dev";

prePatch = ''
cd ../${basename}
cd ../
chmod -R u+w .
cd ${basename}
patch -d ../llvm -p1 -i "${../libcxxabi/wasm.patch}"
'';

patches = [
Expand Down Expand Up @@ -77,7 +79,7 @@ stdenv.mkDerivation rec {
++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
++ lib.optional (stdenv.hostPlatform.useLLVM or false) "-DLIBCXX_USE_COMPILER_RT=ON"
++ lib.optionals stdenv.hostPlatform.isWasm [
"-DLIBCXX_ENABLE_THREADS=OFF"
"-DLIBCXX_ENABLE_THREADS=${if stdenv.cc.libc.hasThreads then "ON" else "OFF"}"
"-DLIBCXX_ENABLE_FILESYSTEM=OFF"
"-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF"
Expand Down
31 changes: 24 additions & 7 deletions pkgs/development/compilers/llvm/16/libcxxabi/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ stdenv.mkDerivation rec {

postUnpack = lib.optionalString stdenv.isDarwin ''
export TRIPLE=x86_64-apple-darwin
'' + lib.optionalString stdenv.hostPlatform.isWasm ''
patch -p1 -d llvm -i ${./wasm.patch}
'';

prePatch = ''
cd ../${pname}
cd ../
chmod -R u+w .
cd ${pname}
patch -p1 -d ../llvm -i ${./wasm.patch}
'';

patches = [
Expand Down Expand Up @@ -65,13 +65,30 @@ stdenv.mkDerivation rec {
# CMake however checks for this anyways; this flag tells it not to. See:
# https://github.com/llvm/llvm-project/blob/4bd3f3759259548e159aeba5c76efb9a0864e6fa/llvm/runtimes/CMakeLists.txt#L243
"-DCMAKE_CXX_COMPILER_WORKS=ON"
"-DCMAKE_C_COMPILER_WORKS=ON"
] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [
"-DLLVM_ENABLE_LIBCXX=ON"
"-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
] ++ lib.optionals stdenv.hostPlatform.isWasm [
"-DLIBCXXABI_ENABLE_THREADS=OFF"
"-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
] ++ lib.optionals (!enableShared) [
] ++ lib.optionals stdenv.hostPlatform.isWasm (
[
"-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
# CMake tests for -fno-exceptions together with -lc++ -lc++abi which fails
# here, without -fno-exceptions, libc++abi is unusable later.
# See also: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=260005
# TODO(@sternenseemann): make this unconditional?
"-DCXX_SUPPORTS_FNO_EXCEPTIONS_FLAG=ON"
]
++ (if stdenv.cc.libc.hasThreads then [
"-DLIBCXXABI_ENABLE_THREADS=ON"
"-DLIBCXXABI_HAS_PTHREAD_API=ON"
"-DLIBCXXABI_HAS_EXTERNAL_THREAD_API=OFF"
"-DLIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY=OFF"
"-DLIBCXXABI_HAS_WIN32_THREAD_API=OFF"
] else [
"-DLIBCXXABI_ENABLE_THREADS=OFF"
])
)
++ lib.optionals (!enableShared) [
"-DLIBCXXABI_ENABLE_SHARED=OFF"
];

Expand Down
3 changes: 3 additions & 0 deletions pkgs/development/haskell-modules/non-hackage-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ self: super: {
# Unofficial fork until PRs are merged https://github.com/pcapriotti/optparse-applicative/pulls/roberth
# cabal2nix --maintainer roberth https://github.com/hercules-ci/optparse-applicative.git > pkgs/development/misc/haskell/hercules-ci-optparse-applicative.nix
hercules-ci-optparse-applicative = self.callPackage ../misc/haskell/hercules-ci-optparse-applicative.nix {};

# Codegen tool used by GHC for wasm FFI support
libffi-wasm = self.callPackage ../libraries/libffi-wasm-ghc/codegen.nix { };
}
32 changes: 32 additions & 0 deletions pkgs/development/libraries/libffi-wasm-ghc/codegen.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{ mkDerivation
, fetchFromGitLab
, base
, bytestring
, language-c
, lib
, pretty
, tasty
, unliftio
}:
mkDerivation {
pname = "libffi-wasm";
version = "unstable-2022-11-10";
src = fetchFromGitLab {
domain = "gitlab.haskell.org";
owner = "ghc";
repo = "libffi-wasm";
rev = "4914da7d7b8b68abf575a47bf88f64b8e1c47ca7";
sha256 = "0x06bp1mr977g7w4pinp010rfipg3r4l0h92dc9jplbw2lxswhnm";
};
isLibrary = false;
isExecutable = true;
libraryHaskellDepends = [ base bytestring language-c pretty ];
executableHaskellDepends = [ base bytestring unliftio ];
testHaskellDepends = [ base tasty ];
doHaddock = false;
doCheck = true;
license = lib.licenses.bsd3;
maintainers = [ lib.maintainers.sternenseemann ];
mainProgram = "libffi-wasm";
homepage = "https://gitlab.haskell.org/ghc/libffi-wasm/";
}
62 changes: 62 additions & 0 deletions pkgs/development/libraries/libffi-wasm-ghc/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{ lib
, stdenv
, buildPackages
}:

let
# Codegen tool written by GHC upstream to generate the source for their port of
# libffi for wasm
libffi-wasm = buildPackages.haskellPackages.libffi-wasm;
in

stdenv.mkDerivation (finalAttrs: {
inherit (libffi-wasm) pname version src;

nativeBuildInputs = [
libffi-wasm
];

dontConfigure = true;

CFLAGS = [
"-Wall"
"-Wextra"
"-DNDEBUG"
"-O3"
"-Icbits"
];

# Based on https://gitlab.haskell.org/ghc/libffi-wasm/-/blob/master/.gitlab-ci.yml
buildPhase = ''
runHook preBuild

set -x

libffi-wasm

for f in cbits/ffi cbits/ffi_call cbits/ffi_closure; do
$CC $CFLAGS -c "$f.c" -o "$f.o"
done

$AR -rc libffi.a cbits/*.o

set +x

runHook postBuild
'';

outputs = [ "out" "dev" ];
installPhase = ''
runHook preInstall

install -Dm644 -t "$dev/include" cbits/*.h
install -Dm755 -t "$out/lib" libffi.a

runHook postInstall
'';

meta = {
inherit (libffi-wasm.meta) maintainers license homepage;
platforms = lib.platforms.wasi;
};
})
54 changes: 48 additions & 6 deletions pkgs/development/libraries/wasilibc/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
, buildPackages
, fetchFromGitHub
, lib
# Enable experimental wasilibc pthread support
, enableThreads ? false
# For tests
, firefox-unwrapped
, firefox-esr-unwrapped
, pkgsCross
, wasmtime
}:

let
pname = "wasilibc";
version = "19";
version = "20";
in
stdenv.mkDerivation {
inherit pname version;
Expand All @@ -17,7 +22,7 @@ stdenv.mkDerivation {
owner = "WebAssembly";
repo = "wasi-libc";
rev = "refs/tags/wasi-sdk-${version}";
hash = "sha256-yQSKoSil/C/1lIHwEO9eQKC/ye3PJIFGYjHyNDn61y4=";
sha256 = "0knm5ch499dksmv1k0kh7356pjd9n1gjn0p3vp9bw57mn478zp8z";
fetchSubmodules = true;
};

Expand All @@ -38,8 +43,7 @@ stdenv.mkDerivation {
"SYSROOT_LIB:=$SYSROOT_LIB"
"SYSROOT_INC:=$SYSROOT_INC"
"SYSROOT_SHARE:=$SYSROOT_SHARE"
# https://bugzilla.mozilla.org/show_bug.cgi?id=1773200
"BULK_MEMORY_SOURCES:="
"THREAD_MODEL=${if enableThreads then "posix" else "single"}"
)

'';
Expand All @@ -53,8 +57,46 @@ stdenv.mkDerivation {
ln -s $share/share/undefined-symbols.txt $out/lib/wasi.imports
'';

passthru.tests = {
inherit firefox-unwrapped firefox-esr-unwrapped;
passthru = {
tests = {
inherit firefox-unwrapped firefox-esr-unwrapped;
simple-c-cxx-binaries = pkgsCross.wasi32.runCommandCC "simple-c-cxx-binaries" {
nativeBuildInputs = [
wasmtime
];
} ''
cat > test.c <<EOF
#include <stdio.h>
int main(void) {
puts("Hello from C");
return 0;
}
EOF
cat > test.cpp <<EOF
#include <iostream>
int main(void) {
std::cout<<"Hello from C++\n";
return 0;
}
EOF

mkdir -p "$out/bin"
# TODO(@sternenseemann): compile with -pthread if enableThreads
$CC -o "$out/bin/test-c" test.c
$CXX -o "$out/bin/test-cxx" test.cpp -lc++ -lc++abi

export HOME=$TMPDIR
export WASMTIME_FLAGS=(${
lib.escapeShellArgs (lib.optionals enableThreads [
"--wasm-features=threads"
"--wasi-modules=experimental-wasi-threads"
])
})
wasmtime run "''${WASMTIME_FLAGS[@]}" "$out/bin/test-c"
wasmtime run "''${WASMTIME_FLAGS[@]}" "$out/bin/test-cxx"
'';
};
hasThreads = enableThreads;
};

meta = with lib; {
Expand Down
Loading