@@ -21,7 +21,7 @@ let self =
21
21
libffi ? null
22
22
23
23
, # 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 )
25
25
, # LLVM is conceptually a run-time-only dependency, but for
26
26
# non-x86, we need LLVM to bootstrap later stages, so it becomes a
27
27
# build-time dependency too.
@@ -117,14 +117,45 @@ let
117
117
INTEGER_LIBRARY = ${ if enableIntegerSimple then "integer-simple" else "integer-gmp" }
118
118
'' ;
119
119
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
+
120
149
# TODO check if this possible fix for segfaults works or not.
121
150
targetLibffi =
122
151
# on native platforms targetPlatform.{libffi, gmp} do not exist; thus fall back
123
152
# to the non-targetPlatform version in those cases.
124
153
let targetLibffi = targetPackages . libffi or libffi ; in
125
154
# we need to set `dontDisableStatic` for musl for libffi to work.
126
155
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
128
159
else targetLibffi ;
129
160
130
161
targetGmp = targetPackages . gmp or gmp ;
@@ -195,13 +226,14 @@ let
195
226
# `--with` flags for libraries needed for RTS linker
196
227
configureFlags = [
197
228
"--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 ) [
201
233
"--with-gmp-includes=${ targetGmp . dev } /include" "--with-gmp-libraries=${ targetGmp . out } /lib"
202
234
] ++ lib . optionals ( targetPlatform == hostPlatform && hostPlatform . libc != "glibc" && ! targetPlatform . isWindows ) [
203
235
"--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 ) [
205
237
"--with-iconv-includes=${ targetIconv } /include" "--with-iconv-libraries=${ targetIconv } /lib"
206
238
] ++ lib . optionals ( targetPlatform != hostPlatform ) [
207
239
"--enable-bootstrap-with-devel-snapshot"
229
261
;
230
262
231
263
# 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 ]
233
265
++ lib . optional ( ! targetPlatform . isGhcjs ) targetLibffi
234
- ++ lib . optional ( ! enableIntegerSimple && ! targetPlatform . isGhcjs ) gmp
266
+ ++ lib . optional ( ! enableIntegerSimple && ! targetPlatform . isGhcjs && ! targetPlatform . isWasm ) gmp
235
267
++ lib . optional ( platform . libc != "glibc" && ! targetPlatform . isWindows ) libiconv
236
268
++ lib . optional ( enableNUMA && platform . isLinux && ! platform . isAarch32 && ! platform . isAndroid ) numactl
237
269
++ lib . optional enableDWARF ( lib . getLib elfutils ) ;
@@ -306,12 +338,12 @@ let
306
338
# For build flavours and flavour transformers
307
339
# see https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/doc/flavours.md
308
340
hadrianArgs = "--flavour=${
309
- ( if targetPlatform . isGhcjs then "quick" else "default" )
341
+ ( if targetPlatform . isGhcjs || targetPlatform . isWasm then "quick" else "default" )
310
342
+ lib . optionalString ( ! enableShared ) "+no_dynamic_ghc"
311
343
+ lib . optionalString useLLVM "+llvm"
312
344
+ 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"
315
347
} --docs=no-sphinx -j --verbose"
316
348
# This is needed to prevent $GCC from emitting out of line atomics.
317
349
# Those would then result in __aarch64_ldadd1_sync and others being referenced, which
@@ -425,9 +457,22 @@ haskell-nix.haskellLib.makeCompilerDeps (stdenv.mkDerivation (rec {
425
457
export EM_CACHE=$(mktemp -d)
426
458
mv config.sub.ghcjs config.sub
427
459
'' )
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
+ ''
428
473
# GHC is a bit confused on its cross terminology, as these would normally be
429
474
# the *host* tools.
430
- + lib . optionalString ( ! targetPlatform . isGhcjs ) ( ''
475
+ + lib . optionalString ( ! targetPlatform . isGhcjs && ! targetPlatform . isWasm ) ( ''
431
476
export CC="${ targetCC } /bin/${ targetCC . targetPrefix } cc"
432
477
export CXX="${ targetCC } /bin/${ targetCC . targetPrefix } c++"
433
478
''
0 commit comments