diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml
index d70ca39..927e64e 100644
--- a/.forgejo/workflows/release.yml
+++ b/.forgejo/workflows/release.yml
@@ -76,7 +76,7 @@ jobs:
apt-get update
apt-get install -y --no-install-recommends \
build-essential debhelper imagemagick librsvg2-bin \
- ca-certificates binutils-aarch64-linux-gnu wget
+ ca-certificates binutils-aarch64-linux-gnu
# For the arm64 cross-build, dpkg-shlibdeps needs to
# resolve ELF NEEDED entries from the arm64 binaries
# (libc.so.6, libstdc++.so.6, libdl, libpthread, etc.)
@@ -91,26 +91,58 @@ jobs:
# We download only what's necessary, not full multi-arch —
# keeps the runner lean and the network round-trips short.
if [ "$(POSTIT_RUNTIME)" = "linux-arm64" ]; then
+ # For arm64 cross-build, dpkg-shlibdeps needs to
+ # resolve ELF NEEDED entries from arm64 binaries
+ # (libc.so.6, libstdc++.so.6, libdl, libpthread,
+ # libfontconfig, etc.) by name. We don't install
+ # arm64 on the host (heavy), but dpkg-shlibdeps
+ # accepts -l
for additional library search
+ # paths — like sbuild/pbuilder do internally.
+ #
+ # apt-get install libc6:arm64 failed in early runs:
+ # the arm64 packages weren't listed in the apt
+ # sources configured in the runner image. So we
+ # wget the .deb directly from deb.debian.org and
+ # extract them with dpkg-deb -x into a stage dir.
+ #
+ # We resolve the filename dynamically through
+ # the Packages index instead of hardcoding
+ # versions — that way Debian security uploads
+ # (libc6 glibc patches are frequent) don't break
+ # the workflow.
mkdir -p /tmp/arm64-stage
- cd /tmp/arm64-stage
- # Bookworm (Debian 12 — matches the runner image base).
- BASE=https://deb.debian.org/debian/pool/main
- for pkg in \
- "$BASE/g/glibc/libc6_2.36-9+deb12u11_arm64.deb" \
- "$BASE/g/gcc-12/libstdc++6_12.2.0-14+deb12u1_arm64.deb" \
- "$BASE/f/fontconfig/libfontconfig1_2.14.1-4_arm64.deb" \
- "$BASE/f/freetype/libfreetype6_2.12.1+dfsg-5+deb12u4_arm64.deb" \
- "$BASE/g/gtk+3.0/libgtk-3-0_3.24.38-2~deb12u3_arm64.deb"; do
- fname=$(basename "$pkg")
- if [ ! -f "$fname" ] && ! wget -q "$pkg" -O "$fname"; then
- echo "::error::Failed to download $pkg"
+ set -e
+ for src in libc6 libstdc++6 libfontconfig1 \
+ libfreetype6 libgtk-3-0; do
+ # Look up the .deb URL from the apt index for
+ # the architecture-less library source name.
+ # apt-get download would do this for free if
+ # arm64 were installed — but it isn't, so we
+ # query via the Packages.gz on deb.debian.org.
+ url=$(wget -qO- \
+ "https://packages.debian.org/bookworm/arm64/${src}/download" \
+ 2>/dev/null \
+ | grep -oE 'http[s]?://[^"]*'"${src}"'_[^"]*arm64\.deb' \
+ | head -1)
+ if [ -z "$url" ]; then
+ echo "::error::Could not resolve .deb URL for $src"
exit 1
fi
- dpkg-deb -x "$fname" /tmp/arm64-stage/
+ echo " --> downloading $url"
+ if ! wget -q "$url" -O "/tmp/${src}.deb"; then
+ echo "::error::wget failed for $url"
+ exit 1
+ fi
+ dpkg-deb -x "/tmp/${src}.deb" /tmp/arm64-stage/
+ rm -f "/tmp/${src}.deb"
done
- ls /tmp/arm64-stage/usr/lib/aarch64-linux-gnu/ | head -10
- echo " arm64 stage ready at /tmp/arm64-stage/"
- cd "${{GITHUB_WORKSPACE:-/}}"
+ ls /tmp/arm64-stage/lib/aarch64-linux-gnu/ 2>/dev/null | head -3 || true
+ ls /tmp/arm64-stage/usr/lib/aarch64-linux-gnu/ 2>/dev/null | head -3 || true
+ echo " --> arm64 stage ready at /tmp/arm64-stage/"
+ fi
+ # Extract the freshly downloaded .deb into the
+ # stage dir.
+ ls ${src}_*.deb
fi
# binutils-aarch64-linux-gnu provides aarch64-linux-gnu-objdump,
# which dh_makeshlibs needs to read the ELF symbol table of