workflow: crossbuild-essential-arm64 + CONFIG_SITE
Some checks failed
Forgejo Release postit-deb / release (push) Failing after 3m59s

The previous two attempts (wget + dpkg-deb -x from packages.debian.org,
apt-get install libc6:arm64) were wrong approaches. The
Debian-recommended way is the crossbuild-essential-<ARCH> meta-package,
which pulls in:

  - gcc-aarch64-linux-gnu / g++-aarch64-linux-gnu (cross-gcc, unused
    for our managed-only build but installed for consistency)
  - binutils-aarch64-linux-gnu (provides aarch64-linux-gnu-objdump
    needed by dh_makeshlibs — replaces the previous binutils-only
    install)
  - libc6-dev:arm64, linux-libc-dev:arm64 (cross-libc for dpkg-shlibdeps
    to resolve the arm64 binaries' NEEDED entries against the system
    shlibs cache)
  - dpkg-cross CONFIG_SITE files under /etc/dpkg-cross/

With crossbuild-essential-arm64 installed:
  - dh_makeshlibs finds its aarch64-linux-gnu-objdump ✓
  - dh_shlibdeps can resolve arm64 binaries against the on-host shlibs
    cache ✓
  - dpkg-buildpackage -Pcross,nocheck runs cleanly

The environment for the arm64 make deb is now:

  CONFIG_SITE=/etc/dpkg-cross/cross-config.arm64 \
    DEB_HOST_ARCH=arm64 DEB_BUILD_ARCH=amd64 \
    DEB_BUILD_OPTIONS=nocheck \
    make deb POSTIT_GIT_TAG= POSTIT_RUNTIME=linux-arm64

which matches the Debian cross-build recipe documented at
https://wiki.debian.org/CrossCompiling (Build without a build
environment section).

debian/rules also drops the now-unused override_dh_shlibdeps
override (the stage dir hack) — standard dh_shlibdeps now
works because the cross-libc is installed.
This commit is contained in:
Paul Schneider 2026-08-17 19:26:11 +01:00
commit 41ab11d7b9
No known key found for this signature in database
GPG key ID: 1E66C65EE2B46F1B
2 changed files with 32 additions and 96 deletions

View file

@ -74,88 +74,24 @@ jobs:
# via `convert`, librsvg2-bin pour le SVG). # via `convert`, librsvg2-bin pour le SVG).
run: | run: |
apt-get update apt-get update
# crossbuild-essential-arm64 is the official Debian
# meta-package for arm64 cross-compilation. It pulls
# in gcc-aarch64-linux-gnu, binutils-aarch64-linux-gnu,
# libc6-dev:arm64, linux-libc-dev:arm64, and sets up
# dpkg-cross (CONFIG_SITE under /etc/dpkg-cross/).
# For our package, the key bits are:
# - binutils-aarch64-linux-gnu (provides
# aarch64-linux-gnu-objdump needed by dh_makeshlibs)
# - libc6-dev:arm64 and friends (so dpkg-shlibdeps can
# resolve the arm64 binaries' NEEDED entries against
# the cross-arch shlibs cache installed on the host).
# The arm64 gcc isn't strictly needed (we have no C
# code to compile — only dotnet publish), but it doesn't
# hurt and keeps the environment consistent for any
# future C-coded debhelper rules.
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
build-essential debhelper imagemagick librsvg2-bin \ build-essential debhelper imagemagick librsvg2-bin \
ca-certificates binutils-aarch64-linux-gnu ca-certificates crossbuild-essential-arm64
# 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.)
# by name. We don't install arm64 on the host (heavy),
# but dpkg-shlibdeps accepts -l<dir> to point at
# additional library search paths. Download the
# deb.debian.org arm64 .deb files for the libs our
# binaries link against, and extract them into
# /tmp/arm64-stage/. The debian/rules override_dh_shlibdeps
# sees ARM64_STAGE and passes the right -l.
#
# 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<dir> 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
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
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/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
# the PostIt.Desktop arm64 binary. Without it, dh_makeshlibs
# fails with "Can't exec 'aarch64-linux-gnu-objdump': No
# such file or directory" (~50 Mo, standard cross-toolkit
# binutils — no arm64 GCC needed because there's no C code to
# compile, only .NET to publish).
#
# We don't install libc6:arm64 etc. — dpkg-buildpackage -d
# skips the build-deps check (we don't need the arm64 SDK),
# and -Pcross toggles the cross-build profile so debhelper
# adapts to the cross-build context.
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
: > "$STATE_FILE" : > "$STATE_FILE"
@ -303,7 +239,16 @@ jobs:
# set -x traces every command so a silent failure inside # set -x traces every command so a silent failure inside
# 'make deb' (e.g. dpkg-buildpackage aborting after the # 'make deb' (e.g. dpkg-buildpackage aborting after the
# 'mv ... || true' swallows the error) is visible. # 'mv ... || true' swallows the error) is visible.
ARM64_STAGE=/tmp/arm64-stage make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-arm64 || { # Debian-recommended cross-build environment for dpkg-buildpackage:
# - CONFIG_SITE points autoconf at the cross-config for arm64
# (set up by crossbuild-essential-arm64)
# - DEB_HOST_ARCH=arm64 is the target architecture
# - DEB_BUILD_ARCH=amd64 stays the build host
# - DEB_BUILD_OPTIONS=nocheck skips tests in the cross context
CONFIG_SITE=/etc/dpkg-cross/cross-config.arm64 \
DEB_HOST_ARCH=arm64 DEB_BUILD_ARCH=amd64 \
DEB_BUILD_OPTIONS=nocheck \
make deb POSTIT_GIT_TAG="$TAG" POSTIT_RUNTIME=linux-arm64 || {
echo "::error::make deb for arm64 exited non-zero — see output above" echo "::error::make deb for arm64 exited non-zero — see output above"
exit 1 exit 1
} }

21
debian/rules vendored
View file

@ -126,21 +126,12 @@ override_dh_auto_test:
# client). Build smoke is sufficient for the package. # client). Build smoke is sufficient for the package.
override_dh_shlibdeps: override_dh_shlibdeps:
# If a stage of arm64 libraries has been extracted into # The runner image installs crossbuild-essential-arm64, which
# $(ARM64_STAGE)/usr/lib/aarch64-linux-gnu/ (by the # provides libc6-dev:arm64 et al. plus dpkg-cross — enough
# upstream fetch-arm64-libs.sh script wired into the # for dh_shlibdeps to resolve the arm64 binaries' NEEDED
# Forgejo Actions workflow), point dpkg-shlibdeps at it # entries against the system's shlibs cache directly. No
# with -l so it can resolve ELF NEEDED entries from the # stage dir, no -l hack: standard dh_shlibdeps just works.
# arm64 binaries (libc.so.6, libstdc++.so.6, etc.) without dh_shlibdeps
# installing arm64 on the amd64 host.
if [ -n "$(ARM64_STAGE)" ] && [ -d "$(ARM64_STAGE)/usr/lib/aarch64-linux-gnu" ]; then \
echo " --> dpkg-shlibdeps: using arm64 stage at $(ARM64_STAGE)"; \
dh_shlibdeps -- -l"$(ARM64_STAGE)/usr/lib/aarch64-linux-gnu"; \
else \
dh_shlibdeps -- \
--warnings=0 \
-l"$(DEB_HOST_MULTIARCH_DIR)" 2>/dev/null || true; \
fi
override_dh_strip: override_dh_strip:
# dh_strip disabled entirely. See MEMORY.md / AGENTS.md for the # dh_strip disabled entirely. See MEMORY.md / AGENTS.md for the