Skip to content

Universal Docker build environment for Emscripten/WASM/Deno/Meson C/C++ projects.

License

Notifications You must be signed in to change notification settings

discere-os/wasm-builder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

41 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

WASM Builder

Universal Docker build environment for Emscripten/WASM/Deno/Meson C/C++ projects.

Image Variants

Standard (With Ports) - ghcr.io/discere-os/wasm-builder:latest

Includes the Emscripten ports system for convenience and upstream compatibility.

  • Use for: Quick prototyping, upstream tutorials, auto-dependency downloads
  • Ports available: SDL2, zlib, libpng, freetype, and 20+ more
  • Auto-download: Use -sUSE_ZLIB, --use-port=sdl2, etc.

Minimal (No Ports) - ghcr.io/discere-os/wasm-builder:minimal

Removes the Emscripten ports system to enforce explicit dependencies.

  • Use for: Production builds with @discere-os/*.wasm packages
  • Benefits: No auto-downloads, explicit dependency control, smaller image
  • Architecture: Aligns with SIDE_MODULE/MAIN_MODULE design

Features

  • Emscripten 4.0.16: Built from source (LLVM, Binaryen, Emscripten)
  • WABT 1.0.38: WebAssembly Binary Toolkit (wat2wasm, wasm2wat, etc.)
  • Complete control: Exact git revisions from upstream DEPS file
  • Pre-built cache: Standard libraries compiled with embuilder
  • Deno v2.5.4: Modern JavaScript/TypeScript runtime
  • Node.js 22: Latest LTS with pnpm package manager
  • Wrangler: Cloudflare Workers CLI for edge deployment
  • Meson + Ninja: Fast, modern build system
  • CMake: Cross-platform build system
  • Build tools only: No system libraries (use *.wasm forks for dependencies)

Quick Start

# Pull the standard image (with ports)
docker pull ghcr.io/discere-os/wasm-builder:latest

# Or pull the minimal image (no ports)
docker pull ghcr.io/discere-os/wasm-builder:minimal

# Build a WASM project with Deno
docker run --rm -v $(pwd):/workspace ghcr.io/discere-os/wasm-builder:latest \
  deno task build:wasm

# Build with Meson
docker run --rm -v $(pwd):/workspace ghcr.io/discere-os/wasm-builder:latest \
  bash -c "meson setup build && ninja -C build"

# Direct Emscripten compilation
docker run --rm -v $(pwd):/workspace ghcr.io/discere-os/wasm-builder:latest \
  emcc main.c -o main.js -O3

Building the Image Locally

Quick Test

./scripts/test-quick.sh
# ~60-90 minutes, ~2-3GB image

Full Build + Test with zlib.wasm

./scripts/test-local-build.sh

Note: Building LLVM from source takes significant time (~30-60 minutes) and resources. The multi-stage build optimizes the final image size by discarding build artifacts.

See scripts/README.md for DNS and other troubleshooting.

Use in GitHub Actions

jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/discere-os/wasm-builder:latest

    steps:
      - uses: actions/checkout@v4
      - name: Build WASM
        run: deno task build:wasm

Installed Tools

Tool Version Source
Emscripten 4.0.16 Built from git 00c5c7d
LLVM/Clang (DEPS) Built from git 07ca4db
Binaryen (DEPS) Built from git c326e66
WABT 1.0.38 Built from git tag
Deno 2.5.4 deno.land install script
Node.js 22 NodeSource repository
pnpm latest npm global install
Wrangler latest npm global install
Meson β‰₯1.3.0 pip3 install
Ninja latest Ubuntu apt
CMake 3.x Ubuntu apt

Version Sources

Emscripten, LLVM, Binaryen: Exact git commits from the emscripten-releases DEPS file for version 4.0.16. These commits are guaranteed compatible by the Emscripten team.

WABT: Not required by Emscripten but included for development convenience. Provides tools like wat2wasm, wasm2wat, wasm-objdump, and wasm-validate.

Validation: All tools are verified during build with emcc --check to ensure correct configuration and compatibility.

Understanding the Ports System

Emscripten includes a ports system that auto-downloads and builds 25+ third-party libraries:

# Standard variant - ports enabled
emcc main.c -sUSE_ZLIB           # Auto-downloads zlib 1.3.1 from GitHub
emcc main.c --use-port=sdl2      # Auto-downloads SDL2 from emscripten-ports

Problems with ports for our use case:

  • Downloads from external URLs (not reproducible)
  • Fixed versions (can't customize or patch)
  • Auto-triggered implicitly (hard to track)
  • No SIDE_MODULE support (only static linking)
  • Conflicts with our @discere-os/*.wasm architecture

Solution: Two variants

Scenario Image Why
Production builds :minimal Explicit control, reproducible, our forks
Quick prototyping :latest Convenience, upstream compatibility
Following upstream tutorials :latest Tutorials assume ports are available
SIDE_MODULE architecture :minimal Ports don't support SIDE_MODULE

Architecture Note

NO system libraries included (by design). Dependencies are handled via client/emscripten/*.wasm forks:

SIDE_MODULE Builds (Production/CDN)

# No dependencies at build time
- run: deno task build:wasm
# Dependencies loaded at runtime via dlopen()

MAIN_MODULE Builds (Testing/NPM)

# Clone and build dependencies from *.wasm forks
- name: Checkout zlib.wasm dependency
  uses: actions/checkout@v4
  with:
    repository: discere-os/zlib.wasm
    path: zlib.wasm

- name: Build zlib dependency
  run: cd zlib.wasm && ./build-dual.sh side
  # Creates zlib.wasm/install/lib/libz.a for static linking

- name: Build with dependency
  run: deno task build:wasm
  # Meson finds libz.a via PKG_CONFIG_PATH

This prevents system library pollution and ensures:

  • Consistent WASM-native dependencies across all builds
  • Version control via our own forks, not system packages
  • Proper SIDE_MODULE architecture (runtime dlopen())
  • Static linking for MAIN_MODULE from our own builds

Environment Variables

  • EMSCRIPTEN_VERSION=4.0.14
  • EMSDK=/emsdk
  • EM_CONFIG=/emsdk/.emscripten
  • EM_CACHE=/emsdk/.emscripten_cache

Optimization

The image is optimized for:

  • Fast builds: Emscripten cache is pre-warmed
  • Small size: Minimal layers, cleaned apt cache
  • Reproducibility: Pinned versions for all major tools
  • Security: Latest Ubuntu 24.04 LTS base

πŸ’– Support This Work

This Docker build environment is part of a larger effort to bring professional desktop applications to browsers with native performance.

πŸ‘¨β€πŸ’» About the Maintainer: Isaac Johnston (@superstructor) - Building foundational browser-native computing infrastructure through systematic C/C++ to WebAssembly porting.

πŸ“Š Impact: 70+ open source WASM libraries enabling professional applications like Blender, GIMP, and scientific computing tools to run natively in browsers.

πŸš€ Your Support Enables:

  • Continued maintenance and updates
  • Performance optimizations
  • New library ports and integrations
  • Documentation and tutorials
  • Cross-browser compatibility testing

πŸ’– Sponsor this work to help build the future of browser-native computing.

License

MIT

Maintainer

Superstruct Ltd

About

Universal Docker build environment for Emscripten/WASM/Deno/Meson C/C++ projects.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages