#!/usr/bin/env bash # Build a Linux AppImage of OctoLauncher (local or CI). # Usage: ./scripts/build.sh [--deps] # --deps install native build deps via the distro package manager (needs sudo) set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" WITH_DEPS=0 for arg in "$@"; do case "$arg" in --deps) WITH_DEPS=1 ;; -h | --help) sed -n '2,5p' "$0" exit 0 ;; *) echo "Unknown option: $arg" >&2 exit 1 ;; esac done if [[ "$(uname -s)" != "Linux" ]]; then echo "This script only builds Linux packages (host is $(uname -s))." >&2 exit 1 fi NODE_MAJOR="$(node -p "process.versions.node.split('.')[0]" 2>/dev/null || true)" if [[ -z "${NODE_MAJOR}" || "${NODE_MAJOR}" -ne 20 ]]; then echo "Warning: Node 20 is recommended (found: $(node -v 2>/dev/null || echo none))." >&2 fi # VS Code / Cursor set this and break Electron. unset ELECTRON_RUN_AS_NODE export ELECTRON_RUN_AS_NODE= is_arch_like() { # CachyOS, Arch, EndeavourOS, Manjaro, etc. [[ -f /etc/arch-release ]] && return 0 if [[ -f /etc/os-release ]]; then # shellcheck disable=SC1091 . /etc/os-release [[ "${ID:-}" == "arch" || "${ID:-}" == "cachyos" || "${ID_LIKE:-}" == *"arch"* ]] && return 0 fi command -v pacman >/dev/null 2>&1 } is_debian_like() { command -v apt-get >/dev/null 2>&1 || return 1 if [[ -f /etc/os-release ]]; then # shellcheck disable=SC1091 . /etc/os-release [[ "${ID:-}" == "debian" || "${ID:-}" == "ubuntu" || "${ID_LIKE:-}" == *"debian"* ]] && return 0 fi # GitHub ubuntu-latest / other apt hosts without a clear ID_LIKE return 0 } install_deps() { if is_arch_like; then echo "==> install deps (pacman: base-devel python)" sudo pacman -S --needed --noconfirm base-devel python elif is_debian_like; then echo "==> install deps (apt: build-essential python3)" sudo apt-get update sudo apt-get install -y build-essential python3 else echo "Unsupported distro for --deps. Install a C++ toolchain + Python 3, then re-run without --deps." >&2 exit 1 fi } if [[ "${WITH_DEPS}" -eq 1 ]]; then install_deps fi if ! command -v g++ >/dev/null 2>&1; then echo "g++ not found. Install build tools (e.g. ./scripts/build.sh --deps) and retry." >&2 exit 1 fi echo "==> npm install (ignore-scripts)" npm install --ignore-scripts --no-audit --no-fund # dll-inject is Windows-only (LoadLibrary) and unused in source. echo "==> drop unused Windows native dep (dll-inject)" rm -rf node_modules/dll-inject echo "==> download Electron binary" node node_modules/electron/install.js # npm 12+ may no-op `npm rebuild` (install scripts blocked), so build stormlib # against Electron headers explicitly. Package ships a Windows .node in dist/. ELECTRON_VERSION="$(node -p "require('./node_modules/electron/package.json').version")" ELECTRON_ARCH="$(node -p "process.arch")" echo "==> rebuild stormlib-node for Electron ${ELECTRON_VERSION} (${ELECTRON_ARCH})" ( cd node_modules/stormlib-node # Don't use post-build.js — it deletes dist/ (wiping enums.js). node scripts/pre-configure.js npx --yes node-gyp rebuild \ --target="${ELECTRON_VERSION}" \ --arch="${ELECTRON_ARCH}" \ --dist-url=https://electronjs.org/headers test -f build/Release/stormlib.node cp build/Release/stormlib.node dist/stormlib.node rm -rf build ) file node_modules/stormlib-node/dist/stormlib.node # Must be ELF on Linux, not the published Windows PE. if ! file node_modules/stormlib-node/dist/stormlib.node | grep -q ELF; then echo "stormlib.node is not a Linux ELF binary after rebuild." >&2 exit 1 fi test -f node_modules/stormlib-node/dist/enums.js echo "==> electron-vite build" npm run build echo "==> package AppImage" npx electron-builder --linux AppImage --config echo "==> done" ls -lh distprod/*.AppImage