building.md - Virtastic Notepad

Jagged Alliance 2 manual: Building from source

--- title: "Building from source" description: "Build the ja2-web engine yourself: the repository layout, the Emscripten 6.0.1 and Rust nightly toolchain, the dev server, and the flags that matter." book: "Developers" order: 60 --- This page covers what is in the ja2-web repository, running a development build, and building the engine with Emscripten. To run your own instance without building anything, see [Self-hosting](/ja2/docs/self-hosting/).

## What's in the repository

This is a code-only repo. Large binaries (game data, dependency caches, build artifacts) are excluded via [`.gitignore`](https://github.com/Virtastic/ja2-web/blob/main/.gitignore) and must be provided or rebuilt locally. | Path | Purpose | |------|---------| | `source-ja2/` | JA2 Stracciatella engine source (upstream v0.22.1 plus local WASM changes under `#ifdef __EMSCRIPTEN__`) | | `wasm-build/` | Toolchain pin (`env.sh`) + configure/build/package scripts, the CDP test harness, smoke tests | | `fsroot/` | Small preloaded tree baked into `ja2.data`: `externalized/`, `mods/` | | `play/` | Browser front-end: `launcher.html`, `index.html`, `server.py` dev server, built `ja2.{js,wasm,data}` | | `infra/` | `nginx.conf` (COOP/COEP + gzip_static) and Terraform (DNS) for production |

### Not included (kept local)

- `gamedata-src/`, `gamedata-lean/`, `fsroot/gamedata/`, `play/ja2*.data`: commercial JA2 game data (`Data/*.slf`). Never committed - copyright. - `build-wasm/` and all `*.wasm` / `*.data` build outputs. - Prebuilt desktop SDL2 binaries and bulky community mods (get them from upstream Stracciatella if you need them).

## Running (dev)

You need your own JA2 game data to build the bundled dev package. Then: ```bash # 1. one-time: stage your JA2 Data/ and repackage the data blob wasm-build/bundle-data.sh ~/path/to/ja2install # 2. build the engine wasm-build/configure-ja2.sh # emcmake configure . wasm-build/env.sh && ninja -C build-wasm ja2 # 3. serve play/ over a cross-origin-isolated origin python3 play/server.py # http://localhost:8795 (set PORT= to change) ``` The dev server sets the cross-origin-isolation headers SharedArrayBuffer needs. Open the URL in desktop Chrome. Set `OPENMW_LAUNCHER=0` to boot straight into the game instead of the data chooser.

## Building

You need **Emscripten 6.0.1**, a **Rust nightly** toolchain, CMake, and Ninja. The exact pins live in [`wasm-build/env.sh`](https://github.com/Virtastic/ja2-web/blob/main/wasm-build/env.sh) (a mismatched Rust nightly miscompiles `std::path` on `wasm32-unknown-emscripten` - do not drift off the pin). ```bash wasm-build/configure-ja2.sh # emcmake cmake -S source-ja2 -B build-wasm . wasm-build/env.sh && ninja -C build-wasm ja2 cp build-wasm/ja2.{js,wasm,data} play/ ``` Things to watch, which is why the flags are scripted in `env.sh`: - The whole build uses `-fexceptions` (JS exceptions, the rustc emscripten ABI) and `-pthread`. Do **not** add `-flto`. - `-sSTACK_SIZE=8388608` (8 MB) - the world-map loader overflows the default 64 KB wasm stack. - `-msimd128` (C++ and Rust `+simd128`) vectorizes the software blitters. - Audio defaults to a Wasm AudioWorklet backend; `?audio=legacy` selects the old SDL/ScriptProcessor path. [WebAssembly adaptations](/ja2/docs/wasm-adaptations/) is a writeup of how the native desktop engine was made to run in a browser tab.

## Hosting what you built

Serve `play/` over HTTPS (`http://localhost` also counts) with these headers on every response, so the page is cross-origin isolated (required for SharedArrayBuffer / pthreads): ``` Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp Cross-Origin-Resource-Policy: cross-origin ``` Serve the precompressed `.gz` siblings with `Content-Encoding: gzip` (nginx `gzip_static on;`). That takes the ~10 MB wasm down to ~3 MB over the wire (the `.js` loader and small preloaded `.data` blob compress too). The reference vhost is [`infra/nginx.conf`](https://github.com/Virtastic/ja2-web/blob/main/infra/nginx.conf). The engine files are content-versioned into `e/<hash>/`, so a new build is served at a fresh URL and the CDN can never serve a mismatched build. Pull requests are welcome; see [CONTRIBUTING.md](https://github.com/Virtastic/ja2-web/blob/main/CONTRIBUTING.md). Deployment and CI are maintainer-only.