108 lines
4.1 KiB
Bash
108 lines
4.1 KiB
Bash
#!/usr/bin/env bash
|
|
# Assemble an AppImage for the OpenPencil Rust desktop shell + `op` CLI.
|
|
#
|
|
# AppDir layout (usr/ tree shared with the .deb via package-linux-common.sh):
|
|
# AppRun -> usr/bin/openpencil-desktop (symlink entrypoint)
|
|
# openpencil.desktop, openpencil.png, .DirIcon (AppImage root metadata)
|
|
# usr/bin/{openpencil-desktop,op}
|
|
# usr/share/{applications,mime/packages,icons,pixmaps}/...
|
|
#
|
|
# The actual packing tool (appimagetool) is downloaded pinned-by-URL by the
|
|
# workflow and passed in via --tool; this script only assembles the AppDir
|
|
# and invokes it. Without --tool (or with --layout-only) it stops after
|
|
# assembly and prints the tree — that is the only mode runnable on macOS,
|
|
# since appimagetool is a Linux ELF.
|
|
#
|
|
# NOTE: plain appimagetool does NOT bundle shared libraries (unlike
|
|
# linuxdeploy). The produced AppImage links against the build host's glibc /
|
|
# mesa / fontconfig, i.e. it runs on distros at least as new as the runner
|
|
# image (ubuntu-24.04). Acceptable for now; switch to linuxdeploy if older
|
|
# distro coverage becomes a requirement.
|
|
#
|
|
# Usage:
|
|
# package-appimage.sh --desktop-bin PATH --cli-bin PATH --icon PATH \
|
|
# --version X.Y.Z --arch x86_64|aarch64 \
|
|
# --out-dir DIR [--tool PATH] [--layout-only]
|
|
#
|
|
# Output: <out-dir>/OpenPencil-<version>-<x64|arm64>-linux.AppImage
|
|
# (matches electron-builder's `${productName}-${version}-${arch}-linux.${ext}`)
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
# shellcheck source=package-linux-common.sh
|
|
source "$SCRIPT_DIR/package-linux-common.sh"
|
|
|
|
DESKTOP_BIN="" CLI_BIN="" ICON_PNG="" VERSION="" AI_ARCH="" OUT_DIR="" TOOL=""
|
|
LAYOUT_ONLY=0
|
|
|
|
usage() {
|
|
sed -n '2,29p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
|
|
exit "${1:-1}"
|
|
}
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--desktop-bin) DESKTOP_BIN="$2"; shift 2 ;;
|
|
--cli-bin) CLI_BIN="$2"; shift 2 ;;
|
|
--icon) ICON_PNG="$2"; shift 2 ;;
|
|
--version) VERSION="$2"; shift 2 ;;
|
|
--arch) AI_ARCH="$2"; shift 2 ;;
|
|
--out-dir) OUT_DIR="$2"; shift 2 ;;
|
|
--tool) TOOL="$2"; shift 2 ;;
|
|
--layout-only) LAYOUT_ONLY=1; shift ;;
|
|
-h|--help) usage 0 ;;
|
|
*) echo "error: unknown argument '$1'" >&2; usage ;;
|
|
esac
|
|
done
|
|
|
|
for req in DESKTOP_BIN CLI_BIN ICON_PNG VERSION AI_ARCH OUT_DIR; do
|
|
if [ -z "${!req}" ]; then
|
|
echo "error: --$(echo "$req" | tr '[:upper:]_' '[:lower:]-') is required" >&2
|
|
usage
|
|
fi
|
|
done
|
|
for f in "$DESKTOP_BIN" "$CLI_BIN" "$ICON_PNG"; do
|
|
[ -f "$f" ] || { echo "error: input file not found: $f" >&2; exit 1; }
|
|
done
|
|
case "$AI_ARCH" in
|
|
x86_64 | aarch64) ;;
|
|
*) echo "error: --arch must be x86_64 or aarch64 (got '$AI_ARCH')" >&2; exit 1 ;;
|
|
esac
|
|
|
|
ARTIFACT_ARCH="$(op_artifact_arch "$AI_ARCH")"
|
|
STAGE="$(mktemp -d)"
|
|
trap 'rm -rf "$STAGE"' EXIT
|
|
APPDIR="$STAGE/OpenPencil.AppDir"
|
|
mkdir -p "$APPDIR"
|
|
|
|
echo "==> staging AppDir"
|
|
op_install_usr_tree "$APPDIR" "$DESKTOP_BIN" "$CLI_BIN" "$ICON_PNG"
|
|
|
|
# AppImage root metadata: desktop entry + icon must sit at AppDir root;
|
|
# .DirIcon is what most file managers display for the mounted image.
|
|
cp "$APPDIR/usr/share/applications/openpencil.desktop" "$APPDIR/openpencil.desktop"
|
|
cp "$ICON_PNG" "$APPDIR/openpencil.png"
|
|
cp "$ICON_PNG" "$APPDIR/.DirIcon"
|
|
ln -sf usr/bin/openpencil-desktop "$APPDIR/AppRun"
|
|
|
|
if [ "$LAYOUT_ONLY" = 1 ] || [ -z "$TOOL" ]; then
|
|
echo "==> layout-only mode: assembled AppDir"
|
|
(cd "$APPDIR" && find . \( -type f -o -type l \) | sort)
|
|
if [ -z "$TOOL" ] && [ "$LAYOUT_ONLY" = 0 ]; then
|
|
echo "note: no --tool given; skipped AppImage packing" >&2
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
[ -x "$TOOL" ] || { echo "error: appimagetool not executable: $TOOL" >&2; exit 1; }
|
|
|
|
mkdir -p "$OUT_DIR"
|
|
OUT_PATH="$OUT_DIR/OpenPencil-$VERSION-$ARTIFACT_ARCH-linux.AppImage"
|
|
echo "==> packing AppImage ($AI_ARCH)"
|
|
# --appimage-extract-and-run: appimagetool itself ships as an AppImage and
|
|
# CI runners have no FUSE; this flag self-extracts instead of mounting.
|
|
# ARCH is required when the tool cannot infer the target architecture.
|
|
ARCH="$AI_ARCH" "$TOOL" --appimage-extract-and-run "$APPDIR" "$OUT_PATH"
|
|
echo "AppImage ready: $OUT_PATH"
|