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:
- Clone and activate the Emscripten SDK (version 4.0.7 by default)
- Auto-detect the host Qt path from
Qt6_DIR - Run
qt-cmakewith-DWASM=ON - Build MNE-CPP for WebAssembly
Build output is placed in out/wasm/.
Script Options
| Option | Description |
|---|---|
--emsdk <version>, -e | Set the Emscripten version (default: 4.0.7) |
--qt <path>, -q | Set the Qt installation path manually |
--qt-host <path> | Set the host Qt path for cross-compilation |
--no-log | Skip writing build_info.txt |
--help, -h | Show 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
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_OPENGLis implied by-DWASM=ON). - The Wasm build always uses static linking (
BUILD_SHARED_LIBS=OFF).