Skip to main content

WebAssembly Build Guide

This guide shows you how to build MNE-CPP for WebAssembly (Wasm). MNE-CPP uses multi-threaded Wasm by default and provides a build script that handles Emscripten setup, CMake configuration, and compilation.

Prerequisites

Qt 6 for WebAssembly

You need a Qt 6 installation that includes the WebAssembly (multi-threaded) target. Install it via the Qt Online Installer — select both a desktop target (e.g. Desktop gcc 64-bit on Linux or macOS on Mac) and the WebAssembly (multi-threaded) target. CI currently uses Qt 6.10.2.

A desktop (host) Qt is required alongside the Wasm Qt because Qt's cross-compilation needs a host toolchain to build code generators and other tools.

Emscripten SDK

The build script can automatically download and set up the Emscripten SDK for you. If you prefer to install it manually, see emscripten.org. CI currently uses emsdk 4.0.7.

System Dependencies

On Linux, install the following packages:

sudo apt-get install build-essential libgl1-mesa-dev ninja-build

On macOS, install Ninja:

brew install ninja

CMake

CMake 3.15 or higher is required.

Build with the Provided Script

MNE-CPP provides a Wasm build script at tools/wasm.sh. From the repository root:

# Set Qt6_DIR to the folder containing wasm_multithread/ and your host Qt (gcc_64/ or macos/)
export Qt6_DIR=$HOME/Qt/6.10.2

./tools/wasm.sh

The script will:

  1. Clone and activate the Emscripten SDK (version 4.0.7 by default)
  2. Auto-detect the host Qt path from Qt6_DIR
  3. Run qt-cmake with -DWASM=ON
  4. Build MNE-CPP for WebAssembly

Build output is placed in out/wasm/.

Script Options

OptionDescription
--emsdk <version>, -eSet the Emscripten version (default: 4.0.7)
--qt <path>, -qSet the Qt installation path manually
--qt-host <path>Set the host Qt path for cross-compilation
--no-logSkip writing build_info.txt
--help, -hShow help

Example with explicit paths:

./tools/wasm.sh --emsdk 4.0.7 --qt $HOME/Qt/6.10.2 --qt-host $HOME/Qt/6.10.2/gcc_64

Build Manually

If you prefer to run the steps yourself:

# 1. Set up Emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install 4.0.7
./emsdk activate 4.0.7
source ./emsdk_env.sh
cd ..

# 2. Configure and build
$HOME/Qt/6.10.2/wasm_multithread/bin/qt-cmake \
-DQT_HOST_PATH=$HOME/Qt/6.10.2/gcc_64 \
-DCMAKE_BUILD_TYPE=Release \
-DWASM=ON \
-S src \
-B build/wasm

cmake --build build/wasm --parallel $(nproc)

Adjust QT_HOST_PATH to gcc_64 (Linux) or macos (macOS) as appropriate.

Run an Application

Navigate to the build output directory and start a local web server:

cd out/wasm/apps
python3 -m http.server

Open a Chromium-based browser or Firefox and visit:

http://localhost:8000/mne_analyze.html
Cross-Origin Headers

Multi-threaded Wasm requires the server to send the Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp headers. Without these headers, SharedArrayBuffer is unavailable and the application will hang silently in Chrome and Safari (Edge is more permissive).

Automatic fix (recommended): Run the post-build script to inject a COI service worker that adds these headers client-side — this works on any static host including GitHub Pages:

./tools/wasm/wasm_postbuild.sh out/wasm/apps

The wasm.sh build script runs this automatically. If you build manually with CMake, run the command above after cmake --build.

Alternative for local testing: Use a server that sends COOP/COEP headers, e.g.:

npx coi-serviceworker-server out/wasm/apps

See the Qt for WebAssembly documentation for details.

Live Demo

Live Wasm builds are available at:

https://mne-cpp.github.io/wasm/mne_analyze.html

Notes

  • Chromium-based browsers and Firefox provide the best compatibility.
  • Qt3D / QOpenGLWidget is not supported in WebAssembly builds (-DNO_OPENGL is implied by -DWASM=ON).
  • The Wasm build always uses static linking (BUILD_SHARED_LIBS=OFF).

References