Deploying software on the web via a browser is a convenient way of connecting with users in a low friction fashion. However these web platforms can cause vexations to more classical compiled language developers due to some of the technology choices made during the early days of the web. I want the ease of deploying to a browser but I despise javascript. I also wish to make a site that “renders” on the client side, that is to generate the DOM within the client from text files communicated from the server, this allows me to have a static webpage hosted for free by GitHub – with any persistent data stored in cookies.

When I learnt about Web Assembly (WASM) I was excited that I’d be able to make a web app without touching javascript. WASM is a bytecode target that can be interpreted either on the browser or a standalone interpreter – like Wasmtime. The interpreter is known as the host and the WASM module is the guest. LLVM can compile to this target enabling c/c++/rust code to be compiled for the browser. One goal for WASM is to be able to deploy the same binary to Web, Linux and Windows. Somehow this reminds me of some of the goals for Java and why they also chose a bytecode target.

As the WASM target is not a traditional POSIX system I cannot link to libc as one would traditionally. I am quite accustomed to using libc and libraries that depend on it, like libc++, so I needed to find a way to statically link to a WASM libc. There are currently two implementations for libc to be used with WASM: the first is Emscripten, which tries to implement many POSIX standards facilitated by a javascript runtime, the other one is WASI which tries to provide for both browser and standalone deployment. I decided to go with WASI due to the smaller javascript runtime and it seems that the WASM team is heading in that direction.

To compile a WASM/WASI binary it is recommended to use WASI-SDK, this bundles all the libraries needed to use WASI into a convenient package. It also provides a CMAKE toolchain file enabling the easy use of CMAKE.

Now WASI provides a different binary to a traditional WASM build, WASI builds components whilst before we were building modules. One of the key benefits of components is a richer interaction between WASM and the host, modules can only interface via passing integers whilst components can use different types. To do this there is a tool call wit-bindgen that generates binding shims to transfer types between languages based on WIT files.

One of the main reasons I chose to use a component build is to enable the use of the reactor model. WASM can be run in one of two modes, command or reactor: command mode runs a main function like a normal posix program and reactor mode expects to be called multiple times from the host. A command works by having an entry point called _start calling __wasm_call_ctors to initialise and __wasm_call_dtors to clean up whilst with a reactor you have to manually call _initialize which in turn calls __wasm_call_ctors for initialisation. Modules can only be run in command mode and I need reactor mode thus the use of a component.

As you can see there are many different ways of writing WASM and the space is moving quickly, this has caused the vexing problem of each blog, tutorial and manual giving different ways of targeting WASM. This is further exasperated by C++ being second class to Rust in the WASM world. I’ve learnt a lot but I have not been able to complete the foundation for a website written in C++ targeting WASM, I’m planning to restart my effort in Rust and giving WASM another go.

edit: Looking into the Rust WASM toolchain it uses the jco transpiler to convert WASM components into modules with some extra runtime javascript code. This has killed my enthusiasm for this project, I may come back to WASM at a later date.