#!/usr/bin/env bash # Rebuild WASM artifacts and install them into solitaire_server/web/pkg/. # # Two artifacts are produced: # solitaire_wasm.* — thin replay-viewer + interactive JS API (wasm-pack) # canvas.* — full Bevy WASM app for play.html (cargo + wasm-bindgen) # # Prerequisites: # cargo install wasm-pack wasm-bindgen-cli # rustup target add wasm32-unknown-unknown # (optional) cargo install wasm-opt # for smaller canvas_bg.wasm # # Run from the repo root: # ./build_wasm.sh # # The generated pkg/ files are committed to git so self-hosters who don't # touch the WASM crates can skip this step. Regenerate after any change to # solitaire_wasm/, solitaire_web/, solitaire_engine/, or solitaire_core/. set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" OUT_DIR="$REPO_ROOT/solitaire_server/web/pkg" # Reproducible builds. The wasm artifacts otherwise bake in machine-specific # absolute source paths (the cargo registry, the rustup std sources, and this # checkout), so a rebuild on a different machine produces different bytes and # the CI freshness gate (rebuild-and-diff) false-positives. Remap all three # prefixes to fixed names so the output is byte-identical anywhere. # # We must use CARGO_ENCODED_RUSTFLAGS (not RUSTFLAGS) and re-state the # getrandom backend cfg here: a `*_RUSTFLAGS` env var *replaces* — does not # merge with — the `[target.wasm32-unknown-unknown] rustflags` in # .cargo/config.toml, so dropping that cfg would break the wasm getrandom build. # Keep this `--cfg` in sync with .cargo/config.toml. CARGO_HOME_DIR="${CARGO_HOME:-$HOME/.cargo}" RUSTUP_HOME_DIR="${RUSTUP_HOME:-$HOME/.rustup}" US=$'\x1f' # unit separator: CARGO_ENCODED_RUSTFLAGS arg delimiter export CARGO_ENCODED_RUSTFLAGS="--cfg${US}getrandom_backend=\"wasm_js\"${US}--remap-path-prefix=${CARGO_HOME_DIR}=/cargo${US}--remap-path-prefix=${RUSTUP_HOME_DIR}=/rustup${US}--remap-path-prefix=${REPO_ROOT}=/build" if ! command -v wasm-pack &> /dev/null; then echo "error: wasm-pack not found." >&2 echo " Install with: cargo install wasm-pack" >&2 exit 1 fi echo "Building solitaire_wasm (target: web)..." wasm-pack build \ --target web \ --out-dir "$OUT_DIR" \ --no-typescript \ "$REPO_ROOT/solitaire_wasm" # wasm-pack writes a package.json and .gitignore into the output dir. # Remove them — we manage the output directory ourselves. rm -f "$OUT_DIR/package.json" "$OUT_DIR/.gitignore" # --------------------------------------------------------------------------- # Bevy WASM app (solitaire_web → canvas.js + canvas_bg.wasm) # --------------------------------------------------------------------------- if ! command -v wasm-bindgen &> /dev/null; then echo "error: wasm-bindgen not found." >&2 echo " Install with: cargo install wasm-bindgen-cli" >&2 echo " The CLI version must match the wasm-bindgen crate dep." >&2 exit 1 fi echo "Building solitaire_web (Bevy WASM app)..." # wasm-release is the size-focused profile (fat LTO, CGU=1, opt-level "s") — # see [profile.wasm-release] in Cargo.toml. Download size is the constraint. cargo build --profile wasm-release --target wasm32-unknown-unknown -p solitaire_web echo "Running wasm-bindgen for solitaire_web..." wasm-bindgen \ --out-dir "$OUT_DIR" \ --out-name canvas \ --target web \ --no-typescript \ "${CARGO_TARGET_DIR:-$REPO_ROOT/target}/wasm32-unknown-unknown/wasm-release/solitaire_web.wasm" # Optional size optimisation — Bevy bundles are large (~5-15 MB uncompressed). # wasm-opt passes are skipped silently when the tool is not installed. if command -v wasm-opt &> /dev/null; then echo "Running wasm-opt on canvas_bg.wasm..." # Use -O2 (not -Oz): Bevy's render pipeline uses deep call stacks and # complex memory patterns that wasm-opt -Oz can miscompile, resulting # in a grey screen on first load. -O2 is speed-optimised and avoids # the size-focused transforms that trigger the regression. wasm-opt -O2 \ -o "$OUT_DIR/canvas_bg.wasm" \ "$OUT_DIR/canvas_bg.wasm" else echo "note: wasm-opt not found; skipping size optimisation." echo " Install with: cargo install wasm-opt (or via binaryen)" fi echo "Done. Output:" ls -lh "$OUT_DIR"