This commit is contained in:
Forrest 2026-08-06 21:32:28 -04:00
parent b6639fb1c9
commit 0a7af1d813
10 changed files with 743 additions and 35 deletions

113
packaging/build_deb.sh Executable file
View file

@ -0,0 +1,113 @@
#!/usr/bin/env bash
# Build a Debian/Ubuntu .deb for Timbre from the Flutter Linux release bundle.
#
# Works even on non-Debian hosts (e.g. Arch): a .deb is an `ar` archive of
# `debian-binary` + `control.tar.gz` + `data.tar.gz`, so we assemble it with
# `ar` + `tar` and never need `dpkg-deb`.
#
# Runtime deps are declared in the control file below. On Linux, media_kit
# loads the *system* libmpv at runtime (it is NOT bundled), so libmpv is a hard
# dependency. libsecret backs flutter_secure_storage; GTK backs the embedder.
#
# Usage: packaging/build_deb.sh [version] [arch]
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
VERSION="${1:-$(grep -m1 '^version:' pubspec.yaml | sed -E 's/version:\s*([0-9.]+).*/\1/')}"
ARCH="${2:-amd64}"
APPID="com.laforrestchurch.timbre"
BUNDLE="build/linux/x64/release/bundle"
OUT="build/deb"
PKGDIR="$OUT/timbre_${VERSION}_${ARCH}"
if [[ ! -x "$BUNDLE/timbre" ]]; then
echo "Release bundle not found at $BUNDLE — run: flutter build linux --release" >&2
exit 1
fi
echo "==> Staging package tree ($VERSION / $ARCH)"
rm -rf "$PKGDIR"
mkdir -p "$PKGDIR/opt/timbre" \
"$PKGDIR/usr/bin" \
"$PKGDIR/usr/share/applications" \
"$PKGDIR/usr/share/pixmaps" \
"$PKGDIR/usr/share/icons/hicolor/512x512/apps" \
"$PKGDIR/DEBIAN"
# App payload → /opt/timbre; /usr/bin/timbre is a symlink (Flutter resolves
# lib/ and data/ relative to the resolved executable path via /proc/self/exe).
cp -r "$BUNDLE/." "$PKGDIR/opt/timbre/"
ln -sf /opt/timbre/timbre "$PKGDIR/usr/bin/timbre"
# Icon (into pixmaps for universal fallback + hicolor for modern launchers).
cp assets/icon/icon.png "$PKGDIR/usr/share/pixmaps/timbre.png"
cp assets/icon/icon.png "$PKGDIR/usr/share/icons/hicolor/512x512/apps/timbre.png"
cat > "$PKGDIR/usr/share/applications/${APPID}.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=Timbre
Comment=Subsonic music client
Exec=timbre
Icon=timbre
Terminal=false
Categories=AudioVideo;Audio;Player;
StartupWMClass=${APPID}
EOF
INSTALLED_KB="$(du -sk "$PKGDIR/opt" "$PKGDIR/usr" | awk '{s+=$1} END {print s}')"
cat > "$PKGDIR/DEBIAN/control" <<EOF
Package: timbre
Version: ${VERSION}
Section: sound
Priority: optional
Architecture: ${ARCH}
Maintainer: Forrest <lchurch@conversionpath.com>
Installed-Size: ${INSTALLED_KB}
Depends: libgtk-3-0 | libgtk-3-0t64, libmpv2 | libmpv1, libsecret-1-0
Recommends: avahi-daemon
Description: Timbre — a Subsonic music client
A Subsonic client for streaming your music library. Audio is played through
libmpv, so it lands on the system mixer (PipeWire/PulseAudio) where a system
equalizer such as EasyEffects can shape it.
EOF
# postinst/postrm: refresh desktop + icon caches when the tools exist (no-op
# otherwise). Non-fatal so install never breaks on a minimal system.
cat > "$PKGDIR/DEBIAN/postinst" <<'EOF'
#!/bin/sh
set -e
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database -q /usr/share/applications || true
fi
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
gtk-update-icon-cache -q /usr/share/icons/hicolor || true
fi
EOF
cp "$PKGDIR/DEBIAN/postinst" "$PKGDIR/DEBIAN/postrm"
chmod 0755 "$PKGDIR/DEBIAN/postinst" "$PKGDIR/DEBIAN/postrm"
# md5sums for every payload file (relative paths, no ./ prefix — dpkg style).
( cd "$PKGDIR" && find opt usr -type f -print0 | xargs -0 md5sum > DEBIAN/md5sums )
echo "==> Assembling .deb"
BUILD="$OUT/_assemble"
rm -rf "$BUILD"; mkdir -p "$BUILD"
echo "2.0" > "$BUILD/debian-binary"
# control.tar.gz from DEBIAN/ contents; data.tar.gz from the filesystem tree.
tar --owner=0 --group=0 --numeric-owner -czf "$BUILD/control.tar.gz" -C "$PKGDIR/DEBIAN" .
tar --owner=0 --group=0 --numeric-owner -czf "$BUILD/data.tar.gz" \
-C "$PKGDIR" --exclude=./DEBIAN .
DEB="$OUT/timbre_${VERSION}_${ARCH}.deb"
rm -f "$DEB"
# Member order is mandated by the .deb format: debian-binary, control, data.
( cd "$BUILD" && ar rc "$OLDPWD/$DEB" debian-binary control.tar.gz data.tar.gz )
rm -rf "$BUILD"
echo "==> Built: $DEB"
ls -lh "$DEB"
echo "==> Contents (ar members):" && ar t "$DEB"