#!/usr/bin/env bash set -euo pipefail # Usage: scripts/make-appimage.sh # Produces an AppImage from a Linux binary using linuxdeploy. if [[ $# -ne 3 ]]; then echo "Usage: $0 " exit 1 fi BINARY="$1" ARCH="$2" OUTDIR="$3" REPO_ROOT="$(git rev-parse --show-toplevel)" CACHE_DIR="$REPO_ROOT/.cache" APP_NAME="$(basename "$BINARY")" APPDIR="$(mktemp -d)/AppDir" LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${ARCH}.AppImage" LINUXDEPLOY="$CACHE_DIR/linuxdeploy-${ARCH}.AppImage" RUNTIME_URL="https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-${ARCH}" RUNTIME="$CACHE_DIR/runtime-${ARCH}" # Map arch to linuxdeploy's expected values case "$ARCH" in x86_64) export LDAI_ARCH="x86_64" ;; aarch64) export LDAI_ARCH="aarch64" ;; *) echo "Unsupported arch: $ARCH"; exit 1 ;; esac download_tools() { mkdir -p "$CACHE_DIR" if [[ ! -f "$LINUXDEPLOY" ]]; then echo " Downloading linuxdeploy for $ARCH..." curl -fSL "$LINUXDEPLOY_URL" -o "$LINUXDEPLOY" chmod +x "$LINUXDEPLOY" fi if [[ ! -f "$RUNTIME" ]]; then echo " Downloading AppImage runtime for $ARCH..." curl -fSL "$RUNTIME_URL" -o "$RUNTIME" fi } build_appdir() { mkdir -p "$APPDIR/usr/bin" cp "$BINARY" "$APPDIR/usr/bin/cagire" chmod +x "$APPDIR/usr/bin/cagire" mkdir -p "$APPDIR/usr/share/icons/hicolor/512x512/apps" cp "$REPO_ROOT/assets/Cagire.png" "$APPDIR/usr/share/icons/hicolor/512x512/apps/cagire.png" cp "$REPO_ROOT/assets/cagire.desktop" "$APPDIR/cagire.desktop" } run_linuxdeploy_native() { export ARCH="$LDAI_ARCH" export LDAI_RUNTIME_FILE="$RUNTIME" "$LINUXDEPLOY" \ --appimage-extract-and-run \ --appdir "$APPDIR" \ --desktop-file "$APPDIR/cagire.desktop" \ --icon-file "$APPDIR/usr/share/icons/hicolor/512x512/apps/cagire.png" \ --output appimage } run_linuxdeploy_docker() { local platform case "$ARCH" in x86_64) platform="linux/amd64" ;; aarch64) platform="linux/arm64" ;; esac local image_tag="cagire-appimage-${ARCH}" echo " Building Docker image $image_tag ($platform)..." docker build --platform "$platform" -q -t "$image_tag" - <<'DOCKERFILE' FROM ubuntu:22.04 RUN apt-get update && apt-get install -y --no-install-recommends \ file \ libasound2 \ libjack0 \ libxcb-render0 \ libxcb-shape0 \ libxcb-xfixes0 \ libxkbcommon0 \ libgl1 \ && rm -rf /var/lib/apt/lists/* DOCKERFILE echo " Running linuxdeploy inside Docker ($image_tag)..." docker run --rm --platform "$platform" \ -v "$REPO_ROOT:/project" \ -v "$APPDIR:/appdir" \ -v "$CACHE_DIR:/cache" \ -e ARCH="$LDAI_ARCH" \ -e LDAI_RUNTIME_FILE="/cache/runtime-${ARCH}" \ -w /project \ "$image_tag" \ bash -c " chmod +x /cache/linuxdeploy-${ARCH}.AppImage && \ /cache/linuxdeploy-${ARCH}.AppImage \ --appimage-extract-and-run \ --appdir /appdir \ --desktop-file /appdir/cagire.desktop \ --icon-file /appdir/usr/share/icons/hicolor/512x512/apps/cagire.png \ --output appimage " } HOST_ARCH="$(uname -m)" download_tools build_appdir echo " Building AppImage for cagire ($ARCH)..." if [[ "$HOST_ARCH" == "$ARCH" ]] && [[ "$(uname -s)" == "Linux" ]]; then run_linuxdeploy_native else run_linuxdeploy_docker fi mkdir -p "$OUTDIR" # linuxdeploy outputs to cwd; find and move the AppImage APPIMAGE=$(ls -1t ./*.AppImage 2>/dev/null | head -1 || true) if [[ -z "$APPIMAGE" ]]; then echo " ERROR: No AppImage produced" exit 1 fi FINAL_NAME="${APP_NAME}-linux-${ARCH}.AppImage" mv "$APPIMAGE" "$OUTDIR/$FINAL_NAME" echo " AppImage -> $OUTDIR/$FINAL_NAME"