From 1330bb70827002fa73fba2ff87882eaca0f0624a Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Fri, 11 Sep 2026 11:05:01 -0400 Subject: [PATCH] build(scripts): let build-wasm.sh build any wasm-bindgen crate It takes an optional crate, output directory and output name, and reads the build output from CARGO_TARGET_DIR when set, as build-site.sh now does for the API docs. build-dashboard-wasm.sh becomes a call to it. Co-Authored-By: Claude Opus 5 (1M context) Change-Id: I7f18cd11030a9f6ad7f4e4b51d4d9c70d6e9b8bd --- scripts/build-dashboard-wasm.sh | 77 +++------------------------------ scripts/build-site.sh | 2 +- scripts/build-wasm.sh | 62 +++++++++++++++++--------- 3 files changed, 49 insertions(+), 92 deletions(-) diff --git a/scripts/build-dashboard-wasm.sh b/scripts/build-dashboard-wasm.sh index 0477c159..4fde9311 100755 --- a/scripts/build-dashboard-wasm.sh +++ b/scripts/build-dashboard-wasm.sh @@ -2,84 +2,19 @@ # Builds crates/didbot-site-anim for the browser and drops the result where # `crates/didbot-serve`'s dashboard serves it from: # crates/didbot-serve/assets/dashboard/wasm/. Same crate, same wave field -# (`wave.rs`) as scripts/build-wasm.sh builds for the site's prototype F — -# this is a second, deliberately separate output directory rather than a -# shared one, because `didbot-serve` and the site are different served -# processes with no runtime relationship to each other. This script is -# intentionally close to a copy of build-wasm.sh's own logic: the two are -# short, and threading one shared script through two unrelated crates' -# lifecycles (one wants Astro's public/ passthrough, the other wants an -# axum route) would cost more legibility than the duplication does. +# (`wave.rs`) as scripts/build-wasm.sh builds for the site's prototype F, in +# a second output directory: `didbot-serve` and the site are different served +# processes with no runtime relationship to each other. The dashboard serves +# no TypeScript declarations, so the .d.ts files are dropped. # # An opt-in step, not part of `cargo build --workspace` or `cargo test -# --workspace`: see crates/didbot-site-anim/Cargo.toml's own comment on why -# the crate builds fine natively without the wasm32 target, which this -# script is the one place that reaches for it. The dashboard falls back to a +# --workspace`: see scripts/build-wasm.sh. The dashboard falls back to a # still background when this has not been run — see # crates/didbot-serve/src/dashboard.rs's `wasm_asset` doc comment. set -euo pipefail cd "$(dirname "$0")/.." -crate_dir="crates/didbot-site-anim" out_dir="crates/didbot-serve/assets/dashboard/wasm" - -locked_version="$( - awk ' - /^name = "wasm-bindgen"$/ { want = 1; next } - want && /^version = / { gsub(/"/, "", $3); print $3; exit } - ' Cargo.lock -)" - -if [ -z "$locked_version" ]; then - echo "build-dashboard-wasm: could not find wasm-bindgen's locked version in Cargo.lock" >&2 - exit 1 -fi - -if ! rustup target list --installed 2>/dev/null | grep -qx wasm32-unknown-unknown; then - echo "build-dashboard-wasm: the wasm32-unknown-unknown target is not installed." >&2 - echo " Install it with: rustup target add wasm32-unknown-unknown" >&2 - exit 1 -fi - -if ! command -v wasm-bindgen >/dev/null 2>&1; then - echo "build-dashboard-wasm: wasm-bindgen-cli is not installed." >&2 - echo " Install the version matching Cargo.lock ($locked_version) with:" >&2 - echo " cargo install wasm-bindgen-cli --version $locked_version --locked" >&2 - exit 1 -fi - -installed_version="$(wasm-bindgen --version | awk '{print $2}')" -if [ "$installed_version" != "$locked_version" ]; then - echo "build-dashboard-wasm: wasm-bindgen-cli $installed_version does not match Cargo.lock's wasm-bindgen $locked_version." >&2 - echo " wasm-bindgen and wasm-bindgen-cli speak a private ABI and must match exactly. Reinstall with:" >&2 - echo " cargo install wasm-bindgen-cli --version $locked_version --locked" >&2 - exit 1 -fi - -echo "=== cargo build: $crate_dir for wasm32-unknown-unknown ===" >&2 -cargo build -p didbot-site-anim --target wasm32-unknown-unknown --release - -wasm_in="target/wasm32-unknown-unknown/release/didbot_site_anim.wasm" -if [ ! -f "$wasm_in" ]; then - echo "build-dashboard-wasm: expected build output at $wasm_in, found nothing" >&2 - exit 1 -fi - -echo "=== wasm-bindgen: generating the JS glue in $out_dir ===" >&2 -rm -rf "$out_dir" -mkdir -p "$out_dir" -wasm-bindgen --target web --out-dir "$out_dir" --out-name site-anim "$wasm_in" +scripts/build-wasm.sh didbot-site-anim "$out_dir" site-anim rm -f "$out_dir"/*.d.ts - -if command -v wasm-opt >/dev/null 2>&1; then - echo "=== wasm-opt: shrinking the release binary ===" >&2 - wasm-opt -Oz -o "$out_dir/site-anim_bg.wasm.opt" "$out_dir/site-anim_bg.wasm" - mv "$out_dir/site-anim_bg.wasm.opt" "$out_dir/site-anim_bg.wasm" -else - echo "build-dashboard-wasm: wasm-opt not found on PATH; shipping the unoptimized binary." >&2 - echo " Install binaryen for a smaller artifact: https://github.com/WebAssembly/binaryen" >&2 -fi - -size_bytes="$(wc -c <"$out_dir/site-anim_bg.wasm")" -echo "build-dashboard-wasm: done — $out_dir/site-anim_bg.wasm is ${size_bytes} bytes" >&2 diff --git a/scripts/build-site.sh b/scripts/build-site.sh index c10241d3..bf22ca3a 100755 --- a/scripts/build-site.sh +++ b/scripts/build-site.sh @@ -66,7 +66,7 @@ echo "=== astro build: marketing pages + docs/ prose ===" >&2 echo "=== mounting the API docs under /api/ ===" >&2 rm -rf site/dist/api mkdir -p site/dist/api -cp -R target/doc/. site/dist/api/ +cp -R "${CARGO_TARGET_DIR:-target}/doc/." site/dist/api/ # `cargo doc --workspace` writes one directory per crate and no root # index.html — there is no single "workspace" page to land on. `didbot` is # the facade crate (see crates/didbot/src/lib.rs, which include_str!s all of diff --git a/scripts/build-wasm.sh b/scripts/build-wasm.sh index 49a3d4a5..a0b03c9d 100755 --- a/scripts/build-wasm.sh +++ b/scripts/build-wasm.sh @@ -1,15 +1,23 @@ #!/usr/bin/env bash -# Builds crates/didbot-site-anim for the browser and drops the result where -# Astro's public/ passthrough picks it up untouched: site/public/wasm/. Astro -# copies public/ verbatim into dist/, so nothing else has to know this ran. +# Builds one wasm-bindgen crate for the browser and drops the JS glue and the +# .wasm where a page serves them from. # -# This is its own script, called from scripts/build-site.sh, because it is -# the one step in that pipeline needing a toolchain the other two -# (`cargo doc`, `npm run build`) do not: the wasm32-unknown-unknown target -# and a wasm-bindgen-cli whose version matches the wasm-bindgen crate -# dependency exactly (the two talk a private ABI to each other; a mismatch -# fails loudly, which is the whole reason the version is pinned rather than -# "whatever is installed"). +# Usage: scripts/build-wasm.sh [crate out-dir out-name] +# +# With no arguments it builds crates/didbot-site-anim into site/public/wasm/ +# as site-anim.js + site-anim_bg.wasm, which is what scripts/build-site.sh +# calls it for: Astro's public/ passthrough copies that directory into dist/ +# untouched, so nothing else has to know this ran. The three arguments name +# another crate, output directory and output name, and are all given or none +# are; scripts/build-dashboard-wasm.sh and scripts/build-policy-wasm.sh are +# the other callers. +# +# This is its own script because it is the one step needing a toolchain the +# rest of the site build does not: the wasm32-unknown-unknown target and a +# wasm-bindgen-cli whose version matches the wasm-bindgen crate dependency +# exactly (the two talk a private ABI to each other; a mismatch fails loudly, +# which is the whole reason the version is pinned rather than "whatever is +# installed"). # # `cargo build --workspace` and `cargo test --workspace` never need this: the # wasm32 target is only touched here, on purpose (see @@ -19,8 +27,22 @@ set -euo pipefail cd "$(dirname "$0")/.." -crate_dir="crates/didbot-site-anim" -out_dir="site/public/wasm" +case "$#" in + 0) + crate="didbot-site-anim" + out_dir="site/public/wasm" + out_name="site-anim" + ;; + 3) + crate="$1" + out_dir="$2" + out_name="$3" + ;; + *) + echo "usage: $0 [crate out-dir out-name]" >&2 + exit 2 + ;; +esac locked_version="$( awk ' @@ -55,10 +77,10 @@ if [ "$installed_version" != "$locked_version" ]; then exit 1 fi -echo "=== cargo build: $crate_dir for wasm32-unknown-unknown ===" >&2 -cargo build -p didbot-site-anim --target wasm32-unknown-unknown --release +echo "=== cargo build: $crate for wasm32-unknown-unknown ===" >&2 +cargo build -p "$crate" --target wasm32-unknown-unknown --release -wasm_in="target/wasm32-unknown-unknown/release/didbot_site_anim.wasm" +wasm_in="${CARGO_TARGET_DIR:-target}/wasm32-unknown-unknown/release/${crate//-/_}.wasm" if [ ! -f "$wasm_in" ]; then echo "build-wasm: expected build output at $wasm_in, found nothing" >&2 exit 1 @@ -67,16 +89,16 @@ fi echo "=== wasm-bindgen: generating the JS glue in $out_dir ===" >&2 rm -rf "$out_dir" mkdir -p "$out_dir" -wasm-bindgen --target web --out-dir "$out_dir" --out-name site-anim "$wasm_in" +wasm-bindgen --target web --out-dir "$out_dir" --out-name "$out_name" "$wasm_in" if command -v wasm-opt >/dev/null 2>&1; then echo "=== wasm-opt: shrinking the release binary ===" >&2 - wasm-opt -Oz -o "$out_dir/site-anim_bg.wasm.opt" "$out_dir/site-anim_bg.wasm" - mv "$out_dir/site-anim_bg.wasm.opt" "$out_dir/site-anim_bg.wasm" + wasm-opt -Oz -o "$out_dir/${out_name}_bg.wasm.opt" "$out_dir/${out_name}_bg.wasm" + mv "$out_dir/${out_name}_bg.wasm.opt" "$out_dir/${out_name}_bg.wasm" else echo "build-wasm: wasm-opt not found on PATH; shipping the unoptimized binary." >&2 echo " Install binaryen for a smaller artifact: https://github.com/WebAssembly/binaryen" >&2 fi -size_bytes="$(wc -c <"$out_dir/site-anim_bg.wasm")" -echo "build-wasm: done — $out_dir/site-anim_bg.wasm is ${size_bytes} bytes" >&2 +size_bytes="$(wc -c <"$out_dir/${out_name}_bg.wasm")" +echo "build-wasm: done — $out_dir/${out_name}_bg.wasm is ${size_bytes} bytes" >&2 -- 2.51.2