Every command line resolves through the catalogue (wai_cli/door.rs): its CLI spelling, an alias, or its mechanical form wai <noun> <verb>; an implementation is found by operation id, and help is written from the catalogue's entries. dx::VERBS is the developer path's view of it. Every command keeps the agent rules (wai_cli/agent.rs): exit codes 0 to 7, --json (a versioned envelope, envelope/1, carrying a command's own JSON or its text in data), --dry-run on every operation that is not read-only (every write goes through wai_cli/out.rs), and --yes where a change waits for confirmation (exit 4 off a terminal). wai ops list, search, schema and export. The tests and the quickstart's packaging check read the JSON forms from the envelope's data. Co-Authored-By: Claude Opus 5.5 <[email protected]>
98 lines
5.3 KiB
Shell
Executable file
98 lines
5.3 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
# The quickstart archive: the `wai` command line and what `wai dev` runs, for one target.
|
|
#
|
|
# bash wai/quickstart/build.sh <out-dir> --web <dir> [--target <triple>] [--version <v>]
|
|
#
|
|
# Builds, each release and --locked, each from its own workspace:
|
|
# wai wai/wai-rs, --no-default-features --features quickstart: the mandatory
|
|
# floor, hello, create, dev and verify; no system codec library
|
|
# wai-relay the relay (crate joule-moq-relay, joule-code/joule-code-rs)
|
|
# wai-room the room service (crate joule-moq-room)
|
|
# wai-remote-host a remote desktop room's host agent
|
|
# wai-pack the packager
|
|
# and writes <out-dir>/wai-<version>-<triple>.tar.gz holding bin/ (those five), share/wai/web/
|
|
# (the room client, from --web: bash wai/quickstart/build-web.sh makes it), README.md and
|
|
# LICENSE, with <archive>.sha256 beside it in the form `shasum -a 256 -c` reads. The version
|
|
# is wai/wai-rs's unless given; the triple is the host's unless given. Extra cargo flags for
|
|
# the target (a linker, static linking) come from the environment, as cargo reads them.
|
|
set -euo pipefail
|
|
usage() { echo "usage: bash wai/quickstart/build.sh <out-dir> --web <dir> [--target <triple>] [--version <v>]" >&2; exit 2; }
|
|
[ $# -ge 3 ] || usage
|
|
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
|
|
OUT=$(mkdir -p "$1" && cd "$1" && pwd); shift
|
|
WEBDIR="" TRIPLE="" VERSION=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--web) WEBDIR="$2"; shift 2 ;;
|
|
--target) TRIPLE="$2"; shift 2 ;;
|
|
--version) VERSION="$2"; shift 2 ;;
|
|
*) usage ;;
|
|
esac
|
|
done
|
|
[ -n "$WEBDIR" ] && [ -f "$WEBDIR/room/index.html" ] && [ -f "$WEBDIR/pkg/wai_live_web_bg.wasm" ] && [ -f "$WEBDIR/pkg/joule_moq_web_bg.wasm" ] \
|
|
|| { echo "--web: a directory build-web.sh made (room/, moq/, pkg/)" >&2; exit 2; }
|
|
HOST=$(rustc -vV | sed -n 's/^host: //p')
|
|
TRIPLE=${TRIPLE:-$HOST}
|
|
VERSION=${VERSION:-$(sed -n 's/^version = "\(.*\)"$/\1/p' "$ROOT/wai/wai-rs/Cargo.toml" | head -1)}
|
|
EXE=""; case "$TRIPLE" in *windows*) EXE=".exe" ;; esac
|
|
TGT=(--target "$TRIPLE")
|
|
|
|
build() { # <dir> <binary> <cargo args...>: the binary's path, or a failure
|
|
local dir="$1" bin="$2"; shift 2
|
|
(
|
|
# Under a target directory shared by every workspace (CARGO_TARGET_DIR), each build gets its
|
|
# own: wai also builds as a cdylib, so its rlib's file name carries no hash, and a second
|
|
# feature set of it (the room service's) would overwrite the first in one directory.
|
|
if [ -n "${CARGO_TARGET_DIR:-}" ]; then export CARGO_TARGET_DIR="$CARGO_TARGET_DIR/quickstart-$bin"; fi
|
|
cd "$dir"
|
|
cargo build --locked --release "${TGT[@]}" "$@" >&2 || exit 1
|
|
t=$(cargo metadata --format-version 1 --no-deps --locked | python3 -c 'import json,sys; print(json.load(sys.stdin)["target_directory"])') || exit 1
|
|
echo "$t/$TRIPLE/release/$bin$EXE"
|
|
)
|
|
}
|
|
need() { # <binary> <cargo args...>: copied into the stage, or the script stops
|
|
local b
|
|
b=$(build "$@") || { echo "build.sh: the build of $2 failed" >&2; exit 1; }
|
|
cp "$b" "$STAGE/$NAME/bin/"
|
|
}
|
|
|
|
NAME="wai-$VERSION-$TRIPLE"
|
|
STAGE=$(mktemp -d)
|
|
trap 'rm -rf "$STAGE"' EXIT
|
|
mkdir -p "$STAGE/$NAME/bin" "$STAGE/$NAME/share/wai"
|
|
need "$ROOT/wai/wai-rs" wai --no-default-features --features quickstart --bin wai
|
|
need "$ROOT/joule-code/joule-code-rs" wai-relay -p joule-moq-relay --bin wai-relay
|
|
need "$ROOT/joule-code/joule-code-rs/crates/joule-moq-room" wai-room --bin wai-room
|
|
need "$ROOT/joule-code/joule-code-rs/crates/joule-moq-remote" wai-remote-host --bin wai-remote-host
|
|
need "$ROOT/wai/wai-pack" wai-pack --bin wai-pack
|
|
cp -R "$WEBDIR" "$STAGE/$NAME/share/wai/web"
|
|
cp "$ROOT/wai/quickstart/README.md" "$STAGE/$NAME/README.md"
|
|
cp "$ROOT/wai/LICENSE" "$STAGE/$NAME/LICENSE"
|
|
chmod 755 "$STAGE/$NAME"/bin/*
|
|
# Each binary runs before it is packaged, where it can run here.
|
|
# The wai packaged must hold this checkout's examples, file for file and byte for byte: a stale
|
|
# binary would ship templates from another commit.
|
|
if [ "$TRIPLE" = "$HOST" ]; then
|
|
"$STAGE/$NAME/bin/wai-pack$EXE" fixture list > /dev/null
|
|
python3 - "$STAGE/$NAME/bin/wai$EXE" "$ROOT/wai/examples" <<'PY' || { echo "build.sh: the packaged wai does not hold this checkout's examples" >&2; exit 1; }
|
|
import json, os, subprocess, sys, tempfile
|
|
wai, ex = sys.argv[1], sys.argv[2]
|
|
with tempfile.TemporaryDirectory() as d:
|
|
for t in json.loads(subprocess.check_output([wai, "create", "--list", "--json"]))["data"]:
|
|
out = os.path.join(d, t["template"])
|
|
subprocess.check_output([wai, "create", out, "--template", t["template"]])
|
|
for f in t["files"]:
|
|
src = os.path.join(ex, t["template"], f)
|
|
if os.path.exists(src) and open(src, "rb").read() != open(os.path.join(out, f), "rb").read():
|
|
sys.exit(f"{t['template']}/{f} differs")
|
|
PY
|
|
fi
|
|
mkdir -p "$OUT"
|
|
# The same bytes for the same inputs: sorted names, fixed owner and times.
|
|
if tar --version 2>/dev/null | grep -q GNU; then
|
|
tar --sort=name --owner=0 --group=0 --numeric-owner --mtime='2026-01-01 00:00Z' -C "$STAGE" -cf - "$NAME" | gzip -n -9 > "$OUT/$NAME.tar.gz"
|
|
else
|
|
tar -C "$STAGE" -cf - "$NAME" | gzip -n -9 > "$OUT/$NAME.tar.gz"
|
|
fi
|
|
( cd "$OUT" && { command -v sha256sum >/dev/null && sha256sum "$NAME.tar.gz" || shasum -a 256 "$NAME.tar.gz"; } > "$NAME.tar.gz.sha256" )
|
|
echo "packaged $OUT/$NAME.tar.gz ($(cut -d' ' -f1 "$OUT/$NAME.tar.gz.sha256"), $(du -h "$OUT/$NAME.tar.gz" | cut -f1))"
|