#!/usr/bin/env bash # The package a site serves under /wai/pkg-vector/: the sink of wai.graphics.vector as # one WebAssembly module, wai_vector.wasm, which a page instantiates with no imports # and no glue script. # # bash wai/wai-vector/wasm/build-pkg.sh [] # # Writes /wai_vector.wasm (default wai/wai-vector/wasm/dist/pkg-vector, which # git ignores) and prints its size and SHA-256. # # The module is WebAssembly 1.0 and nothing later: no SIMD, no threads, no bulk # memory, no sign-extension operators, no saturating conversions, no reference types, # no multi-value. That is enforced twice. # # 1. By the target. The module is built for wasm32v1-none, whose precompiled core # and alloc are themselves WebAssembly 1.0. Those of wasm32-unknown-unknown are # not: they use bulk memory, sign extension and reference types, and the linker # carries what they use into any module linked against them, whatever # -C target-cpu or -C target-feature the build passes. That target has no std, so # the crate is no_std with its own allocator (src/heap.rs). # 2. By reading the result. check-mvp.mjs decodes the module that was built: every # section, type, segment and instruction must be 1.0's; and, as a package, it # must have no imports, no exported function with a 64-bit parameter or result, # no floating point, and exactly the exported functions listed below. The build # fails otherwise, and leaves no module in . # # The crate is built without its default feature, so the module has the sink's # exports and not the recomputation of the conformance vectors. # # The same source gives different module bytes on different hosts, so the SHA-256 # printed here names this build and not the source. What every host's build has in # common is what it computes: the frames of wai/vector-conformance, checked in three # browser engines by wai/wai-vector/browser/run.mjs. # # Needs bash, cargo with the wasm32v1-none target (rustup target add wasm32v1-none) # and node >= 18. set -euo pipefail if [ $# -gt 1 ]; then echo "usage: bash build-pkg.sh []" >&2 exit 2 fi CRATE="$(cd "$(dirname "$0")" && pwd -P)" OUT="${1:-$CRATE/dist/pkg-vector}" # The package's exported functions. A function added to the sink is added here. FUNCTIONS=wv_add_set,wv_alloc,wv_close,wv_cost,wv_free,wv_open,wv_out_len,wv_out_ptr,wv_projection,wv_render,wv_sha256,wv_transcript for t in cargo node; do command -v "$t" >/dev/null || { echo "pkg-vector: needs $t" >&2; exit 1; } done mkdir -p "$OUT" OUT="$(cd "$OUT" && pwd -P)" rm -f "$OUT/wai_vector.wasm" cd "$CRATE" # Asked of the toolchain this crate builds with, before anything is built. LIBDIR="$(rustc --print target-libdir --target wasm32v1-none 2>/dev/null || true)" if [ -z "$LIBDIR" ] || [ ! -d "$LIBDIR" ]; then echo "pkg-vector: this toolchain has no wasm32v1-none target (rustup target add wasm32v1-none)" >&2 exit 1 fi cargo build --locked --release --target wasm32v1-none --no-default-features TARGET_DIR="$(cargo metadata --locked --format-version 1 --no-deps \ | node -e 'let s = ""; process.stdin.on("data", (d) => { s += d; }).on("end", () => console.log(JSON.parse(s).target_directory));')" BUILT="$TARGET_DIR/wasm32v1-none/release/wai_vector_wasm.wasm" [ -f "$BUILT" ] || { echo "pkg-vector: the build left no $BUILT" >&2; exit 1; } node "$CRATE/check-mvp.mjs" "$BUILT" --package --functions "$FUNCTIONS" cp "$BUILT" "$OUT/wai_vector.wasm" echo "pkg-vector: $OUT/wai_vector.wasm"