#!/usr/bin/env bash # Compila roguelikes de Stephen Sherratt (gridbugs, MIT; Rust -> WebAssembly) a partir do fonte, num commit fixo: # cargo build --locked --release --target wasm32-unknown-unknown -p (Cargo.lock do autor) # wasm-bindgen --target web --no-typescript (CLI na versao do Cargo.lock) # O autor empacota com wasm-pack + webpack; aqui sao os mesmos dois passos sem o webpack, e a pagina # (gridbugs/index.html.in) e nossa: CSP que bloqueia conexoes fora da origem, localStorage com prefixo e ajuste # da grade ao quadro. As fontes PxPlus IBM CGA (VileR, CC BY-SA 4.0) vem do static_web/ do jogo, sem mudanca. # Get Well Soon e Meters Below the Ground (2018/2019) sao mais antigos: Rust 1.58.1, wasm-bindgen 0.2.53 / 0.2.33 # (binarios x86_64, rodam no Rosetta) com --no-modules, e a parte JavaScript (biblioteca prototty, MIT, do mesmo # autor) vem do npm nas versoes do package-lock.json do jogo, sem webpack: um import map liga os modulos. O # prototty_storage (IndexedDB via localforage) e trocado por gridbugs/prototty_storage.js (mesma API, localStorage). # O Meters nao tem Cargo.lock: gridbugs/meters-cargo-lock.patch traz um gerado com "cargo generate-lockfile # --publish-time 2019-02-04" (data do commit) e tira o glutin/unix do workspace (nao entram no .wasm). # # src/FredGames.Bundler/Builds/build-gridbugs-games.sh [slug ...] (sem argumento: todos) # # CODEGEN_UNITS=1: com varias unidades o rustc nao gera sempre os mesmos bytes (ids de funcoes mudam). # Rust e wasm-bindgen ficam em artifacts/tools/. Saida de cada jogo: artifacts/build//{dist/, # -dist.tar.gz, -licenses.txt}; o .tar.gz tem que sair igual em dois builds seguidos. set -euo pipefail here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" root="$(git -C "$here" rev-parse --show-toplevel 2>/dev/null || pwd)" cache="$root/artifacts/build/cache" tools="$root/artifacts/tools" mkdir -p "$cache" export RUSTUP_HOME="$tools/rustup" CARGO_HOME="$tools/cargo" export PATH="$CARGO_HOME/bin:$PATH" if [ ! -x "$CARGO_HOME/bin/rustup" ]; then curl -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --profile minimal --default-toolchain none fi fetch() { if [ ! -f "$cache/$2" ]; then curl -fsSL --retry 4 "$1" -o "$cache/$2.partial" && mv "$cache/$2.partial" "$cache/$2" fi echo "$3 $cache/$2" | shasum -a 256 -c - >/dev/null } # Por jogo: REPO COMMIT SHA256 TOOLCHAIN WB WB_ARCH WB_SHA CRATE TITLE COLS ROWS FS CW CH FONT_THIN FONT_BOLD (+ PATCH opcional) load() { PATCH="" KIND=chargrid WEBDIR=web NPM="" NPM_SHA="" SEED="" case "$1" in electric-organ) REPO=electric-organ COMMIT=6e5af917252d890e63b092c95fbdaec81d815af8 SHA256=fe1a0a08c1ddff8e3a818200dae09cdd9302376f1a50a1f6a42b554d28fda3ce TOOLCHAIN=1.92.0 WB=0.2.108 WB_ARCH=aarch64-apple-darwin WB_SHA=3903c81dc8943592dfd9d98c8c21c9a05f8265aa6b0014f641a8457cec4925dd CRATE=frontend_web TITLE="Electric Organ" COLS=80 ROWS=30 FS=24 CW=12 CH=24 FONT_THIN=PxPlus_IBM_CGAthin-2y.ttf FONT_BOLD=PxPlus_IBM_CGA-2y.ttf ;; boat-journey) REPO=boat-journey COMMIT=ec0629136efd42a6a581299a7f5210777b6ec18d SHA256=e719a4607729e2b056bb4c77f55dda54fb909fa52415205a17f0c66b31cbf072 TOOLCHAIN=1.74.1 WB=0.2.86 WB_ARCH=aarch64-apple-darwin WB_SHA=11b0cdb01c2c1d5bc82b3a064a5e59adb972d69e80bc61c64c9f38b7f046440f CRATE=boat_journey_web TITLE="Boat Journey" COLS=80 ROWS=60 FS=16 CW=16 CH=16 FONT_THIN=PxPlus_IBM_CGAthin-with-quadrant-blocks.ttf FONT_BOLD=PxPlus_IBM_CGA-with-quadrant-blocks.ttf ;; road-closed) REPO=road-closed COMMIT=74a9c9de92e6ac2626907fd42be8c186d72d83a5 SHA256=86405e203089a351d746f9831d2c75867ce6c1db6ce900ce0420e6fc527e64a3 TOOLCHAIN=1.92.0 WB=0.2.114 WB_ARCH=aarch64-apple-darwin WB_SHA=b0ef565865b3004bca5df72c83fef9256fa059e7aaa9075493f4e392b1d17350 CRATE=frontend_web TITLE="Road Closed" COLS=80 ROWS=30 FS=24 CW=12 CH=24 FONT_THIN=PxPlus_IBM_CGAthin-2y.ttf FONT_BOLD=PxPlus_IBM_CGA-2y.ttf PATCH=road-closed-wishes-key.patch ;; rain-forest) REPO=rainforest COMMIT=152afd18645094758374db6c7cbb48adae0b2c58 SHA256=ddadc79a28a29d5b46cfb900bfce96879a906152576d204f694f19679582f9ee TOOLCHAIN=1.92.0 WB=0.2.95 WB_ARCH=aarch64-apple-darwin WB_SHA=7d924ae562494e7bbdd81ce673ebdcfd1b343d0b00850587035a85bbbaf0ab7c CRATE=rainforest_web TITLE="Rain Forest" COLS=80 ROWS=60 FS=24 CW=24 CH=24 FONT_THIN=PxPlus_IBM_CGAthin-custom.ttf FONT_BOLD=PxPlus_IBM_CGA-custom.ttf PATCH=rainforest-web-gridbugs-0.7.patch ;; get-well-soon) REPO=gws COMMIT=572761ac06ef57b6cabfc5ae06a55c555f836e5a SHA256=0b33cc50831dc1b49230cf04b96d4fc453510424175b9f60c623f43d7052e3e4 TOOLCHAIN=1.58.1 WB=0.2.53 WB_ARCH=x86_64-apple-darwin WB_SHA=acf53a2a028e0d7fd093d81e19718f75b03de94ed6b30ebeb94074a1c65a66ce CRATE=gws_wasm TITLE="Get Well Soon" KIND=prototty WEBDIR=wasm COLS=74 ROWS=58 CW=16 CH=16 FS=16 SEED= FONT_THIN=PxPlus_IBM_CGAthin.ttf FONT_BOLD=PxPlus_IBM_CGA.ttf NPM="prototty-0.2.0 prototty_input-0.2.0 prototty_render-0.2.0" NPM_SHA="yeCnxgafTJX2VXJwBM5icWHndxFFO4i6k4wbqhBZZgitFoUugsFFooOY5uTKzaziSDoBCG8A49Q2vVd4M9u6Ug== QWdiBGJcRBATQu5vnhjaIGWXosrCs46bMXG2GuNo986ZqMYhhPpM8FqcDei9lF4qSxtEsLYGRWx0i7mjHYawdg== mim7wmS2KUVIIBXMndeD/HvhU+xBEUspV8r3G23hd3nJG+vWae3XNNw30QI22Cu7oImPiSAN1Jjvh1y0OU4gMA==" ;; meters-below-the-ground) REPO=meters-below-the-ground COMMIT=6f4be80b4511a6fd8409fdff1816f76b4aa40a05 SHA256=1b853e11688b632d5b2e07ba4560694660e9b66fe8b4cc983801a7e28cbf0db6 TOOLCHAIN=1.58.1 WB=0.2.33 WB_ARCH=x86_64-apple-darwin WB_SHA=2d9884dc5dfbc163bc3bb9a077dfb7eabdf2367e84ef9188e10cff8bb148d392 CRATE=meters_wasm TITLE="Meters Below the Ground" KIND=prototty WEBDIR=wasm COLS=60 ROWS=45 CW=16 CH=18 FS=16 SEED="rngSeed(), " FONT_THIN=PxPlus_IBM_CGAthin.ttf FONT_BOLD=PxPlus_IBM_CGA.ttf NPM="prototty-0.1.1 prototty_input-0.1.0 prototty_render-0.1.1" NPM_SHA="1+Fbfgo4HUPzyc/TDOt98kwuADke6Gwn07tzUaaPrdpM8VsVmJKhtY8HY3QbmkVoxMZAcgrServi8sXRaIg65A== e0H8a/e2tYLboVc6tpledrFLeoUSirq3RdURs8toljBHLUY1cNZojAUM68RU701Oz6xmYcYNkoI0gXhet+KGOg== MSvldvdWBowMadl1UC6vKwgTiefCztn8RFZullkyIUO1CAizmAp5rlXpuirJPMwp76XYJD0St53d8TdIISTBZg==" PATCH=meters-cargo-lock.patch ;; *) echo "jogo desconhecido: $1" >&2; exit 1 ;; esac } build() { local slug="$1" load "$slug" local out="$root/artifacts/build/$slug" tree="$root/artifacts/build/$slug/tree" fetch "https://github.com/gridbugs/$REPO/archive/$COMMIT.tar.gz" "$slug-${COMMIT:0:7}.tar.gz" "$SHA256" fetch "https://github.com/rustwasm/wasm-bindgen/releases/download/$WB/wasm-bindgen-$WB-$WB_ARCH.tar.gz" \ "wasm-bindgen-$WB-$WB_ARCH.tar.gz" "$WB_SHA" if [ ! -x "$tools/wasm-bindgen-$WB/wasm-bindgen" ]; then rm -rf "$tools/wasm-bindgen-$WB.tmp"; mkdir -p "$tools/wasm-bindgen-$WB.tmp" tar -xzf "$cache/wasm-bindgen-$WB-$WB_ARCH.tar.gz" -C "$tools/wasm-bindgen-$WB.tmp" --strip-components 1 mv "$tools/wasm-bindgen-$WB.tmp" "$tools/wasm-bindgen-$WB" fi rustup toolchain install "$TOOLCHAIN" --profile minimal --target wasm32-unknown-unknown >/dev/null 2>&1 export RUSTUP_TOOLCHAIN="$TOOLCHAIN" rm -rf "$out"; mkdir -p "$tree" "$out/dist" tar -xzf "$cache/$slug-${COMMIT:0:7}.tar.gz" -C "$tree" --strip-components 1 if [ -n "$PATCH" ]; then patch -s -p1 -d "$tree" < "$here/gridbugs/$PATCH"; fi ( cd "$tree" CARGO_INCREMENTAL=0 CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ RUSTFLAGS="--remap-path-prefix=$tree=/src --remap-path-prefix=$CARGO_HOME=/cargo" \ cargo build --locked --release --target wasm32-unknown-unknown -p "$CRATE" 2> "$out/cargo.log" \ || { tail -40 "$out/cargo.log"; exit 1; } if [ "$KIND" = prototty ]; then mkdir -p "$out/bg" "$tools/wasm-bindgen-$WB/wasm-bindgen" --no-modules --out-name app --out-dir "$out/bg" \ "target/wasm32-unknown-unknown/release/$CRATE.wasm" cp "$out/bg/app.js" "$out/bg/app_bg.wasm" "$out/dist/"; rm -rf "$out/bg" else "$tools/wasm-bindgen-$WB/wasm-bindgen" --target web --no-typescript --out-name game --out-dir "$out/dist" \ "target/wasm32-unknown-unknown/release/$CRATE.wasm" fi cargo metadata --locked --format-version 1 --filter-platform wasm32-unknown-unknown 2>/dev/null \ | python3 -I "$here/gridbugs/rust-licenses.py" "$CRATE" "$out/crates.txt" ) cp "$tree/$WEBDIR/static_web/$FONT_THIN" "$tree/$WEBDIR/static_web/$FONT_BOLD" "$out/dist/" tpl="$here/gridbugs/index.html.in" npm_note="" if [ "$KIND" = prototty ]; then tpl="$here/gridbugs/index-prototty.html.in" mkdir -p "$out/dist/npm" "$out/dist/js" cp "$here/gridbugs/prototty_storage.js" "$out/dist/js/" local pkgs=($NPM) sums=($NPM_SHA) i for i in "${!pkgs[@]}"; do local name="${pkgs[$i]%-*}" tgz="${pkgs[$i]}.tgz" if [ ! -f "$cache/npm-$tgz" ]; then curl -fsSL --retry 4 "https://registry.npmjs.org/$name/-/$tgz" -o "$cache/npm-$tgz.partial" && mv "$cache/npm-$tgz.partial" "$cache/npm-$tgz" fi [ "$(openssl dgst -sha512 -binary "$cache/npm-$tgz" | base64 | tr -d '\n')" = "${sums[$i]}" ] || { echo "sha512 de $tgz nao confere"; exit 1; } mkdir -p "$out/dist/npm/$name" "$out/npm-tmp" tar -xzf "$cache/npm-$tgz" -C "$out/npm-tmp" --strip-components 1 cp "$out/npm-tmp/index.js" "$out/npm-tmp/package.json" "$out/dist/npm/$name/"; rm -rf "$out/npm-tmp" done npm_note="The npm packages prototty, prototty_input and prototty_render (MIT, Stephen Sherratt; package.json says \"license\": \"MIT\") are served unchanged; the MIT text above covers them." fi sed -e "s/@TITLE@/$TITLE/g" -e "s/@SLUG@/$slug/g" -e "s/@GRID_W@/$((COLS * CW))/g" -e "s/@GRID_H@/$((ROWS * CH))/g" \ -e "s/@FS@/$FS/g" -e "s/@FONT_THIN@/$FONT_THIN/g" -e "s/@FONT_BOLD@/$FONT_BOLD/g" \ -e "s/@SEED@/$SEED/g" -e "s/@COLS@/$COLS/g" -e "s/@ROWS@/$ROWS/g" -e "s/@CW@/$CW/g" -e "s/@CH@/$CH/g" \ "$tpl" > "$out/dist/index.html" { echo "== $slug (LICENSE of the repository, original text)"; cat "$tree/LICENSE"; echo [ -z "$npm_note" ] || { echo "$npm_note"; echo; } cat "$out/crates.txt"; } > "$out/$slug-licenses.txt" find "$out/dist" -exec touch -t 202610300000 {} + ( cd "$out" && find dist -type f | LC_ALL=C sort > files.txt \ && COPYFILE_DISABLE=1 tar --format=ustar --uid 0 --gid 0 --uname root --gname root -n -cf - -T files.txt \ | gzip -n -9 > "$slug-dist.tar.gz" && rm files.txt ) rm -rf "$tree" "$out/crates.txt" ls -l "$out/$slug-dist.tar.gz" shasum -a 256 "$out/$slug-dist.tar.gz" "$out/$slug-licenses.txt" } games=("$@") [ ${#games[@]} -gt 0 ] || games=(electric-organ boat-journey road-closed rain-forest get-well-soon meters-below-the-ground) for g in "${games[@]}"; do build "$g"; done