#!/usr/bin/env bash # visionA-local Linux AppImage builder # # 必須在 Linux x86_64 跑(GitHub Actions ubuntu-latest 即可)。 # 需要的工具:appimagetool、wails CLI、go 1.26+、pnpm、curl # # 前置:payload/linux/ 應已由 `make payload-linux` 產出, # visiona-local/build/bin/visiona-local(Wails app binary)應已由 `make wails-linux` 產出。 # # 用法: # VERSION=0.1.0 bash installer/linux/build-appimage.sh # # 產物:dist/visiona-local-${VERSION}-linux-x64.AppImage set -euo pipefail PROJECT_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" APPDIR="$PROJECT_ROOT/dist/visiona-local.AppDir" VERSION="${VERSION:-0.1.0}" # 平台守門:只能在 Linux 跑 if [ "$(uname -s)" != "Linux" ]; then echo "❌ build-appimage.sh 只能在 Linux 上執行(目前:$(uname -s))" exit 1 fi echo "==> 清理舊 AppDir" rm -rf "$APPDIR" mkdir -p "$APPDIR/usr/bin" \ "$APPDIR/usr/lib/visiona-local/data" \ "$APPDIR/usr/lib/visiona-local/scripts" \ "$APPDIR/usr/lib/visiona-local/python" \ "$APPDIR/usr/lib/visiona-local/wheels" \ "$APPDIR/usr/share/applications" \ "$APPDIR/usr/share/icons/hicolor/256x256/apps" echo "==> 複製 Wails app binary" WAILS_BIN="$PROJECT_ROOT/visiona-local/build/bin/visiona-local" if [ ! -f "$WAILS_BIN" ]; then echo "❌ 找不到 Wails binary:$WAILS_BIN" echo " 請先執行:make wails-linux" exit 1 fi cp "$WAILS_BIN" "$APPDIR/usr/bin/visiona-local" chmod +x "$APPDIR/usr/bin/visiona-local" echo "==> 複製 server binary + 工具(從 payload/linux/)" PAYLOAD_LINUX="$PROJECT_ROOT/payload/linux" if [ ! -d "$PAYLOAD_LINUX" ]; then echo "❌ 找不到 payload/linux/,請先執行:make payload-linux" exit 1 fi # server binary if [ -f "$PAYLOAD_LINUX/bin/visiona-local-server" ]; then cp "$PAYLOAD_LINUX/bin/visiona-local-server" "$APPDIR/usr/bin/visiona-local-server" else echo "⚠️ payload/linux/bin/visiona-local-server 不存在(需要在 Linux 上 go build server)" fi # ffmpeg / ffprobe # ffmpeg 為 LGPL v3 build(BtbN n7.1,v2 TDD §4) for tool in ffmpeg ffprobe; do if [ -f "$PAYLOAD_LINUX/bin/$tool" ]; then cp "$PAYLOAD_LINUX/bin/$tool" "$APPDIR/usr/bin/$tool" else echo "⚠️ payload/linux/bin/$tool 不存在" fi done chmod +x "$APPDIR/usr/bin/"* 2>/dev/null || true # 把 ffmpeg 授權條款放到 AppImage 的 share/doc/ mkdir -p "$APPDIR/usr/share/doc/visiona-local" if [ -f "$PAYLOAD_LINUX/bin/ffmpeg-LICENSE.txt" ]; then cp "$PAYLOAD_LINUX/bin/ffmpeg-LICENSE.txt" "$APPDIR/usr/share/doc/visiona-local/ffmpeg-LICENSE.txt" fi echo "==> 複製資料、腳本、Python runtime、wheels" [ -d "$PAYLOAD_LINUX/data" ] && cp -R "$PAYLOAD_LINUX/data/." "$APPDIR/usr/lib/visiona-local/data/" || true [ -d "$PAYLOAD_LINUX/scripts" ] && cp -R "$PAYLOAD_LINUX/scripts/." "$APPDIR/usr/lib/visiona-local/scripts/" || true [ -f "$PAYLOAD_LINUX/python/python.tar.gz" ] && \ cp "$PAYLOAD_LINUX/python/python.tar.gz" "$APPDIR/usr/lib/visiona-local/python/" || \ echo "⚠️ python tarball 不存在" if ls "$PAYLOAD_LINUX/wheels/"*.whl >/dev/null 2>&1; then cp "$PAYLOAD_LINUX/wheels/"*.whl "$APPDIR/usr/lib/visiona-local/wheels/" else echo "⚠️ wheels 目錄為空" fi # 複製 udev rule 到 lib 供 Wails app 首次啟動時使用 if [ -f "$PROJECT_ROOT/installer/linux/99-kneron.rules" ]; then cp "$PROJECT_ROOT/installer/linux/99-kneron.rules" "$APPDIR/usr/lib/visiona-local/" fi if [ -f "$PROJECT_ROOT/installer/linux/install-udev.sh" ]; then cp "$PROJECT_ROOT/installer/linux/install-udev.sh" "$APPDIR/usr/lib/visiona-local/" chmod +x "$APPDIR/usr/lib/visiona-local/install-udev.sh" fi echo "==> 寫入 .desktop 與 icon" cat > "$APPDIR/visiona-local.desktop" <<'DESKTOP' [Desktop Entry] Type=Application Name=visionA-local Comment=Local-first Edge AI development tool for Kneron KL520/KL720 Exec=visiona-local Icon=visiona-local Categories=Development; Terminal=false StartupWMClass=visionA-local DESKTOP cp "$APPDIR/visiona-local.desktop" "$APPDIR/usr/share/applications/" # Icon (256x256 PNG),從 visiona-local/build/appicon.png 複製 APPICON="$PROJECT_ROOT/visiona-local/build/appicon.png" if [ -f "$APPICON" ]; then cp "$APPICON" "$APPDIR/visiona-local.png" cp "$APPICON" "$APPDIR/usr/share/icons/hicolor/256x256/apps/visiona-local.png" else echo "⚠️ 找不到 appicon.png,AppImage 將無 icon" fi echo "==> 寫入 AppRun" cat > "$APPDIR/AppRun" <<'APPRUN' #!/bin/bash # AppRun — AppImage 啟動 entry point HERE="$(dirname "$(readlink -f "${0}")")" export PATH="${HERE}/usr/bin:${PATH}" export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH:-}" # visionA-local 專屬環境變數:讓 Wails app 定位 bundle 內檔案 export VISIONA_BUNDLE_BIN_DIR="${HERE}/usr/bin" export VISIONA_BUNDLE_LIB_DIR="${HERE}/usr/lib/visiona-local" exec "${HERE}/usr/bin/visiona-local" "$@" APPRUN chmod +x "$APPDIR/AppRun" echo "==> 檢查 appimagetool" if ! command -v appimagetool &> /dev/null; then echo "❌ appimagetool 未安裝。" echo "" echo " 一鍵安裝(推薦):" echo " curl -fsSL https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage -o /tmp/appimagetool \\" echo " && chmod +x /tmp/appimagetool \\" echo " && sudo mv /tmp/appimagetool /usr/local/bin/appimagetool" echo "" echo " 或重跑 bootstrap-linux.sh(會自動安裝所有依賴):" echo " bash scripts/bootstrap-linux.sh" echo "" exit 1 fi echo "==> 用 appimagetool 打包" mkdir -p "$PROJECT_ROOT/dist" OUTPUT="$PROJECT_ROOT/dist/visiona-local-${VERSION}-linux-x64.AppImage" ARCH=x86_64 appimagetool "$APPDIR" "$OUTPUT" echo "" echo "==> 完成:$OUTPUT" ls -lh "$OUTPUT"