ADR 0045: v0.2.0-alpha, and packaging finally built on pinned old bases¶
Status¶
Accepted
Context¶
A real batch of user-facing work has landed since v0.1.0-alpha: the
mouse hit-test drift fix, the italic glyph clipping fix, the
diagnostic underline redesign, the empty-buffer welcome overlay,
faster global easing, and full floating-panel isolation with a themed
quit-confirmation dialog. That's new functionality, not just fixes —
worth a real version, not a patch.
Separately, docs/feedback/0001 recorded two real, still-open
packaging bugs from the first external review: the .deb requires Qt
6.11 (Debian stable ships 6.10.2) and the AppImage requires glibc 2.43
— both because they were built natively on this rolling-release Arch
machine, baking in whatever happens to be newest here instead of a
real, portable minimum. That was deliberately deferred to "a future
batch of fixes" rather than fixed in isolation. This is that batch.
Decision¶
Version: 0.2.0¶
CMakeLists.txt's project(VERSION 0.2.0) — every consumer
(ASE_VERSION_STRING, the packaging scripts' version detection, the
About panel) reads from this one place already, so nothing else needed
a matching edit. Still -alpha (appended at the GUI compile-definition
level, per ADR 0033) — nowhere near feature-complete for v1 yet.
.deb built inside debian:bookworm (current stable), not natively¶
packaging/debian/build-deb.sh was already written to derive its
dependency floor from whatever machine actually runs it (ldd +
dpkg -S against the just-built binary) — the bug was never the
script, it was running it on the wrong machine. Run via
docker run -v <repo>:/src -w /src debian:bookworm ... build-deb.sh
instead, so the recorded Depends: line reflects Debian stable's own
Qt6 packages (6.4.2 in bookworm), achievable on the distributions this
format actually targets.
Building inside the container surfaced a second real, previously-
invisible bug in the script itself: ldd reports library paths through
/lib, which on a usrmerge system (Debian/Ubuntu today) is a symlink
to /usr/lib — but dpkg -S does a literal path match against its
own database, which records the canonical /usr/lib path. Every Qt6
library silently failed that lookup and got dropped from Depends
entirely; the .deb "built successfully" with no Qt6 dependency at
all. Fixed with readlink -f before the dpkg -S call. Would never
have been caught building natively on Arch, which doesn't have dpkg
at all — the script's own || true fallback silently swallowed the
lookup failure there instead of surfacing it.
AppImage built inside ubuntu:22.04, not natively¶
Same root cause as the .deb, same fix shape. Ubuntu 22.04 is the
standard, widely-used choice for Qt6 AppImages specifically: old
enough to keep the glibc floor low (2.35, vastly older than this dev
machine's), and new enough to have Qt6 available as a native apt
package (qt6-base-dev, 6.2.4 here) — unlike 20.04, which predates
Debian/Ubuntu packaging Qt6 at all.
A real environment gap, not a script bug: --no-install-recommends
(used for a lean container image) drops OpenGL headers, which some of
Qt6's own CMake package-config files transitively find_dependency()
on — without them, find_package(Qt6 COMPONENTS Widgets) reported not
found even with Qt6 itself fully installed, tripping the very
FATAL_ERROR this project added in the previous release for exactly
this "Qt6 missing" case (working as designed — it was right to fail
loudly here). Fixed by adding libgl-dev to the container's package
list; nothing in the project's own CMake needed to change.
Arch PKGBUILD unaffected¶
Not rebuilt in a container — a PKGBUILD is a recipe makepkg runs
on the user's own system, so it never bakes in a build-host version
floor the way a distributed binary (.deb, AppImage) does. Only its
pkgver/_tag/sha256sums needed updating for the new tag.
Consequences¶
Closes docs/feedback/0001 items 1 and 2 for real:
.deb: installed cleanly viaapt-get install ./ase_*.debinside a freshdebian:bookwormcontainer (a separate one from the build, so nothing lingered from having Qt6 already unpacked) and launched successfully —Depends:now correctly includeslibqt6core6/libqt6gui6/libqt6widgets6/libqt6dbus6alongside a full, realistic transitive list (fonts, X11, ICU, ...).- AppImage:
objdump -Ton the bundled binary shows aGLIBC_2.34ceiling, down from2.43— confirmed by actually running the built.AppImageon this dev machine's real X11 display, not just inspecting it.
One diagnostic detour worth recording: smoke-testing the AppImage
headlessly inside a bare ubuntu:22.04 container (no desktop
packages at all beyond what the Dockerfile-equivalent install line
above added) surfaced missing libX11/libxcb/libfontconfig/
libfreetype/libharfbuzz/GL-stack libraries. That's not a bundling
bug — linuxdeploy deliberately excludes exactly this class of library
(X11/GL are tied to the host's display/driver stack; fontconfig/
freetype are tied to the host's actual font configuration, and
bundling a mismatched copy causes worse problems than relying on the
host's own). A bare server-style container simply isn't a realistic
stand-in for "a Linux desktop," which always has these already —
confirmed by installing a minimal, realistic desktop library set and
then, more conclusively, by running the actual AppImage for real.
Containerized builds are slower and need Docker, but the pinned base is the correct fix, matching real AppImage/Debian-packaging convention rather than a workaround.
Addendum: the containers caught exactly what they were for¶
Cutting v0.3.0-alpha, the .deb build failed outright:
error: 'QVector<unsigned char>' has no member named 'assign'
QList::assign() arrived in Qt 6.6. debian:bookworm ships Qt 6.4,
ubuntu:22.04 ships Qt 6.2. The call went in with ADR 0053's render
hot-path fix and had been on main through several rounds of work,
because every build since was native on this rolling-release machine —
Qt 6.10, where it compiles fine. Neither package had been buildable
for that entire stretch, and nothing said so.
That is precisely the failure this ADR introduced the pinned bases to catch, and it only surfaced because a release was cut. Two changes so the next one surfaces sooner and louder:
fill()instead ofassign()— same operation, available since Qt 5.find_package(Qt6 6.2 ...), so a too-old Qt fails at configure time with a version number instead of at 84% of a compile with a missing-member error. The floor is stated, not implied by whatever happens to compile.
The remaining gap, stated plainly: nothing runs a pinned-base build except a human cutting a release. A CI job doing one build against the floor on every push is the real fix; until then this will be found the same way again.