mirror of
https://github.com/JS8Call-improved/JS8Call-improved
synced 2026-08-13 17:47:36 -04:00
JS8Call-Build-AppImage.sh: Update Linux workflow script to include
libopengl-dev
tools/Linux-User-Build-JS8Call.sh: Update user build script to include
libopengl-development package
278 lines
10 KiB
Bash
Executable file
278 lines
10 KiB
Bash
Executable file
|
|
# --- Build an AppImage for JS8Call ---
|
|
# --- Run on Ubuntu 24 Server ---
|
|
# --- Target: any Linux system with glibc 2.39 or later ---
|
|
|
|
# --- Must not run as root ---
|
|
if [ "$(id -u)" -eq 0 ]; then
|
|
echo "This script must NOT be run as root. Exiting."
|
|
exit 1
|
|
fi
|
|
|
|
set -euo pipefail
|
|
|
|
# --- Variables ---
|
|
JS8_ARCH=$(uname -m)
|
|
JS8_SOURCE="https://github.com/JS8Call-improved/JS8Call-improved.git"
|
|
JS8_BUILD_BRANCH="master"
|
|
|
|
# AppImage uses x86_64 and aarch64 — not Debian's amd64/arm64
|
|
if [ "$JS8_ARCH" = "x86_64" ]; then
|
|
APPIMAGE_ARCH="x86_64"
|
|
elif [ "$JS8_ARCH" = "aarch64" ]; then
|
|
APPIMAGE_ARCH="aarch64"
|
|
else
|
|
echo "Unsupported architecture: $JS8_ARCH"
|
|
exit 1
|
|
fi
|
|
|
|
# --- Tarball URLs ---
|
|
JS8LIB_URL="https://github.com/JS8Call-improved/js8lib/releases/download/lib%2F4.0/js8lib4.0-Linux_${JS8_ARCH}_pkg.tar.gz"
|
|
QT_URL="https://github.com/JS8Call-improved/js8lib/releases/download/lib%2F4.0/Qt6.12.0_Linux_${JS8_ARCH}_pkg.tar.gz"
|
|
|
|
# --- Directories ---
|
|
BUILD_DIR="$HOME/js8call-appimage-build"
|
|
STAGING_DIR="$BUILD_DIR/staging"
|
|
APPDIR="$STAGING_DIR/JS8Call.AppDir"
|
|
INSTALL_PREFIX="/usr/lib/js8call"
|
|
|
|
echo "######################################################################"
|
|
echo " Building JS8Call AppImage"
|
|
echo " Architecture: $JS8_ARCH"
|
|
echo "######################################################################"
|
|
sleep 2
|
|
|
|
# --- Install build dependencies ---
|
|
# These are build-time only and will NOT be bundled in the AppImage
|
|
echo "Installing build dependencies..."
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
build-essential cmake ninja-build perl python3 git wget \
|
|
libssl-dev libfontconfig1-dev libfreetype-dev \
|
|
libharfbuzz-dev libjpeg-dev libpng-dev \
|
|
zlib1g-dev libbrotli-dev libdbus-1-dev libglib2.0-dev \
|
|
libatspi2.0-dev libgl-dev libegl-dev libgbm-dev \
|
|
libdrm-dev libinput-dev libvulkan-dev \
|
|
libopengl-dev \
|
|
libxkbcommon-dev libxkbcommon-x11-dev \
|
|
libxcb-util-dev libxcb-image0-dev libxcb-keysyms1-dev \
|
|
libxcb-render-util0-dev libxcb-icccm4-dev libxcb-cursor-dev \
|
|
libxrender-dev libxi-dev \
|
|
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
|
|
libwayland-dev wayland-protocols \
|
|
libpulse-dev \
|
|
libxcb-shape0-dev libxcb-randr0-dev libxcb-sync-dev \
|
|
libxcb-xfixes0-dev libxcb-xkb-dev libxcb-xinput-dev \
|
|
libasound2-dev || sudo apt-get install -y libasound2t64 \
|
|
clang-18 lld-18
|
|
|
|
# libjpeg-turbo ships as .so.62 on Debian but linuxdeploy-plugin-qt
|
|
# expects .so.8 — create a symlink if needed
|
|
if [ ! -f /usr/lib/${JS8_ARCH}-linux-gnu/libjpeg.so.8 ]; then
|
|
sudo ln -s /usr/lib/${JS8_ARCH}-linux-gnu/libjpeg.so.62 \
|
|
/usr/lib/${JS8_ARCH}-linux-gnu/libjpeg.so.8
|
|
fi
|
|
|
|
# --- Create build directory structure ---
|
|
echo "Creating build directory structure..."
|
|
rm -rf "$BUILD_DIR"
|
|
mkdir -p "$BUILD_DIR"
|
|
mkdir -p "$STAGING_DIR"
|
|
mkdir -p "$APPDIR"
|
|
|
|
# --- Download linuxdeploy and its Qt plugin ---
|
|
# linuxdeploy handles all dependency walking and Qt plugin discovery,
|
|
# and builds the final AppImage — no separate appimagetool needed
|
|
echo "Downloading linuxdeploy..."
|
|
cd "$BUILD_DIR"
|
|
wget -q --show-progress \
|
|
"https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${APPIMAGE_ARCH}.AppImage" \
|
|
-O linuxdeploy.AppImage
|
|
wget -q --show-progress \
|
|
"https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-${APPIMAGE_ARCH}.AppImage" \
|
|
-O linuxdeploy-plugin-qt.AppImage
|
|
chmod +x linuxdeploy.AppImage linuxdeploy-plugin-qt.AppImage
|
|
|
|
# --- Download and extract library tarballs ---
|
|
echo "Downloading js8lib and Qt..."
|
|
wget -q --show-progress "$JS8LIB_URL" -O js8lib.tar.gz
|
|
wget -q --show-progress "$QT_URL" -O Qt.tar.gz
|
|
|
|
# Extract to /usr/lib/js8call so cmake can find them at build time.
|
|
# This also serves as the source for bundling into the AppImage.
|
|
echo "Extracting libraries to $INSTALL_PREFIX..."
|
|
sudo mkdir -p "$INSTALL_PREFIX"
|
|
sudo tar -xzf js8lib.tar.gz -C /usr/lib/js8call --strip-components=1
|
|
sudo tar -xzf Qt.tar.gz -C /usr/lib/js8call
|
|
|
|
# Fix pkgconfig prefix paths to match this machine
|
|
for pc in /usr/lib/js8call/lib/pkgconfig/*.pc; do
|
|
sudo sed -i "s|prefix=.*js8call|prefix=/usr/lib/js8call|g" "$pc"
|
|
done
|
|
for pc in /usr/lib/js8call/Qt/lib/pkgconfig/*.pc; do
|
|
sudo sed -i "s|prefix=.*js8call/Qt|prefix=/usr/lib/js8call/Qt|g" "$pc"
|
|
done
|
|
|
|
# --- Fetch JS8Call source ---
|
|
echo "Fetching JS8Call source..."
|
|
cd "$BUILD_DIR"
|
|
|
|
# Check if running inside GitHub Actions
|
|
if [ -n "${GITHUB_WORKSPACE:-}" ]; then
|
|
echo "CI Environment Detected. Tracking local GitHub Workspace context..."
|
|
|
|
# Clone locally from the runner's pre-checked-out workspace.
|
|
git clone "$GITHUB_WORKSPACE" JS8Call-improved
|
|
cd JS8Call-improved
|
|
ACTIVE_BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-unknown}}"
|
|
echo "Active CI Target Branch: $ACTIVE_BRANCH"
|
|
|
|
else
|
|
# Local Fallback Setup
|
|
JS8_BRANCH="$JS8_BUILD_BRANCH"
|
|
echo "Local Environment Detected. Cloning remote fallback branch: $JS8_BRANCH"
|
|
|
|
git clone "$JS8_SOURCE" JS8Call-improved
|
|
cd JS8Call-improved
|
|
git checkout "$JS8_BRANCH"
|
|
|
|
ACTIVE_BRANCH="$JS8_BRANCH"
|
|
echo "Active Local Target Branch: $ACTIVE_BRANCH"
|
|
fi
|
|
|
|
# --- Determine version string ---
|
|
cd "$BUILD_DIR/JS8Call-improved"
|
|
|
|
# 1. Parse the exact VERSION declaration directly from CMakeLists.txt
|
|
CMAKE_VERSION=$(grep -oP 'VERSION\s+\K\d+\.\d+\.\d+' CMakeLists.txt | head -1 || echo "0.0.0")
|
|
|
|
# 2. Check if it's a dev build or an official release
|
|
if [ "$CMAKE_VERSION" = "0.0.0" ]; then
|
|
# Dev build: Fall back to the short git commit hash
|
|
export VERSION=$(git rev-parse --short HEAD)
|
|
else
|
|
# Release build: Prepend 'v' to the real version number from CMakeLists.txt
|
|
export VERSION="v$CMAKE_VERSION"
|
|
fi
|
|
|
|
# 3. Synchronize banner tracking variable
|
|
JS8_VERSION="$VERSION"
|
|
|
|
echo "AppImage Target Export Version: $JS8_VERSION"
|
|
|
|
# --- Build JS8Call ---
|
|
echo "Build version: $JS8_VERSION"
|
|
echo "######################################################################"
|
|
echo " Building JS8Call $JS8_VERSION AppImage on ($ACTIVE_BRANCH)"
|
|
echo " Architecture: $JS8_ARCH"
|
|
echo "######################################################################"
|
|
mkdir build && cd build
|
|
|
|
cmake \
|
|
-DCMAKE_C_COMPILER=clang-18 \
|
|
-DCMAKE_CXX_COMPILER=clang++-18 \
|
|
-DCMAKE_PREFIX_PATH="/usr/lib/js8call;/usr/lib/js8call/Qt" \
|
|
-DHAMLIB_ROOT="/usr/lib/js8call" \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
..
|
|
|
|
cmake --build . --parallel $(nproc)
|
|
|
|
echo "######################################################################"
|
|
echo " JS8Call build successful"
|
|
echo "######################################################################"
|
|
sleep 2
|
|
|
|
# --- Populate the AppDir ---
|
|
# An AppDir mirrors the target filesystem layout:
|
|
#
|
|
# JS8Call.AppDir/
|
|
# AppRun ← entry point script (required, linuxdeploy writes this)
|
|
# js8call.desktop ← desktop entry (required, must be at root)
|
|
# js8call.svg ← icon (required, name must match Icon= in .desktop)
|
|
# usr/
|
|
# bin/JS8Call ← the compiled binary
|
|
# lib/ ← bundled .so files (populated by linuxdeploy)
|
|
|
|
echo "Populating AppDir..."
|
|
|
|
# Binary
|
|
mkdir -p "$APPDIR/usr/bin"
|
|
cp JS8Call "$APPDIR/usr/bin/"
|
|
|
|
# Desktop entry — must live at the ROOT of AppDir
|
|
cat > "$APPDIR/js8call.desktop" << EOF
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=JS8Call
|
|
Exec=JS8Call
|
|
Icon=js8call
|
|
Terminal=false
|
|
Categories=HamRadio;Network;
|
|
EOF
|
|
|
|
# Icon — must be at the root of AppDir and match Icon= above
|
|
cp "$BUILD_DIR/JS8Call-improved/artwork/icon_128.svg" \
|
|
"$APPDIR/js8call.svg"
|
|
|
|
# libxcb-cursor is loaded by Qt's xcb platform plugin via dlopen at
|
|
# runtime — linuxdeploy won't find it by walking ldd output alone.
|
|
# Pre-seed it into the AppDir so linuxdeploy can walk its deps too.
|
|
mkdir -p "$APPDIR/usr/lib"
|
|
cp -L /usr/lib/${JS8_ARCH}-linux-gnu/libxcb-cursor.so.0 \
|
|
"$APPDIR/usr/lib/" 2>/dev/null || true
|
|
|
|
# AppStream metainfo — for software center integration
|
|
mkdir -p "$APPDIR/usr/share/metainfo"
|
|
cp "$BUILD_DIR/JS8Call-improved/.github/workflows/misc/JS8Call.appdata.xml" \
|
|
"$APPDIR/usr/share/metainfo/io.github.JS8Call_improved.JS8Call.appdata.xml"
|
|
|
|
# --- Run linuxdeploy ---
|
|
# linuxdeploy does the heavy lifting:
|
|
# - walks ldd dependencies of the binary and copies matching .so files
|
|
# - the Qt plugin (--plugin qt) uses qmake to find our private Qt
|
|
# installation and copies Qt libs, platform plugins, imageformats,
|
|
# iconengines etc. — everything Qt loads via dlopen at runtime
|
|
# - --output appimage calls appimagetool internally to produce the
|
|
# final compressed self-executing .AppImage file
|
|
#
|
|
# QMAKE points it at our private Qt 6.12.0, not the system Qt,
|
|
# so it bundles the right version
|
|
cd "$BUILD_DIR"
|
|
export EXTRA_PLATFORM_PLUGINS="libqwayland.so;libqoffscreen.so;libqeglfs.so;libqlinuxfb.so;libqminimalegl.so;libqminimal.so"
|
|
export EXTRA_QT_MODULES="waylandcompositor"
|
|
export QMAKE=/usr/lib/js8call/Qt/bin/qmake
|
|
|
|
./linuxdeploy.AppImage \
|
|
--appdir "$APPDIR" \
|
|
--executable "$APPDIR/usr/bin/JS8Call" \
|
|
--desktop-file "$APPDIR/js8call.desktop" \
|
|
--icon-file "$APPDIR/js8call.svg" \
|
|
--plugin qt \
|
|
--output appimage
|
|
|
|
# --- Strip debug symbols ---
|
|
# linuxdeploy copies libs with debug info intact — strip them down.
|
|
# 2>/dev/null suppresses "file format not recognized" on non-ELF files.
|
|
find "$APPDIR" -type f \( -name "*.so*" -o -name "JS8Call" \) \
|
|
-exec strip --strip-unneeded {} \; 2>/dev/null || true
|
|
|
|
# linuxdeploy names the output based on the .desktop file Name= field
|
|
# and the ARCH env var. Rename to our preferred convention.
|
|
APPIMAGE_FILE=$(ls "$BUILD_DIR"/JS8Call-*.AppImage 2>/dev/null | head -1)
|
|
if [ -z "$APPIMAGE_FILE" ]; then
|
|
echo "ERROR: No AppImage was produced by linuxdeploy." >&2
|
|
exit 1
|
|
fi
|
|
mv "$APPIMAGE_FILE" "$HOME/JS8Call-${JS8_VERSION}-${APPIMAGE_ARCH}.AppImage"
|
|
|
|
echo "######################################################################"
|
|
echo " DONE!"
|
|
echo " AppImage: $HOME/JS8Call-${JS8_VERSION}-${APPIMAGE_ARCH}.AppImage"
|
|
echo ""
|
|
echo " To run on any Linux system:"
|
|
echo " chmod +x JS8Call-${JS8_VERSION}-${APPIMAGE_ARCH}.AppImage"
|
|
echo " ./JS8Call-${JS8_VERSION}-${APPIMAGE_ARCH}.AppImage"
|
|
echo ""
|
|
echo " No installation required. The file is self-contained."
|
|
echo "######################################################################"
|