Skip to content

WebAssembly Standalone

Alon Zakai edited this page Jan 30, 2018 · 40 revisions

When compiling to WebAssembly, emcc emits both a JavaScipt file and a WebAssembly file. The JavaScript loads the WebAssembly which contains the compiled code. This is necessary in many cases as WebAssembly currently depends on a JavaScript runtime for features like longjmp, C++ exceptions, checking the date or time, printing to the console, using an API like WebGL, etc. However, if your WebAssembly only contains pure computational code, it may require almost no JavaScript support. If it in fact doesn't need any of the Emscripten runtime, then it is "standalone", and all you need to use it is some JavaScript to load it.

There are two main ways to generate such standalone WebAssembly from Emscripten: letting the optimizer remove the runtime, or creating a dynamic library. We'll go over each on this page.

Note: You will still need JavaScript to load the WebAssembly, at least on the Web and with current APIs.

Let the optimizer remove the runtime

As of 1.37.29, emcc's optimizer is powerful enough to remove all runtime elements that are not used (it does this using meta-dce, dead code elimination that crosses the JavaScript/WebAssembly boundary). To try this, simply build with something like

emcc source.cpp -Os -s WASM=1

-Os is needed to make the optimizer work at full power (you can also use -Oz or -O3). The result will be two files, JavaScript and WebAssembly as usual. You can then inspect the WebAssembly file and see what it imports: if you are only doing pure computation, it should import little or nothing, in which case it is easy to write your own loading code to use it.

  • If you use C++ objects, the compiler must in many cases emit code to catch exceptions so that RAII destructors are called, and exceptions require a lot of runtime support. Build with -fno-exceptions to disable exceptions entirely.
  • More details on how this works.

Create a dynamic library

Dynamic libraries have a formal definition, and are designed to be loadable in a standard way. That is a benefit over the previous approach, however, dynamic libraries also have downsides, such as having relocations for memory and function pointers, which add overhead that may be unnecessary if you are only using one module (and not linking several together).

To build a dynamic library, use

emcc source.cpp -s WASM=1 -s SIDE_MODULE=1 -o target.wasm

That will emit the output dynamic library as target.wasm.

To use a side module, see loadWebAssemblyModule in src/runtime.js for some example loading code.

  • The conventions for a wasm dynamic library are here.
  • Note that there is no special handling of a C stack. A module can have one internally if it wants one (it needs to ask for the memory for it, then handle it however it wants).
  • Full example.
  • The LLVM wasm backend does not support dynamic libraries yet, so you can only use this with asm2wasm (fastcomp).