build: add AppImage packaging pipeline and build scripts
This commit is contained in:
parent
7b4a9c1fe3
commit
26eaf8cf68
6 changed files with 220 additions and 0 deletions
91
packaging/appimage/AppImageBuilder.yml
Normal file
91
packaging/appimage/AppImageBuilder.yml
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
version: 1
|
||||
|
||||
AppDir:
|
||||
path: !ENV '${SCANSLICER_APPDIR}'
|
||||
app_info:
|
||||
id: scanslicer
|
||||
name: ScanSlicer
|
||||
icon: scanslicer
|
||||
version: "1.0.0"
|
||||
exec: usr/bin/python3
|
||||
exec_args: "-m scanslicer $@"
|
||||
|
||||
apt:
|
||||
arch: amd64
|
||||
allow_unauthenticated: false
|
||||
sources:
|
||||
- sourceline: "deb https://archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse"
|
||||
key_url: "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C"
|
||||
include:
|
||||
- python3
|
||||
- python3-pip
|
||||
- libdbus-1-3
|
||||
- libfontconfig1
|
||||
- libegl1
|
||||
- libgl1
|
||||
- libglib2.0-0
|
||||
- libglib2.0-bin
|
||||
- libsm6
|
||||
- libwayland-client0
|
||||
- libwayland-cursor0
|
||||
- libwayland-egl1
|
||||
- libxkbcommon0
|
||||
- libx11-xcb1
|
||||
- libxcb-cursor0
|
||||
- libgdk-pixbuf2.0-bin
|
||||
- libgtk-3-bin
|
||||
|
||||
files:
|
||||
include:
|
||||
- /usr/bin/python3
|
||||
- /usr/bin/pip3
|
||||
- /usr/lib
|
||||
- /usr/share
|
||||
exclude:
|
||||
- usr/share/man
|
||||
- usr/share/doc/*/README.*
|
||||
- usr/share/doc/*/changelog.*
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.*
|
||||
- usr/lib/x86_64-linux-gnu/libQt6*.so*
|
||||
- usr/lib/x86_64-linux-gnu/qt6/**
|
||||
|
||||
runtime:
|
||||
env:
|
||||
APPDIR: "${APPDIR}"
|
||||
PYTHONHOME: "${APPDIR}/usr"
|
||||
PYTHONNOUSERSITE: "1"
|
||||
QT_PLUGIN_PATH: "${APPDIR}/usr/local/lib/python3.12/dist-packages/PySide6/Qt/plugins"
|
||||
LD_LIBRARY_PATH: "${APPDIR}/usr/local/lib/python3.12/dist-packages/PySide6/Qt/lib:${APPDIR}/usr/local/lib/python3.12/dist-packages/opencv_python.libs:${APPDIR}/usr/lib:${APPDIR}/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}"
|
||||
PATH: "${APPDIR}/usr/bin:${PATH}"
|
||||
|
||||
after_bundle: |
|
||||
APPDIR_PATH="${APPDIR:-${SCANSLICER_APPDIR:-}}"
|
||||
if [ -z "${APPDIR_PATH}" ]; then
|
||||
echo "AppDir path is not set (SCANSLICER_APPDIR/APPDIR)." >&2
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "${APPDIR_PATH}/usr/share/applications"
|
||||
mkdir -p "${APPDIR_PATH}/usr/share/icons"
|
||||
mkdir -p "${APPDIR_PATH}/usr/share/pixmaps"
|
||||
mkdir -p "${APPDIR_PATH}/icons"
|
||||
mkdir -p "${APPDIR_PATH}/pixmaps"
|
||||
cp "${SCANSLICER_ROOT}/packaging/appimage/scanslicer.desktop" "${APPDIR_PATH}/usr/share/applications/scanslicer.desktop"
|
||||
cp "${SCANSLICER_ROOT}/packaging/appimage/scanslicer.svg" "${APPDIR_PATH}/usr/share/icons/scanslicer.svg"
|
||||
cp "${SCANSLICER_ROOT}/packaging/appimage/scanslicer.svg" "${APPDIR_PATH}/usr/share/pixmaps/scanslicer.svg"
|
||||
rsvg-convert -w 256 -h 256 "${SCANSLICER_ROOT}/packaging/appimage/scanslicer.svg" > "${APPDIR_PATH}/usr/share/icons/scanslicer.png"
|
||||
cp "${APPDIR_PATH}/usr/share/icons/scanslicer.png" "${APPDIR_PATH}/usr/share/pixmaps/scanslicer.png"
|
||||
cp "${APPDIR_PATH}/usr/share/icons/scanslicer.png" "${APPDIR_PATH}/icons/scanslicer.png"
|
||||
cp "${APPDIR_PATH}/usr/share/icons/scanslicer.png" "${APPDIR_PATH}/pixmaps/scanslicer.png"
|
||||
cp "${APPDIR_PATH}/usr/share/icons/scanslicer.png" "${APPDIR_PATH}/.DirIcon"
|
||||
test -f "${APPDIR_PATH}/usr/share/icons/scanslicer.png"
|
||||
test -f "${APPDIR_PATH}/usr/share/pixmaps/scanslicer.png"
|
||||
test -f "${APPDIR_PATH}/icons/scanslicer.png"
|
||||
test -f "${APPDIR_PATH}/pixmaps/scanslicer.png"
|
||||
test -f "${APPDIR_PATH}/.DirIcon"
|
||||
rm -rf "${APPDIR_PATH}/usr/lib/x86_64-linux-gnu/qt6"
|
||||
rm -f "${APPDIR_PATH}"/usr/lib/x86_64-linux-gnu/libQt6*.so*
|
||||
python3 -m pip install --no-cache-dir --upgrade --ignore-installed --prefix=/usr --root="${APPDIR_PATH}" -r "${SCANSLICER_REQUIREMENTS}"
|
||||
|
||||
AppImage:
|
||||
arch: x86_64
|
||||
34
packaging/appimage/Dockerfile
Normal file
34
packaging/appimage/Dockerfile
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
FROM ubuntu:24.04
|
||||
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.10.2 /uv /uvx /usr/local/bin/
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
binutils \
|
||||
ca-certificates \
|
||||
desktop-file-utils \
|
||||
fakeroot \
|
||||
file \
|
||||
libgdk-pixbuf2.0-bin \
|
||||
libglib2.0-bin \
|
||||
libgtk-3-bin \
|
||||
libfuse2 \
|
||||
librsvg2-bin \
|
||||
patchelf \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
squashfs-tools \
|
||||
strace \
|
||||
xz-utils \
|
||||
zsync \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN python3 -m pip install --no-cache-dir --break-system-packages \
|
||||
"packaging<21" \
|
||||
appimage-builder
|
||||
|
||||
WORKDIR /work
|
||||
28
packaging/appimage/build-appimage-docker.sh
Executable file
28
packaging/appimage/build-appimage-docker.sh
Executable file
|
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
IMAGE_NAME="${APPIMAGE_DOCKER_IMAGE:-scanslicer-appimage-builder}"
|
||||
HOST_UID="${HOST_UID:-$(id -u)}"
|
||||
HOST_GID="${HOST_GID:-$(id -g)}"
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "Missing required command: docker" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker build \
|
||||
-f "${ROOT_DIR}/packaging/appimage/Dockerfile" \
|
||||
-t "${IMAGE_NAME}" \
|
||||
"${ROOT_DIR}"
|
||||
|
||||
docker run --rm \
|
||||
-e HOST_UID="${HOST_UID}" \
|
||||
-e HOST_GID="${HOST_GID}" \
|
||||
-v "${ROOT_DIR}:/work" \
|
||||
-w /work \
|
||||
--entrypoint bash \
|
||||
"${IMAGE_NAME}" \
|
||||
-lc 'set -euo pipefail; bash packaging/appimage/build-appimage.sh; if [ -d /work/appimage ]; then chown -R "${HOST_UID}:${HOST_GID}" /work/appimage; fi'
|
||||
|
||||
echo "Docker AppImage build complete. Output in ${ROOT_DIR}/appimage/dist"
|
||||
51
packaging/appimage/build-appimage.sh
Executable file
51
packaging/appimage/build-appimage.sh
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
APPIMAGE_ROOT="${ROOT_DIR}/appimage"
|
||||
BUILD_DIR="${APPIMAGE_ROOT}/build"
|
||||
APPDIR="${BUILD_DIR}/AppDir"
|
||||
DIST_DIR="${APPIMAGE_ROOT}/dist"
|
||||
|
||||
APPIMAGE_BUILDER_BIN="${APPIMAGE_BUILDER_BIN:-appimage-builder}"
|
||||
|
||||
for cmd in uv "${APPIMAGE_BUILDER_BIN}"; do
|
||||
if ! command -v "${cmd}" >/dev/null 2>&1; then
|
||||
echo "Missing required command: ${cmd}" >&2
|
||||
echo "See docs/appimage.md for setup instructions." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p "${BUILD_DIR}" "${DIST_DIR}"
|
||||
rm -rf "${APPDIR}"
|
||||
mkdir -p "${APPDIR}"
|
||||
|
||||
cd "${ROOT_DIR}"
|
||||
uv export \
|
||||
--frozen \
|
||||
--no-dev \
|
||||
--no-emit-project \
|
||||
--no-hashes \
|
||||
--format requirements-txt \
|
||||
--output-file "${BUILD_DIR}/requirements.txt"
|
||||
uv build --wheel --out-dir "${BUILD_DIR}"
|
||||
|
||||
WHEEL_PATH="$(ls -1 "${BUILD_DIR}"/scanslicer-*.whl | head -n 1)"
|
||||
if [[ -z "${WHEEL_PATH}" ]]; then
|
||||
echo "Could not find built wheel in ${BUILD_DIR}" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf "%s\n" "${WHEEL_PATH}" >> "${BUILD_DIR}/requirements.txt"
|
||||
|
||||
export SCANSLICER_ROOT="${ROOT_DIR}"
|
||||
export SCANSLICER_APPDIR="${APPDIR}"
|
||||
export SCANSLICER_REQUIREMENTS="${BUILD_DIR}/requirements.txt"
|
||||
|
||||
cd "${BUILD_DIR}"
|
||||
"${APPIMAGE_BUILDER_BIN}" --recipe "${ROOT_DIR}/packaging/appimage/AppImageBuilder.yml"
|
||||
|
||||
mkdir -p "${DIST_DIR}"
|
||||
find "${BUILD_DIR}" -maxdepth 1 -type f \( -name "*.AppImage" -o -name "*.zsync" \) -exec mv -f {} "${DIST_DIR}/" \;
|
||||
|
||||
echo "AppImage build complete. Output in ${DIST_DIR}"
|
||||
9
packaging/appimage/scanslicer.desktop
Normal file
9
packaging/appimage/scanslicer.desktop
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=ScanSlicer
|
||||
Comment=Detect, straighten and save photos from flatbed scans
|
||||
Exec=scanslicer %F
|
||||
Icon=scanslicer
|
||||
Terminal=false
|
||||
Categories=Graphics;Photography;
|
||||
StartupWMClass=ScanSlicer
|
||||
7
packaging/appimage/scanslicer.svg
Normal file
7
packaging/appimage/scanslicer.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||
<rect x="16" y="16" width="224" height="224" rx="24" fill="#2d3748"/>
|
||||
<rect x="40" y="40" width="176" height="176" rx="16" fill="#4a5568"/>
|
||||
<rect x="68" y="68" width="120" height="80" rx="8" fill="#e2e8f0"/>
|
||||
<rect x="68" y="160" width="52" height="20" rx="4" fill="#90cdf4"/>
|
||||
<rect x="136" y="160" width="52" height="20" rx="4" fill="#f6ad55"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 450 B |
Loading…
Add table
Add a link
Reference in a new issue