skate3recomp-multiplayer/tools/release/release.sh
MiTHRAL 81189576c0 releases: harden for Windows + one-click windows-build.cmd launcher
Addresses the known Windows build issues (see /mnt/archive/Issues.txt):
- windows-build.cmd: loads vcvarsall with a stable Windows SDK (WINSDK,
  default 10.0.26100.0) fixing kernel32.lib LNK1104; sets
  MSYS2_ARG_CONV_EXCL=* so Git Bash does not corrupt %LIB%; inits submodules
  (including the broken-pin self-heal) before building.
- release.sh: auto-detect the Title Update package (repo root or game dir);
  zip fallback to 7z or PowerShell Compress-Archive (Git Bash has no zip);
  upload JSON parsing falls back from python3/python to grep (Git Bash ships
  neither python).
2026-08-27 14:02:24 -04:00

189 lines
No EOL
7.8 KiB
Bash
Executable file

#!/usr/bin/env bash
# Build a Skate 3 recomp release from this checkout and optionally publish it
# to a Forgejo/Gitea Release.
#
# IMPORTANT: the release zip contains ONLY the recompiled binaries
# (skate3 + librexruntime.so + ghost_relay + README) - NO game files. Players
# bring their own ISO and the in-app installer extracts it. The game dump
# (default.xex + data/webkit/EAWebkit.xex) is required at BUILD TIME only,
# because codegen translates the actual Xbox 360 binary into C++ source; it
# is never included in, or uploaded with, the release.
#
# Usage:
# ./tools/release/release.sh # build this platform, no upload
# ./tools/release/release.sh --tag v1.0.0 --upload # build + publish
# ./tools/release/release.sh --game-root /path/to/game --tu /path/to/TU_12K2276_...
#
# Options:
# --tag TAG release tag/version (default: last git tag or 'dev')
# --game-root DIR extracted game dump (default: $REPO/game)
# --tu FILE optional Title Update STFS package for codegen
# --os linux|windows|macos override platform (default: host OS)
# --cmake-args "..." extra flags appended to every cmake configure
# call (e.g. -DCMAKE_C_COMPILER=clang-22
# -DCMAKE_CXX_COMPILER=clang++-22
# -DCMAKE_LINKER=ld.lld on distros without clang-20)
# --upload publish the zip to a Forgejo Release
#
# Env for --upload:
# GITEA_TOKEN Forgejo token with write:repository (release) scope
# FORGEJO_REPO default "ad3laid3/skate3recomp-multiplayer"
# FORGEJO_INSTANCE default "https://git.mithraic.cloud"
set -euo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd "$REPO"
UPLOAD=0
TAG=""
GAME_ROOT="${SKATE3_GAME_DATA_ROOT:-$REPO/game}"
TU="${SKATE3_TITLE_UPDATE_PACKAGE:-}"
OS_ARG=""
CMAKE_ARGS=""
while [ $# -gt 0 ]; do
case "$1" in
--tag) TAG="${2:?--tag needs a value}"; shift 2;;
--game-root) GAME_ROOT="$2"; shift 2;;
--tu) TU="$2"; shift 2;;
--os) OS_ARG="$2"; shift 2;;
--cmake-args) CMAKE_ARGS="$2"; shift 2;;
--upload) UPLOAD=1; shift;;
-h|--help)
sed -n '2,32p' "$0"; exit 0;;
*) echo "unknown argument: $1"; exit 2;;
esac
done
# ---- platform ---------------------------------------------------------------
UNAME_S="$(uname -s 2>/dev/null || echo Windows)"
case "${OS_ARG:-$UNAME_S}" in
linux|Linux) PRESET="linux-relwithdebinfo"; BIN="skate3"; LIB="librexruntime.so"; EXT="Linux";;
windows|Windows|MINGW*|MSYS*|CYGWIN*)
PRESET="relwithdebinfo"; BIN="skate3.exe"; LIB="librexruntime.dll"; EXT="Windows";;
macos|macOS|Darwin) PRESET="macos-relwithdebinfo"; BIN="skate3"; LIB="librexruntime.dylib"; EXT="macOS";;
*) echo "unsupported platform: ${OS_ARG:-$UNAME_S} (set --os linux|windows|macos)"; exit 2;;
esac
if [ -z "$TAG" ]; then
TAG="$(git describe --tags --always 2>/dev/null || echo dev)"
fi
VER="${TAG#v}"
NAME="Skate3Recomp-$EXT-$VER"
if [ ! -f "$GAME_ROOT/default.xex" ]; then
echo "ERROR: game dump not found at $GAME_ROOT (need default.xex + data/webkit/EAWebkit.xex)"
echo " It is required for codegen; it is NOT shipped in the release."
exit 1
fi
# ---- helpers (Windows Git Bash lacks zip/python; provide fallbacks) ---------
json_id() { # read JSON on stdin, print the value of "id"
if command -v python3 >/dev/null 2>&1; then
python3 -c "import sys,json
try: print(json.load(sys.stdin).get('id',''))
except Exception: print('')"
elif command -v python >/dev/null 2>&1; then
python -c "import sys,json
try: print(json.load(sys.stdin).get('id',''))
except Exception: print('')"
else
grep -o '"id":[0-9]*' | head -1 | cut -d: -f2
fi
}
make_zip() { # make_zip <zipname> <dir>
if command -v zip >/dev/null 2>&1; then
(cd "$(dirname "$2")" && zip -r "$(basename "$1")" "$(basename "$2")")
elif command -v 7z >/dev/null 2>&1; then
7z a -tzip "$1" "$2" >/dev/null
elif command -v powershell >/dev/null 2>&1; then
powershell -NoProfile -Command "Compress-Archive -Path '$2' -DestinationPath '$1' -Force"
else
echo "ERROR: no zip tool found (install zip, 7z, or use PowerShell)"; exit 1
fi
}
# ---- build ------------------------------------------------------------------
TU_ARGS=""
if [ -n "$TU" ]; then
if [ ! -f "$TU" ]; then echo "ERROR: title update package not found: $TU"; exit 1; fi
TU_ARGS="-DSKATE3_TITLE_UPDATE_PACKAGE=$TU"
elif [ -n "$(ls "$REPO"/TU_12K2276_* "$GAME_ROOT"/TU_12K2276_* 2>/dev/null | head -1)" ]; then
TU="$(ls "$REPO"/TU_12K2276_* "$GAME_ROOT"/TU_12K2276_* 2>/dev/null | head -1)"
echo "==> Using title update package: $TU"
TU_ARGS="-DSKATE3_TITLE_UPDATE_PACKAGE=$TU"
fi
echo "==> Release $TAG ($EXT) preset=$PRESET game=$GAME_ROOT"
echo "==> Configure"
cmake --preset "$PRESET" -DSKATE3_GAME_DATA_ROOT="$GAME_ROOT" $TU_ARGS $CMAKE_ARGS
echo "==> Generate recompiled code"
cmake --build --preset "$PRESET" --target generate-all --parallel
echo "==> Reconfigure (generated sources)"
cmake --preset "$PRESET" -DSKATE3_GAME_DATA_ROOT="$GAME_ROOT" $TU_ARGS $CMAKE_ARGS
echo "==> Build"
cmake --build --preset "$PRESET" --parallel
# ---- package ---------------------------------------------------------------
OUT="out/build/$PRESET"
STAGE="$NAME"
rm -rf "$STAGE"; mkdir -p "$STAGE"
cp "$OUT/$BIN" "$STAGE/"
# The rexglue runtime lib carries a config suffix (librexruntimerd.so for
# relwithdebinfo, librexruntime.so for release); the binary links whichever
# was built, so ship it under its real name.
RUNTIME="$(ls "$OUT"/librexruntime*.so "$OUT"/librexruntime*.dll "$OUT"/librexruntime*.dylib 2>/dev/null | head -1 || true)"
if [ -n "$RUNTIME" ]; then
cp "$RUNTIME" "$STAGE/"
fi
cp "$OUT/ghost_relay" "$STAGE/" 2>/dev/null || true
cp "$OUT/ghost_relay.exe" "$STAGE/" 2>/dev/null || true
# Title-update patches staged next to the binary when the build used the TU
if [ -f "$OUT/game/default.xexp" ]; then
mkdir -p "$STAGE/game/data/webkit"
cp "$OUT/game/default.xexp" "$STAGE/game/"
cp "$OUT/game/data/webkit/EAWebkit.xexp" "$STAGE/game/data/webkit/" 2>/dev/null || true
fi
cp README.md "$STAGE/"
rm -f "$NAME.zip"
make_zip "$NAME.zip" "$STAGE"
rm -rf "$STAGE"
echo "==> Packaged: $NAME.zip ($(du -h "$NAME.zip" | cut -f1))"
sha256sum "$NAME.zip"
# ---- publish ----------------------------------------------------------------
if [ "$UPLOAD" = 1 ]; then
: "${GITEA_TOKEN:?--upload needs GITEA_TOKEN}"
REPO_FULL="${FORGEJO_REPO:-ad3laid3/skate3recomp-multiplayer}"
INSTANCE="${FORGEJO_INSTANCE:-https://git.mithraic.cloud}"
AUTH="Authorization: token $GITEA_TOKEN"
echo "==> Publishing $NAME.zip to $INSTANCE/$REPO_FULL release '$TAG'"
RELEASE_ID="$(curl -s -X POST "$INSTANCE/api/v1/repos/$REPO_FULL/releases" \
-H "$AUTH" -H "Content-Type: application/json" \
-d "{\"tag_name\":\"$TAG\",\"name\":\"Skate 3 Recomp $TAG\",\"target_commitish\":\"main\"}" \
| json_id)"
if [ -z "$RELEASE_ID" ]; then
RELEASE_ID="$(curl -s "$INSTANCE/api/v1/repos/$REPO_FULL/releases/tags/$TAG" -H "$AUTH" \
| json_id)"
fi
if [ -z "$RELEASE_ID" ]; then
echo "ERROR: could not create/find release '$TAG'"; exit 1
fi
curl -s -X POST "$INSTANCE/api/v1/repos/$REPO_FULL/releases/$RELEASE_ID/assets" \
-H "$AUTH" -F "attachment=@$NAME.zip" -F "name=$NAME.zip" \
| if command -v python3 >/dev/null 2>&1 || command -v python >/dev/null 2>&1; then
PY=python3; command -v python3 >/dev/null 2>&1 || PY=python
"$PY" -c "import sys,json
try:
a=json.load(sys.stdin); print('Uploaded asset', a.get('name'), a.get('size'), 'bytes')
except Exception as e: print('upload response parse failed:', e)"
else
echo "Upload request sent (no python to parse the response)"
fi
echo "==> Done: https://git.mithraic.cloud/$REPO_FULL/releases/tag/$TAG"
fi