2026-08-22 14:30:14 +02:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# Builds the wasm32 static-library dependency set vpinball needs:
|
|
|
|
|
# SDL3, SDL3_image, SDL3_ttf (+freetype), FreeImage, libwinevbs.
|
|
|
|
|
#
|
|
|
|
|
# Modeled on vendor/vpinball/platforms/linux-x64/external.sh's own build
|
|
|
|
|
# sections, with `cmake` swapped for `emcmake cmake` and shared libs swapped
|
|
|
|
|
# for static (a single wasm binary has no runtime dynamic loader). Codec/font
|
|
|
|
|
# backends are scoped down from vpinball's native default to what's realistic
|
|
|
|
|
# for browser-loaded .vpx textures (PNG/JPEG/BMP/etc. via SDL3_image's
|
|
|
|
|
# built-in decoders + stb, no libpng/libjpeg/libwebp/libtiff/libjxl/libavif
|
|
|
|
|
# needed at all; SDL3_ttf uses vendored freetype only, no harfbuzz/plutosvg)
|
|
|
|
|
# - this avoids pulling in several hundred MB of vendored codec submodules
|
|
|
|
|
# (AV1/AVIF in particular) that real VPX tables don't exercise.
|
|
|
|
|
#
|
|
|
|
|
# Requires: scripts/setup.sh has already run (vendor/ populated+patched,
|
|
|
|
|
# emsdk installed).
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
|
|
source "$ROOT_DIR/scripts/versions.sh"
|
|
|
|
|
|
|
|
|
|
VENDOR_DIR="$ROOT_DIR/vendor"
|
|
|
|
|
DEPS_DIR="$ROOT_DIR/build/deps-wasm32"
|
|
|
|
|
WORK_DIR="$ROOT_DIR/build/deps-src"
|
|
|
|
|
NUM_PROCS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)"
|
|
|
|
|
|
|
|
|
|
if [ ! -d "$VENDOR_DIR/vpinball" ] || [ ! -d "$VENDOR_DIR/libwinevbs" ]; then
|
|
|
|
|
echo "ERROR: vendor/ not populated. Run scripts/setup.sh first." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
if ! command -v emcc >/dev/null 2>&1; then
|
|
|
|
|
echo "ERROR: emcc not on PATH. Run: source $ROOT_DIR/emsdk/emsdk_env.sh" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
mkdir -p "$DEPS_DIR/lib" "$DEPS_DIR/include" "$WORK_DIR"
|
|
|
|
|
|
|
|
|
|
cache_check() { [ "$(cat "$1/.cache-sha" 2>/dev/null || true)" = "$2" ]; }
|
|
|
|
|
|
|
|
|
|
# --- SDL3 core -------------------------------------------------------------
|
|
|
|
|
if ! cache_check "$WORK_DIR/SDL3/SDL" "$SDL_SHA"; then
|
|
|
|
|
echo "== Building SDL3 core for wasm32 =="
|
|
|
|
|
rm -rf "$WORK_DIR/SDL3/SDL"
|
|
|
|
|
mkdir -p "$WORK_DIR/SDL3"
|
|
|
|
|
cd "$WORK_DIR/SDL3"
|
|
|
|
|
curl -sL "https://github.com/libsdl-org/SDL/archive/${SDL_SHA}.tar.gz" | tar xz
|
|
|
|
|
mv "SDL-${SDL_SHA}" SDL
|
|
|
|
|
( cd SDL && emcmake cmake -DSDL_SHARED=OFF -DSDL_STATIC=ON -DSDL_TEST_LIBRARY=OFF \
|
|
|
|
|
-DCMAKE_BUILD_TYPE=Release -B build && cmake --build build -- -j"$NUM_PROCS" )
|
|
|
|
|
echo "$SDL_SHA" > "$WORK_DIR/SDL3/SDL/.cache-sha"
|
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --- SDL3_image (built-in decoders + stb only, no vendored codec libs) ----
|
|
|
|
|
if ! cache_check "$WORK_DIR/SDL3/SDL_image" "$SDL_IMAGE_SHA"; then
|
|
|
|
|
echo "== Building SDL3_image for wasm32 =="
|
|
|
|
|
rm -rf "$WORK_DIR/SDL3/SDL_image"
|
|
|
|
|
cd "$WORK_DIR/SDL3"
|
|
|
|
|
curl -sL "https://github.com/libsdl-org/SDL_image/archive/${SDL_IMAGE_SHA}.tar.gz" | tar xz
|
|
|
|
|
mv "SDL_image-${SDL_IMAGE_SHA}" SDL_image
|
|
|
|
|
( cd SDL_image && emcmake cmake \
|
|
|
|
|
-DBUILD_SHARED_LIBS=OFF -DSDLIMAGE_SAMPLES=OFF -DSDLIMAGE_VENDORED=OFF \
|
|
|
|
|
-DSDLIMAGE_AVIF=OFF -DSDLIMAGE_WEBP=OFF -DSDLIMAGE_JXL=OFF -DSDLIMAGE_TIF=OFF \
|
|
|
|
|
-DSDLIMAGE_PNG_LIBPNG=OFF \
|
|
|
|
|
-DSDL3_DIR=../SDL/build -DCMAKE_BUILD_TYPE=Release -B build \
|
|
|
|
|
&& cmake --build build -- -j"$NUM_PROCS" )
|
|
|
|
|
echo "$SDL_IMAGE_SHA" > "$WORK_DIR/SDL3/SDL_image/.cache-sha"
|
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --- SDL3_ttf (vendored freetype only, no harfbuzz/plutosvg) --------------
|
|
|
|
|
if ! cache_check "$WORK_DIR/SDL3/SDL_ttf" "$SDL_TTF_SHA"; then
|
|
|
|
|
echo "== Building SDL3_ttf for wasm32 =="
|
|
|
|
|
rm -rf "$WORK_DIR/SDL3/SDL_ttf"
|
|
|
|
|
cd "$WORK_DIR/SDL3"
|
|
|
|
|
curl -sL "https://github.com/libsdl-org/SDL_ttf/archive/${SDL_TTF_SHA}.tar.gz" | tar xz
|
|
|
|
|
mv "SDL_ttf-${SDL_TTF_SHA}" SDL_ttf
|
|
|
|
|
( cd SDL_ttf && git clone --filter=blob:none --depth 1 \
|
|
|
|
|
https://github.com/libsdl-org/freetype.git external/freetype \
|
|
|
|
|
&& emcmake cmake \
|
|
|
|
|
-DBUILD_SHARED_LIBS=OFF -DSDLTTF_SAMPLES=OFF -DSDLTTF_VENDORED=ON \
|
|
|
|
|
-DSDLTTF_HARFBUZZ=OFF -DSDLTTF_PLUTOSVG=OFF \
|
|
|
|
|
-DSDL3_DIR=../SDL/build -DCMAKE_BUILD_TYPE=Release -B build \
|
|
|
|
|
&& cmake --build build -- -j"$NUM_PROCS" )
|
|
|
|
|
echo "$SDL_TTF_SHA" > "$WORK_DIR/SDL3/SDL_ttf/.cache-sha"
|
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
cp "$WORK_DIR"/SDL3/SDL/build/libSDL3.a "$DEPS_DIR/lib/"
|
|
|
|
|
cp "$WORK_DIR"/SDL3/SDL_image/build/libSDL3_image.a "$DEPS_DIR/lib/"
|
|
|
|
|
cp "$WORK_DIR"/SDL3/SDL_ttf/build/libSDL3_ttf.a "$DEPS_DIR/lib/"
|
|
|
|
|
cp "$WORK_DIR"/SDL3/SDL_ttf/build/external/freetype/libfreetype.a "$DEPS_DIR/lib/"
|
|
|
|
|
cp -r "$WORK_DIR/SDL3/SDL/include/SDL3" "$DEPS_DIR/include/"
|
|
|
|
|
cp -r "$WORK_DIR/SDL3/SDL_image/include/SDL3_image" "$DEPS_DIR/include/"
|
|
|
|
|
cp -r "$WORK_DIR/SDL3/SDL_ttf/include/SDL3_ttf" "$DEPS_DIR/include/"
|
|
|
|
|
|
|
|
|
|
# --- FreeImage (bundles all its codecs as vendored source, no submodules) -
|
|
|
|
|
if ! cache_check "$WORK_DIR/freeimage" "$FREEIMAGE_SHA"; then
|
|
|
|
|
echo "== Building FreeImage for wasm32 =="
|
|
|
|
|
rm -rf "$WORK_DIR/freeimage"
|
|
|
|
|
mkdir -p "$WORK_DIR/freeimage"
|
|
|
|
|
cd "$WORK_DIR/freeimage"
|
|
|
|
|
curl -sL "https://github.com/toxieainc/freeimage/archive/${FREEIMAGE_SHA}.tar.gz" | tar xz
|
|
|
|
|
mv "freeimage-${FREEIMAGE_SHA}" freeimage
|
|
|
|
|
# PLATFORM/ARCH here are freeimage's own bookkeeping vars (like
|
|
|
|
|
# libwinevbs's), not a toolchain gate - emcmake supplies the real wasm32
|
|
|
|
|
# toolchain, so any placeholder PLATFORM value that isn't specially
|
|
|
|
|
# branched on (macos/ios/tvos/android) works unmodified.
|
|
|
|
|
( cd freeimage && emcmake cmake -DPLATFORM=linux -DARCH=wasm32 -DBUILD_STATIC=ON \
|
|
|
|
|
-DBUILD_SHARED=OFF -DCMAKE_BUILD_TYPE=Release -B build && cmake --build build -- -j"$NUM_PROCS" )
|
|
|
|
|
echo "$FREEIMAGE_SHA" > "$WORK_DIR/freeimage/.cache-sha"
|
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
cp "$WORK_DIR"/freeimage/freeimage/build/libfreeimage.a "$DEPS_DIR/lib/"
|
|
|
|
|
cp "$WORK_DIR/freeimage/freeimage/Source/FreeImage.h" "$DEPS_DIR/include/"
|
|
|
|
|
|
|
|
|
|
# --- libwinevbs (its own CMakeLists.txt needs no patch beyond the winnt.h --
|
|
|
|
|
# --- CONTEXT stub already applied by setup.sh; PLATFORM/ARCH are likewise --
|
|
|
|
|
# --- just its own bookkeeping, same as FreeImage above) --------------------
|
|
|
|
|
if ! cache_check "$VENDOR_DIR/libwinevbs" "built-${LIBWINEVBS_SHA}"; then
|
|
|
|
|
echo "== Building libwinevbs for wasm32 =="
|
|
|
|
|
( cd "$VENDOR_DIR/libwinevbs" && emcmake cmake -DPLATFORM=emscripten -DARCH=wasm32 \
|
|
|
|
|
-DBUILD_STATIC=ON -DBUILD_SHARED=OFF -DCMAKE_BUILD_TYPE=Release -B build \
|
|
|
|
|
&& cmake --build build -- -j"$NUM_PROCS" )
|
|
|
|
|
echo "built-${LIBWINEVBS_SHA}" > "$VENDOR_DIR/libwinevbs/.cache-sha"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
cp "$VENDOR_DIR"/libwinevbs/build/libwinevbs.a "$DEPS_DIR/lib/"
|
|
|
|
|
mkdir -p "$DEPS_DIR/include/libwinevbs/wine/include" "$DEPS_DIR/include/libwinevbs/atl/include" "$DEPS_DIR/include/libwinevbs/atlmfc/include"
|
|
|
|
|
cp "$VENDOR_DIR/libwinevbs/include/libwinevbs.h" "$DEPS_DIR/include/libwinevbs/"
|
|
|
|
|
cp -r "$VENDOR_DIR/libwinevbs/wine/include/"* "$DEPS_DIR/include/libwinevbs/wine/include/"
|
|
|
|
|
cp -r "$VENDOR_DIR/libwinevbs/atl/include/"* "$DEPS_DIR/include/libwinevbs/atl/include/"
|
|
|
|
|
cp -r "$VENDOR_DIR/libwinevbs/atlmfc/include/"* "$DEPS_DIR/include/libwinevbs/atlmfc/include/"
|
|
|
|
|
|
2026-08-23 12:09:35 +02:00
|
|
|
# --- libpinmame (the real ROM/hardware emulation core VPinMAME.Controller --
|
|
|
|
|
# --- wraps on every other platform; validated end-to-end for wasm32 by this
|
|
|
|
|
# --- project's own pinmame-wasm spike - see patches/pinmame/ for the 3
|
|
|
|
|
# --- portability fixes it needed. ARCH=wasm32 (not x86/x64/arm64/aarch64)
|
|
|
|
|
# --- makes its own CMakeLists.txt skip the asmjit-based ARM7 JIT backend and
|
|
|
|
|
# --- fall back to its portable interpreter, exactly as it already does for
|
|
|
|
|
# --- 32-bit arm targets - no patch needed for that part. libpinmame's
|
|
|
|
|
# --- CMakeLists.txt lives at cmake/libpinmame/ but its source paths are all
|
|
|
|
|
# --- relative to the repo root, so upstream's own CI copies it there first;
|
|
|
|
|
# --- mirrored here rather than patched, to stay a plain file copy diff-free.
|
|
|
|
|
if ! cache_check "$VENDOR_DIR/pinmame" "built-${PINMAME_SHA}"; then
|
|
|
|
|
echo "== Building libpinmame for wasm32 =="
|
|
|
|
|
cp "$VENDOR_DIR/pinmame/cmake/libpinmame/CMakeLists.txt" "$VENDOR_DIR/pinmame/CMakeLists.txt"
|
|
|
|
|
( cd "$VENDOR_DIR/pinmame" && emcmake cmake -DPLATFORM=linux -DARCH=wasm32 \
|
|
|
|
|
-DBUILD_STATIC=ON -DBUILD_SHARED=OFF -DCMAKE_BUILD_TYPE=Release -B build \
|
|
|
|
|
&& cmake --build build --target pinmame_static -- -j"$NUM_PROCS" )
|
|
|
|
|
echo "built-${PINMAME_SHA}" > "$VENDOR_DIR/pinmame/.cache-sha"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
cp "$VENDOR_DIR/pinmame/build/libpinmame.a" "$DEPS_DIR/lib/"
|
|
|
|
|
mkdir -p "$DEPS_DIR/include/pinmame"
|
|
|
|
|
cp "$VENDOR_DIR/pinmame/src/libpinmame/libpinmame.h" "$DEPS_DIR/include/pinmame/"
|
|
|
|
|
cp "$VENDOR_DIR/pinmame/src/libpinmame/PinMAMEPlugin.h" "$DEPS_DIR/include/pinmame/"
|
|
|
|
|
|
2026-08-22 14:30:14 +02:00
|
|
|
echo ""
|
|
|
|
|
echo "== build-deps.sh complete: $DEPS_DIR =="
|
|
|
|
|
ls -la "$DEPS_DIR/lib"
|