Skip to content

Building from source

Consumers do not need to build — the npm package ships a prebuilt .wasm. Build from source only to change build flags, bump Gmsh/OCCT, or develop the package.

Prerequisites

  • Linux/macOS, git, cmake ≥ 3.16, python3, node ≥ 18
  • Disk: several GB (OCCT + Gmsh build trees)
  • The Gmsh git submodule checked out:
    git submodule update --init --recursive
    

The pinned Emscripten SDK, OpenCASCADE, and LLVM OpenMP runtime versions are set in scripts/env.sh.

One-shot build

npm run setup        # install + activate the pinned emsdk into .emsdk/
npm run build:libomp # build LLVM's OpenMP runtime (libomp) -> wasm32 static lib
npm run build:occt   # build OpenCASCADE -> static WASM libs (slow, ~once)
npm run build:wasm   # generate bindings, build gmsh, link + assemble dist/
npm test             # Node test suite
npm run test:browser # headless-Chromium test (needs playwright + chromium)

npm run build runs build:libomp, build:occt, then build:wasm.

The pipeline

scripts/setup-emsdk.sh   emsdk (pinned) -> .emsdk/
scripts/build-libomp.sh  LLVM openmp source -> libomp.a in build/libomp-install/
scripts/build-occt.sh    OCCT source -> static libTK*.a in build/occt-install/
scripts/build-wasm.sh    gen_js.py  -> generated/ (exports, descriptor, .d.ts)
                         emcmake gmsh -> build/gmsh/libgmsh.a
                         emcc link  -> dist/gmsh-core.{mjs,cjs,wasm}
                         assemble.mjs -> dist/gmsh.{mjs,cjs}, runtime, descriptor

See Architecture for details.

Key flags

Gmsh CMake (headless, OCC-enabled, OpenMP):

-DCMAKE_C_FLAGS="-pthread" -DCMAKE_CXX_FLAGS="-fexceptions -pthread"
-DENABLE_BUILD_LIB=ON -DENABLE_FLTK=OFF -DENABLE_GRAPHICS=OFF
-DENABLE_OPENMP=ON -DENABLE_MPI=OFF
-DOpenMP_C_FLAGS="-fopenmp -pthread -I<libomp>/include" -DOpenMP_C_LIB_NAMES=omp
-DOpenMP_CXX_FLAGS="-fopenmp -pthread -I<libomp>/include" -DOpenMP_CXX_LIB_NAMES=omp
-DOpenMP_omp_LIBRARY=<libomp>/lib/libomp.a
-DENABLE_EIGEN=ON -DENABLE_BLAS_LAPACK=OFF
-DENABLE_OCC=ON -DENABLE_OCC_STATIC=ON -DENABLE_OCC_CAF=ON
-DENABLE_MESH=ON -DENABLE_PARSER=ON -DENABLE_POST=ON

The explicit OpenMP_* variables are required because Emscripten ships no OpenMP runtime, so CMake's FindOpenMP cannot autodetect one — without them gmsh silently falls back to a serial build (build-wasm.sh asserts that OpenMP appears in the generated GMSH_CONFIG_OPTIONS after configure to catch this). Every object linked into the shared-memory module must be compiled with -pthread (gmsh, OCCT, libomp alike), or wasm-ld rejects the link.

Emscripten link:

-O3 -fexceptions -pthread
-sMODULARIZE=1 -sEXPORT_NAME=initGmsh -sEXPORT_ES6=1 (ESM)
-sALLOW_MEMORY_GROWTH=1 -sINITIAL_MEMORY=64MB -sMAXIMUM_MEMORY=4GB -sMALLOC=emmalloc
-sPTHREAD_POOL_SIZE=(typeof navigator!=='undefined'&&navigator.hardwareConcurrency)||4
-sFORCE_FILESYSTEM=1
-sEXPORTED_FUNCTIONS=@generated/exported_functions.json
-sENVIRONMENT=node,web,worker

A no-OCC build (faster, smaller, no STEP/IGES) is available with:

GMSH_ENABLE_OCC=OFF npm run build:wasm

Build without OpenCASCADE

OCC roughly quadruples the .wasm size. If you do not need STEP/IGES/BREP import or the occ kernel, build with GMSH_ENABLE_OCC=OFF for a ~12 MB artifact (vs ~45 MB).