You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.1 KiB
136 lines
4.1 KiB
#!/usr/bin/env bash |
|
set -euo pipefail |
|
|
|
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd) |
|
DIST_DIR="${DIST_DIR:-$ROOT_DIR/dist}" |
|
APPDIR="${APPDIR:-$DIST_DIR/AppDir}" |
|
APP_NAME="Mice" |
|
APP_ID="mice" |
|
ARCH_EXPECTED="aarch64" |
|
APPIMAGETOOL_BIN="${APPIMAGETOOL_BIN:-appimagetool}" |
|
PYTHON_BIN="${PYTHON_BIN:-python3}" |
|
OUTPUT_APPIMAGE="${OUTPUT_APPIMAGE:-$DIST_DIR/${APP_NAME}-${ARCH_EXPECTED}.AppImage}" |
|
|
|
PYTHON_DIR="$APPDIR/usr/opt/python" |
|
GAME_DIR="$APPDIR/usr/share/mice" |
|
LIB_DIR="$APPDIR/usr/lib" |
|
|
|
require_command() { |
|
if ! command -v "$1" >/dev/null 2>&1; then |
|
printf 'Missing required command: %s\n' "$1" >&2 |
|
exit 1 |
|
fi |
|
} |
|
|
|
find_system_library() { |
|
local soname="$1" |
|
ldconfig -p | awk -v target="$soname" '$1 == target { print $NF; exit }' |
|
} |
|
|
|
should_bundle_soname() { |
|
case "$1" in |
|
linux-vdso.so.*|libc.so.*|libm.so.*|libpthread.so.*|libdl.so.*|librt.so.*|libutil.so.*|libresolv.so.*|ld-linux*.so.*) |
|
return 1 |
|
;; |
|
*) |
|
return 0 |
|
;; |
|
esac |
|
} |
|
|
|
copy_dependency_tree() { |
|
local binary="$1" |
|
local dep |
|
local soname |
|
|
|
while IFS= read -r dep; do |
|
[ -n "$dep" ] || continue |
|
[ -f "$dep" ] || continue |
|
soname=$(basename "$dep") |
|
if ! should_bundle_soname "$soname"; then |
|
continue |
|
fi |
|
if [ ! -e "$LIB_DIR/$soname" ]; then |
|
cp -a "$dep" "$LIB_DIR/$soname" |
|
chmod 755 "$LIB_DIR/$soname" || true |
|
copy_dependency_tree "$dep" |
|
fi |
|
done < <( |
|
ldd "$binary" 2>/dev/null | awk ' |
|
/=>/ && $3 ~ /^\// { print $3 } |
|
$1 ~ /^\// { print $1 } |
|
' | sort -u |
|
) |
|
} |
|
|
|
copy_system_library() { |
|
local soname="$1" |
|
local path |
|
path=$(find_system_library "$soname") |
|
if [ -z "$path" ]; then |
|
printf 'Unable to locate required system library: %s\n' "$soname" >&2 |
|
exit 1 |
|
fi |
|
cp -a "$path" "$LIB_DIR/$(basename "$path")" |
|
chmod 755 "$LIB_DIR/$(basename "$path")" || true |
|
copy_dependency_tree "$path" |
|
} |
|
|
|
printf '==> Checking build prerequisites\n' |
|
require_command rsync |
|
require_command "$PYTHON_BIN" |
|
require_command "$APPIMAGETOOL_BIN" |
|
require_command ldconfig |
|
require_command ldd |
|
|
|
if [ "$(uname -m)" != "$ARCH_EXPECTED" ]; then |
|
printf 'This builder must run on %s. Current architecture: %s\n' "$ARCH_EXPECTED" "$(uname -m)" >&2 |
|
exit 1 |
|
fi |
|
|
|
printf '==> Creating AppDir at %s\n' "$APPDIR" |
|
rm -rf "$APPDIR" |
|
mkdir -p "$DIST_DIR" "$LIB_DIR" "$GAME_DIR" |
|
|
|
printf '==> Building bundled Python environment with %s\n' "$PYTHON_BIN" |
|
"$PYTHON_BIN" -m venv --copies "$PYTHON_DIR" |
|
"$PYTHON_DIR/bin/pip" install --upgrade pip setuptools wheel |
|
"$PYTHON_DIR/bin/pip" install -r "$ROOT_DIR/requirements.txt" |
|
|
|
printf '==> Syncing game files\n' |
|
rsync -a \ |
|
--delete \ |
|
--exclude '.git' \ |
|
--exclude '.github' \ |
|
--exclude '.venv' \ |
|
--exclude '__pycache__' \ |
|
--exclude '*.pyc' \ |
|
--exclude '.mypy_cache' \ |
|
--exclude '.pytest_cache' \ |
|
--exclude 'build' \ |
|
--exclude 'dist' \ |
|
--exclude 'packaging' \ |
|
"$ROOT_DIR/" "$GAME_DIR/" |
|
|
|
rm -f "$GAME_DIR/user_profiles.json" "$GAME_DIR/scores.txt" |
|
|
|
printf '==> Installing AppImage metadata\n' |
|
install -Dm755 "$ROOT_DIR/packaging/appimage/AppRun" "$APPDIR/AppRun" |
|
install -Dm644 "$ROOT_DIR/packaging/appimage/mice.desktop" "$APPDIR/$APP_ID.desktop" |
|
install -Dm644 "$ROOT_DIR/packaging/appimage/mice.desktop" "$APPDIR/usr/share/applications/$APP_ID.desktop" |
|
install -Dm644 "$ROOT_DIR/assets/Rat/BMP_WEWIN.png" "$APPDIR/$APP_ID.png" |
|
install -Dm644 "$ROOT_DIR/assets/Rat/BMP_WEWIN.png" "$APPDIR/usr/share/icons/hicolor/256x256/apps/$APP_ID.png" |
|
|
|
printf '==> Bundling native dependencies\n' |
|
copy_system_library libSDL2-2.0.so.0 |
|
copy_system_library libSDL2_ttf-2.0.so.0 |
|
copy_dependency_tree "$PYTHON_DIR/bin/python" |
|
|
|
while IFS= read -r -d '' candidate; do |
|
copy_dependency_tree "$candidate" |
|
done < <(find "$PYTHON_DIR" -type f \( -name '*.so' -o -name '*.so.*' -o -perm -u+x \) -print0) |
|
|
|
printf '==> Building AppImage %s\n' "$OUTPUT_APPIMAGE" |
|
ARCH="$ARCH_EXPECTED" "$APPIMAGETOOL_BIN" --appimage-extract-and-run "$APPDIR" "$OUTPUT_APPIMAGE" |
|
|
|
printf 'AppImage created at %s\n' "$OUTPUT_APPIMAGE" |