Home - WebGHC/wasm-cross GitHub Wiki
Status
GHC cross compiler can compile most of the packages including ones with C code (like bytestring
). For example jsaddle
works fine, and it has a lot of dependecies including lens
, aeson
, attoparsec
, etc.
The runtime kernel can run in single threaded mode,
concurrency stuff like forkIO
, MVars, threadDelay
, etc work fine, though there is no parallelism.
There is support to do very minimal IO (it can print on the browser console, and communicate with jsaddle js code). The IO support is currently in experimental stage, and has been hand crafted to do a proof of concept implementation.
The size of wasm executable (containing RTS, libc and all the libraries statically linked) is above 15mb for simple hello world, and 27mb for jsaddle.
Since we know the jsaddle
works and can do arbitrary JS code execution, in theory we should be able to run any ghcjs-dom
based applications like reflex-dom
.
Next tasks
Reduce the code size
This is currently the most critical issue we will have to fix. This has been captured in the below issues.
https://github.com/WebGHC/ghc/issues/13
https://github.com/WebGHC/jsaddle-wasm/issues/1
Currently I (@dfordivam) am trying a number of experiments here to better understand the problem and possible solutions. If you know llvm
, or ghc
code generation, then please get in touch.
Implement kernel execution environment for runtime
There is a need to create a proper "kernel" support for running the runtime in JavaScript, and interact with DOM.
-
Implement basic APIs for memory management, other system calls. In current implementation some of these APIs dont do what they are intended to do, so that need to be fixed.
-
Need to provide a unix like File system support, using the
browsefs
package. -
The wasm executable and kernel code runs in a separate
WebWorker
thread (currently they run together in one thread, though that might change in next version). Whereas thejsaddle
JavaScript code has to run in the main thread, as it need to manipulate theDOM
.So there is a need to do this communication between the different threads. We are thinking to implement this as a special character device in
browserfs
(like/dev/jsaddle
) with support of doing system calls to do read, write and get status.
Currently @ElvishJerricco is implementing this in TypeScript (https://github.com/WebGHC/webabi/tree/typescript-kernel-reorg).
This work is independent of the code size issue and there is a lot to be done. So contributions are very much appreciated here.
Create jsaddle-wasm
Jsaddle interface for WebGHC. https://github.com/WebGHC/jsaddle-wasm
This is relatively easy to implement once the above kernel execution environment is created.
This will allow the ghcjs-dom
to work using the jsaddle-dom
package.
Executation on NodeJS
This will be required to run the test-suites, and perhaps other applications.
We have managed to run the current version of webabi
on nodejs
, though there is some more work required to run the ghc
test-suite.
Try it out
# Make sure you add the binary key to fetch pre-compiled ghc and toolchain
# hydra.webghc.org-1:knW30Yb8EXYxmUZKEl0Vc6t2BDjAUQ5kfC1BKJ9qEG8=
$ git clone https://github.com/WebGHC/wasm-cross.git
$ cd wasm-cross
$ nix-build release.nix -o haskell-example-web -A wasm.haskell-example-web
$ cd haskell-example-web
$ hserv -p8080
Go to 127.0.0.1:8080 in firefox or chrome, and open console to view the print outputs. You will have to enable SharedArrayBuffer from the browser config settings. Or you can edit the wasm.js file and comment out the two lines containing SharedArrayBuffer.
Hack
Get in touch with us (@dfordivam, @ElvishJerricco) on IRC freenode #reflex-frp or #ghc
GHC
GHC currently uses unregistered compilation, by generating C code and compiling using clang. The llvm native code generation cannot be used currently because wasm doesn't have tail-call support.
The runtime system (RTS) has been compiled to wasm with some minor modifications.
To build GHC cross compiler, first do this config
$ git config --global url."[email protected]:WebGHC/packages-".insteadOf [email protected]:WebGHC/packages/
$ git config --global url."ssh://github.com/WebGHC/packages-".insteadOf ssh://github.com/WebGHC/packages/
$ git config --global url."https://github.com/WebGHC/packages-".insteadOf https://github.com/WebGHC/packages/
$ git config --global url."http://github.com/WebGHC/packages-".insteadOf http://github.com/WebGHC/packages/
$ git config --global url."git://github.com/WebGHC/packages-".insteadOf git://github.com/WebGHC/packages/
Then fetch the sources and build
$ git clone --recursive https://github.com/WebGHC/ghc.git
# Obtain a nix-shell
$ cd /path/to/wasm-cross
$ nix-shell -A nixpkgsWasm.haskell.packages.ghcHEAD.ghc
# Do build
$ cd /path/to/ghc
# Edit mk/build.mk if required
$ configurePhase
$ make -j4
# Run your local ghc cross compiler
$ /path/to/ghc/inplace/bin/ghc-stage1 main.hs
# use the generated *main* file
Webabi / kernel execution / System calls
The supporting kernel code (wasm.js) is work in progress, and can do minimal operations like write to STDOUT.
# Get source
$ git clone https://github.com/WebGHC/webabi
$ cd webabi
# obtain a shell with ghc
$ cd wasm-cross
$ nix-shell -A nixpkgsWasm.haskell.packages.ghcHEAD.hello
# Copy some dependecies
$ cp /path/to/haskell-example-web/node_modules .
$ cp /path/to/haskell-example-web/index.html .
After this you can compile haskell code using the ghc in this shell, and modify the files wasm.js, kernel.js, etc.
# Compile haskell
$ wasm32-unknown-unknown-wasm-ghc main.hs -o hello
$ hserv