Skip to content

2.0.11-rc3 fixes - #1688

Merged
tdewey-rpi merged 15 commits into
mainfrom
dev/tdewey/2.0.11-rc3-fixes
Aug 13, 2026
Merged

2.0.11-rc3 fixes#1688
tdewey-rpi merged 15 commits into
mainfrom
dev/tdewey/2.0.11-rc3-fixes

Conversation

@tdewey-rpi

Copy link
Copy Markdown
Collaborator

No description provided.

Pin curl, libarchive, libusb, nghttp2, xz, zlib and zstd as git
submodules under src/dependencies/vendor and build them from source via
CMake (fetch-vendor.cmake + per-dependency *.cmake). This links the
imager against known-good upstream versions independent of the host
distribution.
Add a patch fixing Qt6 QTestSupport chrono atomics on 32-bit targets
(armhf) and adjust the shared Qt build helper and armhf build notes.
Add a release pipeline that builds the desktop, CLI and embedded
AppImages and wraps them into .debs for amd64, arm64 and armhf. The host
architecture builds locally; foreign arches build in rootless mmdebstrap
chroots, with prebuilt AppImages and Qt injected via bind mounts.

Includes release.sh orchestration, chroot/mirror/keyring helpers,
per-arch apt sources, Qt caching and the updated packaging metadata
(rules, control, changelog, install files).
Retarget the rootless mmdebstrap chroots from trixie to bookworm and
parameterise the apt source templates on CHROOT_DIST, adding the bookworm
sources those templated paths resolve to.

Packaging fixes on top of that pipeline:

* build-source.sh collected three of the four files listed in
  _source.changes; the generated _source.buildinfo was destroyed with the
  temporary build directory, so the source upload referenced a file that
  was never written out.

* The chroot build path never invoked linuxdeploy, so the AppImages
  bundled Qt and nothing else, silently resolving around twenty libraries
  from the host (PCRE2, zstd, brotli, GnuTLS, glib, double-conversion,
  liburing). Cross-architecture builds never invoked it either, since
  linuxdeploy cannot introspect foreign binaries, so arm64 and armhf had
  never been bundled correctly. Replace it with
  appimage_deploy_lib_closure(), which walks DT_NEEDED using readelf and
  so works unchanged on a foreign-architecture AppDir, and which fails the
  build rather than silently under-bundling.

* The embedded package copies Qt from a hand-maintained list but copies
  the QML tree wholesale, so sixteen libraries its plugins reference were
  never shipped: libQt6Quick could not resolve libQt6QmlModels or
  libQt6OpenGL, and the QtQuick.Controls plugin could not resolve
  libQt6QuickControls2. Complete the closure there too, additively, so the
  curated list stays authoritative for payload size.

* Build Qt with -no-feature-icu. No ICU-backed Qt feature is used (UTF-8
  conversion only, no QCollator, timezones handled as IANA identifier
  strings) and it was enabled purely by configure autodetection. Saves
  about 12.6 MB per binary package and removes the per-release libicu
  soname pin that tied the packages to a single Debian release.

* Prune the QML tree to the eight modules the UI imports, with one policy
  shared between the AppImage and embedded paths. Each unused module's
  plugin links a Qt library of its own, so pruning modules is what removes
  the libraries; libQt6QmlWorkerScript is retained because libQt6QmlMeta
  links it directly.

* Drop the JPEG 2000 image format plugin, staged on amd64 only, whose
  libjasper dependency was never shipped or declared.

* Declare the host-coupled libraries all three packages resolve from the
  system. dh_shlibdeps cannot inspect an AppImage payload, so these were
  previously undeclared.

Verified across amd64, arm64 and armhf plus embedded: ELF machine types
match their filename architecture, 60/60 checksums verify, and the
dependency sets are exactly right in both directions with nothing
under-declared and nothing surplus.
A singular `user:` block is merged over the distro's default_user from
/etc/cloud/cloud.cfg, which upstream populates with
`sudo: ["ALL=(ALL) NOPASSWD:ALL"]` for every variant including
raspberry-pi-os. Omitting the key therefore inherited passwordless sudo
via /etc/sudoers.d/90-cloud-init-users regardless of what the user chose.

