# wasm-cross ### `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`](https://github.com/WebGHC/webabi) library. It currently provides a minimal ABI, sufficient to run the Haskell code using the `jsaddle` library with [`jsaddle-wasm`](https://github.com/WebGHC/jsaddle-wasm) ## Quick start #### Setup nix cache - 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=` ### Build an example app ``` git clone git@github.com: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 ``` ### Nix based build with TemplateHaskell support #### Template Haskell For Template Haskell support the [save/load-splices infrastructure](https://github.com/WebGHC/ghc/commits/webghc-8.6.5-splices) 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](https://github.com/WebGHC/example-jsaddle-project) and the [example Reflex app](https://github.com/WebGHC/example-reflex-project) ### Cabal based build without TemplateHaskell support 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 in `if !arch(wasm32)` block. > Note: `reflex-dom` library from v0.7 onwards already includes `jsaddle-wasm` dependency, so it is not necessary to modify anything. > TODO: add instructions for `miso` and `reflex-dom` < 0.7 - Use the `work-on` script from reflex-platform to obtain a shell with `WebGHC` ``` sh /scripts/work-on wasm ./. ``` Then do the `cabal configure` with following options, followed by `cabal build` ``` sh 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 ``` #### Limitations / Known issues - The `-threaded` option is not supported with `WebGHC`. 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 the `clang` warnings to errors. This is a temporary issue, as it should be possible to get rid of `clang` warnings altogether. ### Other details The C toolchain is made up of Clang / LLVM, LLD, and [a fork of musl](https://github.com/WebGHC/musl). The Haskell compilation is done using WebGHC, which is a fork of GHC GHC cross compilers are built from [a fork](https://github.com/WebGHC/ghc) using the Nix infrastructure largely developed by John Ericson (@Ericson2314), producing a working `haskellPackages`. [`webabi`](https://github.com/WebGHC/webabi) is the "kernel" to support `musl`'s syscalls. ### Notes - We have [forked `nixpkgs`](https://github.com/WebGHC/nixpkgs) just to support the `wasm32-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` or `wasm32-unknown-unknown-webghc` being other candidates. - The `wasm-cross` contains some code for `nodejs` 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.