Contents

Use environment variables in WebAssembly with Emscripten

It is typical for native C code to poke and probe a shell environment with POSIX getenv and setenv. JavaScript can preload environment variables expected by a WebAssembly module using the Emscripten toolchain.

Native code

This example queries the environment for a way to greet. Don’t try to think about reasons for doing it this way; the point is to demonstrate how JS can preload the environment for WebAssembly ;)

// main.cpp
#include <cstdlib>
#include <iostream>

int main(int, char*[])
{
  std::cout << std::getenv("GREETING") << '!' << std::endl;
  return 0;
}

Compile with emscripten

The glue code will use an export name called createModule, making the wasm initialization look cleaner. We’ll use it later in HTML.

em++ -sWASM=1 -sMODULARIZE=1 -sEXPORT_NAME=createModule "-sEXPORTED_RUNTIME_METHODS=['ENV']" main.cpp -o main.js

This command outputs a main.wasm binary and main.js source file. The main.js is the glue code that defines functions to fetch, compile and run WebAssembly instructions from main.wasm.

Setup environment variable in JS

configuration maps functions referenced by the emscripten glue layer. The first is an stdout handler which pipes text into the developer console.

<!-- index.html -->
<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <script type="text/javascript" src="main.js"></script>
    <script type='text/javascript'>
        // define wasm module configuration.
        let configuration = {
            'print': (text) => { console.info(text); },
            'preRun': [(runtime) => { runtime.ENV.GREETING = 'HI'; }],
        };
        // initialize the wasm module with above configuration.
        createModule(configuration).then((runtime) => {
            console.log("wasm module initialized");
        })
    </script>
</body>
</html>

The second entry preloads the environment variable GREETING="HI". Here, runtime refers to the wasm runtime. preRun is a list of functions called one by one by the glue code right before initializing and starting up the wasm runtime. The ENV object contains key-value pairs corresponding to a shell environment.

Emscripten docs has additional information on preRun.

That was it! This exact method was used to switch between different rendering backends for the VTK WebAssembly example - ConeMultiBackend.