Emit `sudo: null` explicitly, which suppresses the sudoers rules while
still inheriting the default user's groups, so the account keeps `sudo`
group membership and is simply prompted for a password. `false` behaves
the same but has been deprecated since cloud-init 22.2.
…_uring

file_operations_linux.cpp uses io_uring_sqe_set_data64 and
io_uring_prep_cancel64, added in liburing 2.2. Some distributions ship an
older liburing that provides the library but not these helpers (Ubuntu
22.04 carries 2.1), where pkg-config succeeds and the build then fails to
link.

Compile-probe for the two helpers and gate both -DHAVE_LIBURING and the
link against the result, warning and falling back to synchronous writes
when the library is present but too old.
A package built against the host's libraries is not the package it claims
to be. Building on a newer glibc than bookworm yields binaries that will
not start on bookworm at all; building on an older one silently drops
features -- a host with liburing < 2.2 fails the io_uring API probe and
produces a functionally slower binary -- and in both cases the artifact
still gets labelled for bookworm. Nothing in the artifact reveals which
happened.

BUILDER=auto/local existed as an escape hatch for environments that could
not run sbuild. The rootless mmdebstrap chroots removed that constraint:
they need no sudo, and CHROOT_AUTO_CREATE=auto creates them on demand, so
there is no environment that cannot use one. Nothing in the tree selected
it, and no CI referenced it.

Remove choose_builder() and the BUILDER variable, the _local_build()
branches in build-appimages.sh, and build-binary-local.sh, which becomes
unreachable. build-embedded.sh had a separate host-arch shortcut that never
consulted BUILDER at all -- invisible today only because the embedded
package is arm64-only and is built on amd64 -- so make that unconditional
too.

Rebuilt all three architectures plus embedded: identical output, 60/60
checksums verify, ELF machine types match their filename architecture.
The embedded package shipped through a standalone path in create-embedded.sh
that hand-wrote its own DEBIAN/control, so it diverged from debian/control:
the Depends stanza was stale (missing the host-coupled libraries the vendored
tree needs), it carried no md5sums, and its version (2.0.10) did not match the
other packages. Route the packaging through debhelper instead, so debian/control
is the single source of the package's dependencies and metadata:

* create-embedded.sh now stages the vendored /opt tree and assembles the .deb
  with dh_gencontrol / dh_md5sums / dh_builddeb. Version is taken from the
  changelog (2.0.10-1), md5sums are generated, and Depends come from
  debian/control. dh_shlibdeps is deliberately not used -- on a vendored /opt
  tree it demands ~19 libraries from the target that are bundled precisely so a
  netboot micro image need not carry them -- so debian/control lists the
  genuinely-external libraries (C/C++ runtime, GPU stack, X11, libsystemd)
  explicitly.

* Bake the deployed rpath in at build time (CMAKE_INSTALL_RPATH=$ORIGIN/../lib,
  CMAKE_BUILD_WITH_INSTALL_RPATH). The binary was copied to /opt carrying the
  cmake build rpath, an absolute build-host path: a privacy leak, a
  reproducibility hazard, and the reason dpkg-shlibdeps could not resolve the
  bundled libraries.

* Dereference the fontconfig conf.d symlinks (cp -rL) so the bundle is
  self-contained instead of shipping 21 links that dangle on a target without
  fontconfig installed.

* Remove the ICU detection and copy code. Qt is built with -no-feature-icu, so
  no ICU is linked or bundled; the code only ever emitted a spurious
  "ICU not found" warning.

* CONTRIBUTING.md: document the real build (debian/release.sh embedded arm64),
  dropping the obsolete build-qt-embedded.sh and dpkg-buildpackage steps.

