wasm-cross
is a toolchain for cross compiling C and Haskell to WebAssembly, using the WebGHC
and LLVM
The generated WebAssembly binary can be run on a browser using the webabi
library.
It currently provides a minimal ABI, sufficient to run the Haskell code using the jsaddle
library with jsaddle-wasm
-
If you're using linux, a nix binary cache is available at https://nixcache.webghc.org with a public key of:
hydra.webghc.org-1:knW30Yb8EXYxmUZKEl0Vc6t2BDjAUQ5kfC1BKJ9qEG8=
-
When using reflex-platform you may want to add its cache as well: https://nixcache.reflex-frp.org
ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=
git clone [email protected]:WebGHC/wasm-cross.git
cd wasm-cross;
Reflex TodoMVC
nix-build release.nix -A examples.wasm.reflex-todomvc
Miso 2048
nix-build release.nix -A examples.wasm._2048
For Template Haskell support the save/load-splices infrastructure is used. This was initially created to support the arm
cross-compilation, but it works equally well for WebGHC
.
This works by first compiling the code for x86/64
arch, and then using the splices generated by it in the wasm
compilation.
It needs the reflex-platform
's nix wizardry to achieve this.
It works well for the straightforward use cases of Template Haskell, but may break for more complicated uses.
Note: use of reflex
is not required to use reflex-platform
, it should work well for Miso
too.
In order to support TemplateHaskell
the reflex-platform
and nix based build is necessary.
See the example JSaddle app and the example Reflex app
If you dont need TemplateHaskell support, then you can use only cabal
to do the builds, which works much faster as it can do builds incrementally.
The reflex-platform
is used here as it provides an easier to use interface for creating a nix-shell with all the dependencies necessary for a cabal project.
Get the latest reflex-platform
from https://github.com/reflex-frp/reflex-platform/
- For a JSaddle app, add the
jsaddle-wasm
in your executable's cabal file, and put the-threaded
option inif !arch(wasm32)
block.
Note:
reflex-dom
library from v0.7 onwards already includesjsaddle-wasm
dependency, so it is not necessary to modify anything.
TODO: add instructions for
miso
andreflex-dom
< 0.7
- Use the
work-on
script from reflex-platform to obtain a shell withWebGHC
<reflex-platform>/scripts/work-on wasm ./.
Then do the cabal configure
with following options, followed by cabal build
cabal configure --configure-option=--host=wasm32-unknown-unknown-wasm --with-ghc=wasm32-unknown-unknown-wasm-ghc --with-ghc-pkg=wasm32-unknown-unknown-wasm-ghc-pkg --with-gcc=wasm32-unknown-unknown-wasm-cc --with-ld=wasm32-unknown-unknown-wasm-ld --with-ar=wasm32-unknown-unknown-wasm-ar --with-hsc2hs=wasm32-unknown-unknown-wasm-hsc2hs
cabal build
- The
-threaded
option is not supported withWebGHC
. You will have to put to modify the cabal file to exclude this option like this:
if !arch(wasm32)
ghc-options: -threaded
- The
-Werror
option is known to cause compilation failure as it converts theclang
warnings to errors. This is a temporary issue, as it should be possible to get rid ofclang
warnings altogether.
The C toolchain is made up of Clang / LLVM, LLD, and a fork of musl.
The Haskell compilation is done using WebGHC, which is a fork of GHC
GHC cross compilers are built from a fork using the Nix infrastructure largely developed by John Ericson (@Ericson2314), producing a working haskellPackages
.
webabi
is the "kernel" to support musl
's syscalls.
-
We have forked
nixpkgs
just to support thewasm32-unknown-unknown-wasm
compilation target, as this support cannot be provided by overlays. All other changes needed to nixpkgs, which cannot be done by overlays, have already been upstreamed.The choice of target triple is still under debate, with
wasm32-unknown-unknown
orwasm32-unknown-unknown-webghc
being other candidates. -
The
wasm-cross
contains some code fornodejs
support, but unfortunately it has not been maintained. If there is interest in running the executables outside the browser environment, then this could be resurrected with a little effort.