mirror of
https://github.com/aphrody-labs/deckcraft.git
synced 2026-10-14 03:29:07 +00:00
- release.yml: new linux-riscv64 job, ported from GridCraft. Cross-compiles on ubuntu-24.04 against ports.ubuntu.com riscv64 libs (incl. libasound2-dev:riscv64), packages a tar.gz and smoke-tests deckcraft-cli --version under QEMU. The release job needs it, so the draft and SHA256SUMS include it. - packaging/linux/package.sh: CROSS_ARCH/CROSS_TARGET/CROSS_COMPILE/EMULATOR support. - README Downloads: list the riscv64 tarball. - Version 0.4.0 -> 0.5.0 (cargo xtask version set). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
150 lines
6.7 KiB
Bash
Executable File
150 lines
6.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Build and package DeckCraft for Linux (<arch> is x86_64 or aarch64, or riscv64 when cross-compiling):
|
|
#
|
|
# $DIST/deckcraft-<version>-linux-<arch>.AppImage any distro with glibc >= the build host's
|
|
# $DIST/deckcraft-<version>-linux-<arch>.AppImage.zsync delta updates (needs zsyncmake)
|
|
# $DIST/deckcraft-<version>-linux-<arch>.deb Debian, Ubuntu, Mint, Pop!_OS, ...
|
|
# $DIST/deckcraft-<version>-linux-<arch>.rpm Fedora, openSUSE, RHEL, ...
|
|
# $DIST/deckcraft-<version>-linux-<arch>.tar.gz plain FHS-style tree (bin/, share/)
|
|
#
|
|
# Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm tar"]
|
|
#
|
|
# Needs: cargo; nfpm for deb/rpm (https://nfpm.goreleaser.com); appimagetool for the AppImage
|
|
# (downloaded into $CARGO_TARGET_DIR if missing). Build on an old distro (CI: Ubuntu 22.04,
|
|
# glibc 2.35) so the binaries run on newer ones. Optional: desktop-file-validate, appstreamcli,
|
|
# zsyncmake (the zsync package) for the AppImage's .zsync.
|
|
set -euo pipefail
|
|
# shellcheck source=../common.sh
|
|
. "$(dirname "${BASH_SOURCE[0]}")/../common.sh"
|
|
HERE="$ROOT/packaging/linux"
|
|
APP_ID=ai.storyteller.deckcraft
|
|
|
|
SKIP_BUILD=0
|
|
FORMATS="appimage deb rpm tar"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--skip-build) SKIP_BUILD=1; shift ;;
|
|
--formats) FORMATS="$2"; shift 2 ;;
|
|
-h | --help) sed -n '2,17p' "$0"; exit 0 ;;
|
|
*) echo "unknown argument: $1" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
ARCH="${CROSS_ARCH:-$(uname -m)}"
|
|
case "$ARCH" in
|
|
riscv64) DEB_ARCH=riscv64 ;;
|
|
x86_64) DEB_ARCH=amd64 ;;
|
|
aarch64 | arm64) ARCH=aarch64; DEB_ARCH=arm64 ;;
|
|
*) echo "unsupported architecture $ARCH" >&2; exit 2 ;;
|
|
esac
|
|
export DECKCRAFT_MAINTAINER="${DECKCRAFT_MAINTAINER:-DeckCraft maintainers <deckcraft@storyteller.ai>}"
|
|
BASENAME="deckcraft-$VERSION-linux-$ARCH"
|
|
|
|
echo "==> DeckCraft $VERSION for Linux $ARCH ($FORMATS)"
|
|
|
|
if [ "$SKIP_BUILD" = 0 ]; then
|
|
if [ -n "${CROSS_TARGET:-}" ]; then
|
|
(cd "$ROOT" && cargo build --release --locked -p deckcraft -p deckcraft-cli --target "$CROSS_TARGET")
|
|
else
|
|
(cd "$ROOT" && cargo build --release --locked -p deckcraft -p deckcraft-cli)
|
|
fi
|
|
fi
|
|
BIN="$CARGO_TARGET_DIR/${CROSS_TARGET:+$CROSS_TARGET/}release"
|
|
WORK="$CARGO_TARGET_DIR/linux-package"
|
|
STAGE="$WORK/root"
|
|
rm -rf "$WORK"
|
|
|
|
# ---- stage an FHS tree (shared by every format) -------------------------------------------------
|
|
install -Dm755 "$BIN/deckcraft" "$STAGE/usr/bin/deckcraft"
|
|
install -Dm755 "$BIN/deckcraft-cli" "$STAGE/usr/bin/deckcraft-cli"
|
|
"${CROSS_COMPILE:-}strip" "$STAGE/usr/bin/deckcraft" "$STAGE/usr/bin/deckcraft-cli" 2>/dev/null || true
|
|
install -Dm644 "$HERE/$APP_ID.desktop" "$STAGE/usr/share/applications/$APP_ID.desktop"
|
|
install -Dm644 "$HERE/$APP_ID.mime.xml" "$STAGE/usr/share/mime/packages/$APP_ID.xml"
|
|
mkdir -p "$STAGE/usr/share/metainfo"
|
|
sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$DECKCRAFT_BUILD_DATE/g" \
|
|
"$HERE/$APP_ID.metainfo.xml.in" >"$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml"
|
|
mkdir -p "$STAGE/usr/share/icons"
|
|
cp -R "$ROOT/assets/app-icon/hicolor" "$STAGE/usr/share/icons/"
|
|
mkdir -p "$STAGE/usr/share/doc/deckcraft"
|
|
copy_docs "$STAGE/usr/share/doc/deckcraft"
|
|
|
|
if command -v desktop-file-validate >/dev/null; then
|
|
desktop-file-validate "$STAGE/usr/share/applications/$APP_ID.desktop"
|
|
fi
|
|
if command -v appstreamcli >/dev/null; then
|
|
appstreamcli validate --no-net --explain "$STAGE/usr/share/metainfo/$APP_ID.metainfo.xml"
|
|
fi
|
|
|
|
has() { case " $FORMATS " in *" $1 "*) return 0 ;; *) return 1 ;; esac; }
|
|
|
|
# ---- .tar.gz ------------------------------------------------------------------------------------
|
|
if has tar; then
|
|
mkdir -p "$WORK/tar"
|
|
cp -R "$STAGE/usr" "$WORK/tar/$BASENAME"
|
|
tar -C "$WORK/tar" -czf "$DIST/$BASENAME.tar.gz" "$BASENAME"
|
|
echo "wrote $DIST/$BASENAME.tar.gz"
|
|
fi
|
|
|
|
# ---- .deb / .rpm --------------------------------------------------------------------------------
|
|
if has deb || has rpm; then
|
|
command -v nfpm >/dev/null || { echo "error: nfpm not found (https://nfpm.goreleaser.com/install/)" >&2; exit 1; }
|
|
export VERSION
|
|
export NFPM_ARCH="$DEB_ARCH"
|
|
# nfpm expands env vars in fields like `version` and `arch`, but not in `contents[].src`.
|
|
sed "s|\${STAGE}|$STAGE|g" "$HERE/nfpm.yaml" >"$WORK/nfpm.yaml"
|
|
for fmt in deb rpm; do
|
|
if has "$fmt"; then (cd "$ROOT" && nfpm package -f "$WORK/nfpm.yaml" -p "$fmt" -t "$DIST/$BASENAME.$fmt"); fi
|
|
done
|
|
fi
|
|
|
|
# ---- AppImage -----------------------------------------------------------------------------------
|
|
if has appimage; then
|
|
APPDIR="$WORK/DeckCraft.AppDir"
|
|
cp -R "$STAGE" "$APPDIR"
|
|
mv "$APPDIR/usr/share/doc" "$WORK/doc-unused"
|
|
ln -s usr/bin/deckcraft "$APPDIR/AppRun"
|
|
cp "$HERE/$APP_ID.desktop" "$APPDIR/$APP_ID.desktop"
|
|
cp "$ROOT/assets/app-icon/hicolor/256x256/apps/$APP_ID.png" "$APPDIR/$APP_ID.png"
|
|
ln -s "$APP_ID.png" "$APPDIR/.DirIcon"
|
|
|
|
TOOL="${APPIMAGETOOL:-$(command -v appimagetool || true)}"
|
|
if [ -z "$TOOL" ]; then
|
|
TOOL="$CARGO_TARGET_DIR/appimagetool-$ARCH.AppImage"
|
|
if [ ! -x "$TOOL" ]; then
|
|
curl -fsSL -o "$TOOL" "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$ARCH.AppImage"
|
|
chmod +x "$TOOL"
|
|
fi
|
|
fi
|
|
# Absolute, because appimagetool runs in $DIST below (CARGO_TARGET_DIR or APPIMAGETOOL may be
|
|
# relative).
|
|
OUT="$(cd "$DIST" && pwd)/$BASENAME.AppImage"
|
|
APPDIR="$(cd "$APPDIR" && pwd)"
|
|
TOOL="$(cd "$(dirname "$TOOL")" && pwd)/$(basename "$TOOL")"
|
|
# A .zsync left by an earlier run would hide a missing zsyncmake and describe another file.
|
|
rm -f "$OUT.zsync"
|
|
# Update information: AppImageUpdate, AppImageLauncher and the like read it from the file and
|
|
# fetch only the blocks that changed in a newer release, through the .zsync published next to
|
|
# each AppImage on GitHub Releases. `latest` is the newest published release that is not a
|
|
# pre-release. A fork's builds point at its own releases through GITHUB_REPOSITORY.
|
|
REPO="${GITHUB_REPOSITORY:-storytold/deckcraft}"
|
|
UPDATE_INFO="gh-releases-zsync|${REPO%%/*}|${REPO#*/}|latest|deckcraft-*-linux-$ARCH.AppImage.zsync"
|
|
# Extract-and-run: works without FUSE (containers, CI). The output embeds the static runtime,
|
|
# so users don't need libfuse2 either. With zsyncmake on the host (CI installs the zsync
|
|
# package) appimagetool also writes the .zsync, into its working directory, hence the cd.
|
|
(cd "$DIST" && ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream -u "$UPDATE_INFO" "$APPDIR" "$OUT")
|
|
echo "wrote $OUT"
|
|
if [ -s "$OUT.zsync" ]; then
|
|
echo "wrote $OUT.zsync"
|
|
else
|
|
warn "zsyncmake not found, so $OUT.zsync was not written; AppImage delta updates need it"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "${CROSS_TARGET:-}" ]; then
|
|
"$STAGE/usr/bin/deckcraft-cli" --version
|
|
elif [ -n "${EMULATOR:-}" ]; then
|
|
"$EMULATOR" "$STAGE/usr/bin/deckcraft-cli" --version
|
|
fi
|
|
echo "==> done"
|
|
ls -lh "$DIST"
|