Exploring WebAssembly (WASM)

Compiling to WebAssembly

Emscripten Compiler

In this lesson, you'll learn how to use Emscripten—the powerful compiler toolchain that converts C and C++ into high-performance WebAssembly (WASM) and JavaScript. Emscripten enables both browsers and server environments (like Node.js) to run native code with near-native speed, making it ideal for games, graphics libraries, and utility ports.

Why Emscripten Matters

  • Brings established C/C++ applications to the Web platform
  • Enables game engines, graphics libraries, and frameworks to run in browsers
  • Supports modern optimizations and a simulated file system

Mozilla and Epic Games showcased Unreal Engine 3 and 4 running in Firefox, illustrating WebAssembly’s potential for gaming.

The image features logos of Mozilla Firefox and Epic Games, with a central graphic representing Unreal Engine 3. The word "Background" is at the top left.

Unity joined the movement, announcing “WebAssembly is here” to accelerate game performance on the web.

The image shows a Unity blog post titled "WebAssembly is here" by Marco Trivellato, featuring a black banner with the WebAssembly logo.


Emscripten in Action

Emscripten powers ports of:

CategoryExamples
Game EnginesUnity, Nebula 3, GeoGram
Graphics LibrariesOpenGL ES 2.0, ImGui
Frameworks & AppsPyQt, .NET Blazor
Utilities & EmulatorsClassic emulators, image tools, and more

The image is an infographic about Emscripten, showing its applications in game engines, graphics programs, and application frameworks, with examples like Unity, OpenGL ES 2.0, and Python's QT.


A Closer Look at Emscripten

Emscripten integrates the LLVM toolchain—Clang and LLVM—plus Google’s Closure Compiler to output optimized WebAssembly modules and JavaScript glue code.

The image is a diagram titled "A Bit About Emscripten," showing Emscripten with components Clang, LLVM, and Closure.

Invoke the frontend emcc just like gcc or clang:

# Compile C/C++ files
emcc [options] file...
# Display help and version
emcc --help
emcc --version

By default, emcc generates:

  • *.wasm — WebAssembly binary
  • *.js — JavaScript loader

Installation Options

Choose the approach that suits your workflow:

MethodDescriptionQuick Start
DockerRun Emscripten without local installdocker run --rm -v $(pwd):/src emscripten/emsdk emcc ...
EMSDK (Local)Full SDK with version management (Linux/Win/macOS)See Emscripten SDK Downloads
# Docker example:
docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk
# Inside container:
emcc helloworld.cpp -o helloworld.js

Note

For local development, install the Emscripten SDK (EMSDK). It bundles emcc, LLVM, Node.js support, and utility scripts.


Verifying Your Installation

Ensure emcc is on your PATH and run:

emcc -v

Expected output:

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.45-git
clang version 18.0.0 (...)
Target: wasm32-unknown-emscripten
...

If you encounter missing-tool warnings, refer to the official docs for troubleshooting.


Your First WebAssembly Program

  1. Create hello_world.c:
#include <stdio.h>
int main() {
    printf("Hello, World!\n");
    return 0;
}
  1. Compile with Emscripten:
emcc hello_world.c

This yields:

  • a.out.wasm — WebAssembly module
  • a.out.js — JS loader
  1. Run in Node.js:
node a.out.js
# → Hello, World!

JavaScript Fallback

Force pure JavaScript output for environments without WASM:

The image illustrates the use of Emscripten for compilation, showing a comparison between a WebAssembly file (Hello.wasm) marked with a red cross and a JavaScript file (Hello.js) marked with a green check.

emcc hello_world.c -s WASM=0

Creating an HTML Wrapper

Generate an HTML file that auto-loads your module:

emcc hello_world.c -o hello.html

Open hello.html in a browser (or via a local server) to see “Hello, World!” rendered on the page.


Enforcing Strict Mode

Use -s STRICT=1 to catch deprecated or unsafe code patterns.

Warning

Strict mode treats deprecated patterns as errors. Ensure your code adheres to modern C/C++ standards.

// hello.cpp
#include <iostream>
#include <stdlib.h>
int main() {
    char *buffer = (char*)malloc(10); // Deprecated in C++
    if (!buffer) return 1;
    std::cout << "Memory allocated." << std::endl;
    free(buffer);
    return 0;
}
emcc hello.cpp -o hello.html -s STRICT=1

You may see warnings like:

Warning: ‘malloc’ is not recommended in modern C++. Use ‘new’ instead
Warning: inclusion of the C header file <stdlib.h> is deprecated in STRICT mode

Exporting Custom Functions

By default, only main is exported. Use -s EXPORTED_FUNCTIONS to expose additional functions:

The image is a slide titled "Exported Functions" focusing on "Optimization," with points about making a WASM Bin smaller and more optimized, accompanied by related icons.

#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int multiplyNumbers(int a, int b) {
    return a * b;
}
emcc multiplyNumbers.c -o multiplyNumbers.js \
    -s EXPORTED_FUNCTIONS="['_multiplyNumbers']"

Now call it in JS:

Module._multiplyNumbers(3, 4); // 12

Simulated File System

Emscripten provides a virtual file system so your C/C++ code can use standard I/O in the browser:

The image illustrates the concept of using files with Emscripten, featuring icons for a simulated file system and functions like `fopen()` and `fclose()`.

test/hello_world_file.cpp:

#include <stdio.h>
int main() {
    FILE *file = fopen("hello_world_file.txt", "rb");
    if (!file) {
        printf("cannot open file\n");
        return 1;
    }
    int c;
    while ((c = fgetc(file)) != EOF) putchar(c);
    fclose(file);
    return 0;
}

Preload data at compile time:

emcc test/hello_world_file.cpp -o hello.html \
    --preload-file test/hello_world_file.txt

Serve hello.html via HTTP to view the file contents in the browser.


Build Optimizations

Fine-tune performance with standard optimization levels:

emcc -O1 hello_world.cpp  # safe transformations
emcc -O2 hello_world.cpp  # balanced speed and size
emcc -O3 hello_world.cpp  # aggressive inlining & loop unrolling
  • O1: removes assertions, minimal size reduction
  • O2: faster runtime with code replacements
  • O3: extensive optimizations for release builds

Further Reading & References

The image shows a webpage about the Emscripten Compiler Frontend (emcc), detailing command line syntax and arguments. It includes a sidebar with navigation links related to Emscripten documentation.

Watch Video

Watch video content

Previous
WASM Compilers