Skip to content

Commit bffc217

Browse files
committed
Use libffi-wasm when building for wasi32
1 parent 2c920fd commit bffc217

File tree

4 files changed

+81
-37
lines changed

4 files changed

+81
-37
lines changed

ci.nix

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
|| (system == "aarch64-darwin" && !builtins.elem compiler-nix-name ["ghc902" "ghc928" "ghc948" "ghc966" "ghc967" "ghc96720250227" "ghc982" "ghc983" "ghc984"])
8484
)) {
8585
inherit (lib.systems.examples) ghcjs;
86+
inherit (lib.systems.examples) wasi32;
8687
} // lib.optionalAttrs (nixpkgsName == "unstable"
8788
&& (__match ".*llvm" compiler-nix-name == null)
8889
&& ((system == "x86_64-linux" && !builtins.elem compiler-nix-name ["ghc902" "ghc928" "ghc966" "ghc967" "ghc96720250227"]) # Not sure why GHC 9.6.6 TH code now wants `log1pf`

compiler/ghc/default.nix

+57-12
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let self =
2121
libffi ? null
2222

2323
, # we don't need LLVM for x86, aarch64, or ghcjs
24-
useLLVM ? with stdenv.targetPlatform; !(isx86 || isAarch64 || isGhcjs)
24+
useLLVM ? with stdenv.targetPlatform; !(isx86 || isAarch64 || isGhcjs || isWasm)
2525
, # LLVM is conceptually a run-time-only dependency, but for
2626
# non-x86, we need LLVM to bootstrap later stages, so it becomes a
2727
# build-time dependency too.
@@ -117,14 +117,45 @@ let
117117
INTEGER_LIBRARY = ${if enableIntegerSimple then "integer-simple" else "integer-gmp"}
118118
'';
119119

120+
libffi-wasm = buildPackages.runCommand "libffi-wasm" {
121+
nativeBuildInputs = [
122+
(buildPackages.haskell-nix.tool "ghc912" "libffi-wasm" {
123+
src = buildPackages.haskell-nix.sources.libffi-wasm;
124+
})
125+
buildPackages.clang
126+
targetPackages.buildPackages.clang
127+
targetPackages.buildPackages.llvm
128+
targetPackages.buildPackages.binaryen
129+
];
130+
outputs = ["dev" "out"];
131+
NIX_NO_SELF_RPATH = true;
132+
} ''
133+
mkdir cbits
134+
cp ${buildPackages.haskell-nix.sources.libffi-wasm}/cbits/* cbits/
135+
libffi-wasm
136+
wasm32-unknown-wasi-clang -Wall -Wextra -mcpu=mvp -Oz -DNDEBUG -Icbits -c cbits/ffi.c -o cbits/ffi.o
137+
wasm32-unknown-wasi-clang -Wall -Wextra -mcpu=mvp -Oz -DNDEBUG -Icbits -c cbits/ffi_call.c -o cbits/ffi_call.o
138+
wasm32-unknown-wasi-clang -Wall -Wextra -mcpu=mvp -Oz -DNDEBUG -Icbits -c cbits/ffi_closure.c -o cbits/ffi_closure.o
139+
140+
mkdir -p $dev/include
141+
cp cbits/*.h $dev/include
142+
mkdir -p $out/lib
143+
llvm-ar -r $out/lib/libffi.a cbits/*.o
144+
145+
wasm32-unknown-wasi-clang -Wall -Wextra -mcpu=mvp -Oz -DNDEBUG -Icbits -fPIC -fvisibility=default -shared -Wl,--keep-section=target_features,--strip-debug cbits/*.c -o libffi.so
146+
wasm-opt --low-memory-unused --converge --debuginfo --flatten --rereloop --gufa -O4 -Oz libffi.so -o $out/lib/libffi.so
147+
'';
148+
120149
# TODO check if this possible fix for segfaults works or not.
121150
targetLibffi =
122151
# on native platforms targetPlatform.{libffi, gmp} do not exist; thus fall back
123152
# to the non-targetPlatform version in those cases.
124153
let targetLibffi = targetPackages.libffi or libffi; in
125154
# we need to set `dontDisableStatic` for musl for libffi to work.
126155
if stdenv.targetPlatform.isMusl
127-
then targetLibffi.overrideAttrs (_old: { dontDisableStatic = true; })
156+
then targetLibffi.overrideAttrs (_old: { dontDisableStatic = true; })
157+
else if stdenv.targetPlatform.isWasm
158+
then libffi-wasm
128159
else targetLibffi;
129160

130161
targetGmp = targetPackages.gmp or gmp;
@@ -195,13 +226,14 @@ let
195226
# `--with` flags for libraries needed for RTS linker
196227
configureFlags = [
197228
"--datadir=$doc/share/doc/ghc"
198-
] ++ lib.optionals (!targetPlatform.isGhcjs && !targetPlatform.isAndroid) ["--with-curses-includes=${targetPackages.ncurses.dev}/include" "--with-curses-libraries=${targetPackages.ncurses.out}/lib"
199-
] ++ lib.optionals (targetLibffi != null && !targetPlatform.isGhcjs) ["--with-system-libffi" "--with-ffi-includes=${targetLibffi.dev}/include" "--with-ffi-libraries=${targetLibffi.out}/lib"
200-
] ++ lib.optionals (!enableIntegerSimple && !targetPlatform.isGhcjs) [
229+
] ++ lib.optionals (!targetPlatform.isGhcjs && !targetPlatform.isWasm && !targetPlatform.isAndroid) ["--with-curses-includes=${targetPackages.ncurses.dev}/include" "--with-curses-libraries=${targetPackages.ncurses.out}/lib"
230+
] ++ lib.optionals (targetLibffi != null && !targetPlatform.isGhcjs && !targetPlatform.isWasm) ["--with-system-libffi" "--with-ffi-includes=${targetLibffi.dev}/include" "--with-ffi-libraries=${targetLibffi.out}/lib"
231+
] ++ lib.optionals (targetPlatform.isWasm) ["--with-system-libffi"
232+
] ++ lib.optionals (!enableIntegerSimple && !targetPlatform.isGhcjs && !targetPlatform.isWasm) [
201233
"--with-gmp-includes=${targetGmp.dev}/include" "--with-gmp-libraries=${targetGmp.out}/lib"
202234
] ++ lib.optionals (targetPlatform == hostPlatform && hostPlatform.libc != "glibc" && !targetPlatform.isWindows) [
203235
"--with-iconv-includes=${libiconv}/include" "--with-iconv-libraries=${libiconv}/lib"
204-
] ++ lib.optionals (targetPlatform != hostPlatform && !targetPlatform.isGhcjs) [
236+
] ++ lib.optionals (targetPlatform != hostPlatform && !targetPlatform.isGhcjs && !targetPlatform.isWasm) [
205237
"--with-iconv-includes=${targetIconv}/include" "--with-iconv-libraries=${targetIconv}/lib"
206238
] ++ lib.optionals (targetPlatform != hostPlatform) [
207239
"--enable-bootstrap-with-devel-snapshot"
@@ -229,9 +261,9 @@ let
229261
;
230262

231263
# Splicer will pull out correct variations
232-
libDeps = platform: lib.optional (enableTerminfo && !targetPlatform.isGhcjs && !targetPlatform.isAndroid) [ targetPackages.ncurses targetPackages.ncurses.dev ]
264+
libDeps = platform: lib.optional (enableTerminfo && !targetPlatform.isGhcjs && !targetPlatform.isWasm && !targetPlatform.isAndroid) [ targetPackages.ncurses targetPackages.ncurses.dev ]
233265
++ lib.optional (!targetPlatform.isGhcjs) targetLibffi
234-
++ lib.optional (!enableIntegerSimple && !targetPlatform.isGhcjs) gmp
266+
++ lib.optional (!enableIntegerSimple && !targetPlatform.isGhcjs && !targetPlatform.isWasm) gmp
235267
++ lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows) libiconv
236268
++ lib.optional (enableNUMA && platform.isLinux && !platform.isAarch32 && !platform.isAndroid) numactl
237269
++ lib.optional enableDWARF (lib.getLib elfutils);
@@ -306,12 +338,12 @@ let
306338
# For build flavours and flavour transformers
307339
# see https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/doc/flavours.md
308340
hadrianArgs = "--flavour=${
309-
(if targetPlatform.isGhcjs then "quick" else "default")
341+
(if targetPlatform.isGhcjs || targetPlatform.isWasm then "quick" else "default")
310342
+ lib.optionalString (!enableShared) "+no_dynamic_ghc"
311343
+ lib.optionalString useLLVM "+llvm"
312344
+ lib.optionalString enableDWARF "+debug_info"
313-
+ lib.optionalString ((enableNativeBignum && hadrianHasNativeBignumFlavour) || targetPlatform.isGhcjs) "+native_bignum"
314-
+ lib.optionalString targetPlatform.isGhcjs "+no_profiled_libs"
345+
+ lib.optionalString ((enableNativeBignum && hadrianHasNativeBignumFlavour) || targetPlatform.isGhcjs || targetPlatform.isWasm) "+native_bignum"
346+
+ lib.optionalString (targetPlatform.isGhcjs || targetPlatform.isWasm) "+no_profiled_libs"
315347
} --docs=no-sphinx -j --verbose"
316348
# This is needed to prevent $GCC from emitting out of line atomics.
317349
# Those would then result in __aarch64_ldadd1_sync and others being referenced, which
@@ -425,9 +457,22 @@ haskell-nix.haskellLib.makeCompilerDeps (stdenv.mkDerivation (rec {
425457
export EM_CACHE=$(mktemp -d)
426458
mv config.sub.ghcjs config.sub
427459
'')
460+
+ lib.optionalString (targetPlatform.isWasm) ''
461+
export CC="${targetCC}/bin/${targetCC.targetPrefix}cc"
462+
export CXX="${targetCC}/bin/${targetCC.targetPrefix}c++"
463+
export LD="${buildPackages.llvmPackages.lld}/bin/wasm-ld"
464+
export AS="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}as"
465+
export AR="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}ar"
466+
export NM="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}nm"
467+
export RANLIB="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}ranlib"
468+
export READELF="${targetCC.bintools.bintools}/bin/${targetCC.bintools.targetPrefix}readelf"
469+
export STRIP="${bintoolsFor.strip}/bin/${bintoolsFor.strip.targetPrefix}strip"
470+
export NIX_CFLAGS_COMPILE_FOR_BUILD+=" -I${libffi.dev}/include -L${libffi.out}/lib"
471+
export NIX_CFLAGS_COMPILE_FOR_TARGET+=" -I${targetLibffi.dev}/include -L${targetLibffi.out}/lib"
472+
''
428473
# GHC is a bit confused on its cross terminology, as these would normally be
429474
# the *host* tools.
430-
+ lib.optionalString (!targetPlatform.isGhcjs) (''
475+
+ lib.optionalString (!targetPlatform.isGhcjs && !targetPlatform.isWasm) (''
431476
export CC="${targetCC}/bin/${targetCC.targetPrefix}cc"
432477
export CXX="${targetCC}/bin/${targetCC.targetPrefix}c++"
433478
''

flake.lock

+19-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

+4-7
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,6 @@
4949
url = "github:input-output-hk/cardano-shell";
5050
flake = false;
5151
};
52-
"ghc-8.6.5-iohk" = {
53-
type = "github";
54-
owner = "input-output-hk";
55-
repo = "ghc";
56-
ref = "release/8.6.5-iohk";
57-
flake = false;
58-
};
5952
hpc-coveralls = {
6053
url = "github:sevanspowell/hpc-coveralls";
6154
flake = false;
@@ -72,6 +65,10 @@
7265
url = "github:stable-haskell/iserv-proxy?ref=iserv-syms";
7366
flake = false;
7467
};
68+
libffi-wasm = {
69+
url = "gitlab:haskell-wasm/libffi-wasm?host=gitlab.haskell.org";
70+
flake = false;
71+
};
7572
};
7673

7774
outputs =

0 commit comments

Comments
 (0)