Verified on the rebuilt arm64 package: version 2.0.10-1, md5sums present,
Depends complete (external closure fully covered, nothing surplus), binary
rpath $ORIGIN/../lib with no build-host path in any shipped ELF, no dangling
symlinks, no ICU, 83/83 ELF objects aarch64.
The embedded (linuxfb netboot) target runs on a pi-gen-micro image with no
session bus (SYSTEMD=0) and a five-package base. Linking QtDBus there is pure
liability: it drags in libQt6DBus -> libdbus-1 -> libsystemd, none of which the
image carries, so the binary could not even load.

Nothing embedded actually needs DBus at runtime. The three DBus users degrade
to nothing useful on that image anyway: the XDG portal file dialog (embedded
already forces QML dialogs), the NetworkManager WiFi-credential backend (no NM
daemon to read from), and the Pi Connect rpi-imager:// URI handler (no browser
to sign in from).

Drop Qt6::DBus from find_package/link for BUILD_EMBEDDED. With it unlinked Qt's
QT_DBUS_LIB macro goes undefined, which compiles out the guarded DBus paths:
platformquirks_linux.cpp already used that guard; extend it to the main.cpp
single-instance/URI-handler blocks and to nativefiledialog_linux.cpp (whose
portal implementation falls back to the QML dialog stub). Platform.cmake routes
embedded to the existing CLI stubs for the WiFi-credential and suspend-inhibitor
backends and drops the NetworkManager and URI-handler sources.

Desktop and CLI builds are unchanged (desktop keeps DBus; CLI never had it).
Embedded was quietly using the desktop release Qt, which is built with OpenGL,
DBus and (by autodetection) ICU. On the pi-gen-micro netboot image that is
wrong on every count: there is no Mesa (far too large for a network-loaded
image), no session bus, and the embedded build ships none of the complex-script
languages that could want ICU. The result linked libEGL/libGL/libX11 and
libQt6DBus and would not load on the target at all.

Build a dedicated embedded Qt as its own cache variant (gcc_arm64_embedded),
configured -no-opengl -qpa linuxfb (software rendering over DRM, no GL/X11),
-no-dbus, and -no-feature-icu. Remove the custom from-source ICU build from
build-qt-embedded.sh -- it cloned and compiled ICU only to feed a feature we no
longer enable, and needs network access the chroot does not have.

Wire the variant into the release pipeline: qt_embedded_path()/qt_embedded_ok()
in lib.sh, and build-embedded.sh builds it on cache miss and passes it to
create-embedded.sh. The cache-miss check is by file presence, not qt_embedded_ok
(which runs `qmake -query`): the cached qmake is arm64 and the orchestrator runs
on the host, so executing it would always fail and force a needless full Qt
rebuild.

Embedded is arm64 only -- the only platform the netboot installer targets.
With the app built without QtDBus and Qt built -no-opengl, the vendored tree no
longer references libQt6DBus, libEGL/libGL or libX11. Two loose ends remained:

create-embedded.sh still copied libQt6DBus and libdbus-1 in explicitly. The
libQt6DBus copy carried a "# Required by linuxfb plugin" comment, but that was a
misattribution: libqlinuxfb.so never linked it -- the app binary did (via the
unconditional Qt6::DBus link, now removed), and the copy had been added in the
same debugging pass as the genuine linuxfb input libraries. Drop both copies;
they only dragged libdbus-1 -> libsystemd back in, and libsystemd is absent from
the netboot image.

debian/control still declared libegl1/libgl1/libopengl0/libx11-6/libsystemd0 in
the embedded Depends. These are now not merely unnecessary but harmful: apt
enforces Depends when building the image, so declaring them would pull Mesa and
X11 into it -- exactly the bloat the -no-opengl build exists to avoid. Trim the
Depends to the genuinely-external, base-provided set.

Verified on the rebuilt package: external sonames down to five (ld-linux, libc,
libm, libgcc_s, libstdc++), no libEGL/libGL/libX11/libQt6DBus/libdbus/libsystemd
anywhere, no ICU, md5sums present, version 2.0.10-1.
@tdewey-rpi
tdewey-rpi force-pushed the dev/tdewey/2.0.11-rc3-fixes branch from 97b31e8 to 83aa533 Compare August 12, 2026 13:51
@tdewey-rpi
tdewey-rpi merged commit 38087f8 into main Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant