# WebAssembly cross-build via Emscripten. # # Includes Emscripten's own platform toolchain (found through $EMSDK, set by the # emsdk image / `emsdk_env.sh`) and then layers the project's requirements: # # * C++26 `import std;`. Emscripten ships the libc++ `std` module source and a # modules.json in its sysroot; its toolchain wires that up, but only if # `CMAKE_CXX_MODULE_STD` is on and no std-modules JSON has been set yet, so # both are arranged before Emscripten.cmake is included and before the # compiler is probed. # * Global `-fexceptions`. Emscripten disables exceptions by default, and the # libc++ `std` module must be built with the same setting as its consumers, # or clang rejects the prebuilt module ("configuration mismatch"). The engine # throws, so exceptions are enabled everywhere. # * Asyncify turns `emscripten_sleep` (used by display::sleep_frame on # Emscripten) into a yield: the engine's frame loops are blocking, and without # yielding the worker freezes and never paints. # # No pthreads: the runtime's main thread runs inside a plain Web Worker started # by `apps/web/openra3.worker.js`, so its virtual filesystem is local to that # worker and `FS.createLazyFile` (synchronous XHR) is legal. Under # `PROXY_TO_PTHREAD` Emscripten proxies every filesystem syscall to the main # browser thread, where synchronous XHR is forbidden, so lazy assets cannot work # there - hence the plain worker. The SDL3 web port is only pulled in by the # legacy main-thread backend (OPENRA3_WASM_SDL). # `import std` support: the gate and the module switch must be in place before # Emscripten.cmake runs and before the compiler is probed. set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") set(CMAKE_CXX_MODULE_STD ON) # Let Emscripten.cmake point CMake at its own sysroot modules.json. unset(CMAKE_CXX_STDLIB_MODULES_JSON) if(DEFINED ENV{EMSDK}) set(OPENRA3_EMSCRIPTEN_CMAKE "$ENV{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake") elseif(DEFINED ENV{EMSCRIPTEN_ROOT}) set(OPENRA3_EMSCRIPTEN_CMAKE "$ENV{EMSCRIPTEN_ROOT}/cmake/Modules/Platform/Emscripten.cmake") endif() if(NOT EXISTS "${OPENRA3_EMSCRIPTEN_CMAKE}") message(FATAL_ERROR "Emscripten.cmake not found (set EMSDK); looked at '${OPENRA3_EMSCRIPTEN_CMAKE}'") endif() include("${OPENRA3_EMSCRIPTEN_CMAKE}") # Exceptions are used by the engine; keep them on globally so the std module and # its consumers agree. # # Asyncify turns `emscripten_sleep` (used by display::sleep_frame on Emscripten) # into a yield to the browser: the engine's frame loops are blocking, and # without yielding the worker freezes and never paints. set(CMAKE_CXX_FLAGS_INIT "-fexceptions -sASYNCIFY=1") set(CMAKE_C_FLAGS_INIT "-sASYNCIFY=1") set(CMAKE_EXE_LINKER_FLAGS_INIT "-fexceptions -sDISABLE_EXCEPTION_CATCHING=0 -sALLOW_MEMORY_GROWTH=1 -sASYNCIFY=1") set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fexceptions -sDISABLE_EXCEPTION_CATCHING=0 -sALLOW_MEMORY_GROWTH=1 -sASYNCIFY=1")