Web builds
Compile a game to WebAssembly with Emscripten and host it as a page.
On web, moksha_add_game produces a page: <Target>.html, .js, .wasm and .data. Games don’t need any web-specific code.
Setup
You need Emscripten 4.0.10 or newer (Moksha is built with 6.0.13), whose install needs Python 3.10+. You also need a cook built for your host machine, because the cook runs during the build. With the live preset from Getting started:
cmake --preset live
cmake --build --preset live --target Moksha_Cook
Rebuild it after changing the cook.
Then add a per-machine web preset to CMakeUserPresets.json, replacing <emsdk> with your emsdk folder:
{
"name": "web",
"binaryDir": "${sourceDir}/build-web",
"toolchainFile": "<emsdk>/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake",
"cacheVariables": {
"FETCHCONTENT_SOURCE_DIR_MOKSHA": "${sourceDir}/../../moksha/moksha",
"MOKSHA_COOK_EXECUTABLE": "${sourceDir}/build-live/_deps/moksha-build/tools/cook/Moksha_Cook",
"CMAKE_BUILD_TYPE": "Release"
}
}
Add a matching build preset, { "name": "web", "configurePreset": "web" }.
Build and serve
cmake --preset web
cmake --build --preset web --target MyGame
WebGPU needs a secure page, so serve the output from localhost or HTTPS. A plain http:// address on your network will not work, even though the page itself loads.
python3 -m http.server -d build-web 8000
DISPLAY_NAME on moksha_add_game sets the page’s title. The samples repository’s tools/build_web.py is a working example of collecting several games into one folder.
What’s different in a browser
- WebGPU only. There is no WebGL fallback, and the page shows a message if the browser has no WebGPU.
- No networking. Browsers have no raw sockets, so
gameClientnever connects, andcontentClientfails and carries on. Two socket errors in the console at startup are expected. - The window size is read once. The game keeps its configured size and shrinks to fit the browser window at startup, and it never scales up or resizes afterwards. If you embed it in an
<iframe>, give the frame its final size before the game loads. Quit()only logs, since a page can’t close itself.- Saves live in the browser.
UserDatais kept in IndexedDB, per site address, after each write. A tab killed right after a write can lose that write. Moving the game to a new address loses its saves. - The app can end without
End(), as it can on mobile. - Input: keyboard and mouse, with the first finger acting as the mouse.
Hosting
A build is single-threaded, so it needs no COOP or COEP headers. Any static host with HTTPS works. Serve .wasm as application/wasm, and turn on compression if you can: the .data files shrink a great deal, taking a whole game from 2-3 MB to about 300 KB with gzip.