@@ -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"
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 ''
0 commit comments