kobodl/build-web.sh
Ville Lindholm 0677b2cbca
Add Emscripten/WebAssembly build target
Builds a browser-playable .html/.js/.wasm/.data via `./build-web.sh` (no
new CMake top-level target — Emscripten is detected at configure time and
takes the existing kobodl through a web-flavored pipeline).

Key pieces:
- CMakeLists.txt: route SDL3 through `--use-port=sdl3`; substitute
  `--use-port=libpng` for the missing sdl3_image port (Emscripten 5.0.7
  ships only sdl3 + sdl3_ttf). pthread (atomics+bulk-memory) lifted to
  kobo_deps so every TU agrees with wasm-ld's --shared-memory. Link with
  -sASYNCIFY (avoids rewriting kobo's blocking main loop around
  emscripten_set_main_loop), -sALLOW_MEMORY_GROWTH/-sMAXIMUM_MEMORY=1gb,
  -sPTHREAD_POOL_SIZE=4, -lidbfs.js, and --preload-file data@/data.
- graphics/img_compat.{h,c}: libpng-backed IMG_Load shim, used in
  sprite.c / gfxengine.cpp / filters.c via #include "img_compat.h".
  Native builds passthrough to <SDL3_image/SDL_image.h> unchanged.
- web/shell.html: HTML wrapper that mounts /home as IDBFS for persistent
  scores/config. Startup gated on addRunDependency until syncfs(true)
  finishes, then /home/scores is mkdir'd post-load (the game's addPlayer
  doesn't auto-create the score dir; see TODO in score.cpp).
  beforeunload + visibilitychange flushes /home back to IndexedDB.
- build-web.sh: emcmake wrapper + a static server that sets the
  COOP/COEP headers SharedArrayBuffer/pthreads require.

Source fixes needed to build under Emscripten's libc/libcxx:
- Renamed enemy_kind `pipe2` -> `pipe2k` (collided with libc pipe2(2)
  always declared in Emscripten's <unistd.h>).
- graphics/toolkit.cpp: added missing <stdio.h> for snprintf (Emscripten's
  libcxx headers don't pull it in transitively).
- states.cpp: gated the "Quit Kobo Deluxe" main-menu button on
  !__EMSCRIPTEN__; exit() on the web leaves a dead canvas.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-04 18:47:10 +03:00

49 lines
1.5 KiB
Bash
Executable File

#!/bin/sh
# Build Kobo Deluxe as a WebAssembly app via Emscripten.
#
# Prereq: install and activate emsdk so emcmake / emcc are on PATH.
# git clone https://github.com/emscripten-core/emsdk ~/emsdk
# ~/emsdk/emsdk install latest && ~/emsdk/emsdk activate latest
# . ~/emsdk/emsdk_env.sh
#
# Output: build-web/kobodl.{html,js,wasm,data}
# Serve from build-web/ with any static server that sets the COOP/COEP headers
# required for SharedArrayBuffer (pthreads). Example:
# ./build-web.sh && ./build-web.sh serve
set -e
HERE="$(cd "$(dirname "$0")" && pwd)"
BUILD="$HERE/build-web"
case "${1:-build}" in
serve)
cd "$BUILD"
exec python3 -c "
import http.server, socketserver
class H(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header('Cross-Origin-Opener-Policy', 'same-origin')
self.send_header('Cross-Origin-Embedder-Policy', 'require-corp')
super().end_headers()
socketserver.TCPServer(('', 8000), H).serve_forever()
"
;;
clean)
rm -rf "$BUILD"
;;
build|*)
command -v emcmake >/dev/null 2>&1 || {
echo "emcmake not found. Source emsdk_env.sh first." >&2
exit 1
}
mkdir -p "$BUILD"
cd "$BUILD"
emcmake cmake -DCMAKE_BUILD_TYPE=Release "$HERE"
cmake --build . -j
echo
echo "Built: $BUILD/kobodl.html"
echo "Serve: ./build-web.sh serve (then open http://localhost:8000/kobodl.html)"
;;
esac