Skip to content

Commit 1931227

Browse files
ten9876claude
andauthored
ci(appimage): build aarch64 against Qt 6.8.3 LTS and enable QRhi spectrum rendering (#4670)
The aarch64 AppImage was the only artifact still building against the distro's Qt. It shipped **Qt 6.4.2** while x86_64, macOS Intel and Windows all pin 6.8.3 — so README's "Release binaries ship Qt 6.8.3 LTS" was simply untrue for the Pi build, and the platform least likely to have a modern Qt available got the oldest one. ## Why it was like that, and why that reason is gone Commit `49ea8a50` (2026-03) split ARM onto system Qt with an explicit reason: > Qt doesn't provide prebuilt ARM64 Linux binaries via aqtinstall. That expired and nobody re-checked. Verified against aqt directly: ``` $ aqt list-qt linux_arm64 desktop 6.8.0 6.8.1 6.8.2 6.8.3 6.9.0 ... 6.12.0 $ aqt list-qt linux_arm64 desktop --arch 6.8.3 linux_gcc_arm64 ``` All four modules this build needs (`qtmultimedia`, `qtwebsockets`, `qtserialport`, `qtshadertools`) are published for `6.8.3 linux_gcc_arm64`, so the x86_64 recipe transplants directly. **6.8.3, not a newer 6.8.** Qt's 6.8 LTS goes commercial-only after 6.8.3: 6.8.4 is source-only and 6.8.5+ are absent from the open-source repo entirely. 6.8.3 is the newest 6.8 LTS obtainable under our licence, and it is what every other artifact already pins. ## The runner stays on noble, and must An earlier revision of this branch moved aarch64 to `ubuntu-22.04-arm` to lower the AppImage's glibc floor, on the assumption that jammy would do for ARM what it does for x86_64. It will not, and that change has been reverted. Qt does not build the two Linux hosts on the same base: ``` linux_x64 → qtbase-Linux-RHEL_8_10-GCC-Linux-RHEL_8_10-X86_64.7z linux_arm64 → qtbase-Linux-Ubuntu_24_04-GCC-Linux-Ubuntu_24_04-AARCH64.7z ``` The "old glibc, new Qt" property x86_64 enjoys comes from Qt shipping its x64 build from RHEL 8.10, not from the runner: `readelf -V` on the shipped libraries gives **max `GLIBC_2.27` for x86_64 and `GLIBC_2.38` for arm64**. Jammy is 2.35, so the arm64 Qt cannot run there at all — the job would die at the aqt step's `qmake -query`, on release day. The asymmetry is Qt's, not ours. The floor therefore has two contributors: Qt sets a hard lower bound of 2.38 that no runner can undercut, and the app's own objects add the builder's glibc on top, so the artifact assembled on noble floors at **2.39** — unchanged from what ships today. Practical consequence for the target platform: Raspberry Pi OS **Trixie** (glibc 2.41) is the supported Pi baseline; **Bookworm** (2.36) cannot run it. That was already true of the current aarch64 AppImage, so it is not a regression — but "Qt 6.8.3 on the Pi" and "runs on Bookworm" cannot both be had from Qt's prebuilt arm64 binaries, and that trade would need its own decision. ## Four latent traps this had to clear 1. **Four** separate steps hardcoded `.../Qt/6.8.3/gcc_64` — configure, `QMAKE` for `linuxdeploy-plugin-qt`, the multimedia-plugin copy, and the env export. Flipping aarch64 to aqt while missing any one would have pointed the ARM build at an x86_64 Qt. Now derived once into `QT_ROOT`, with an assertion that `qmake` exists there — a wrong path would otherwise pass configure via system Qt and only surface as a mis-deployed AppImage. 2. The glslc steps gated on `runner == 'ubuntu-22.04'` vs `!=`, which assumed "not jammy" meant "noble" — an equivalence that holds only by accident of the current matrix. Both legs need glslc and only the *source* differs, so that is now an explicit `glslc_source` matrix key (`lunarg` / `apt`) driving the LunarG repo step and both install steps. 3. The multimedia plugin copy ended in `|| true`, so a wrong path shipped an AppImage with no multimedia backend and a green build. Dropped. 4. `AETHER_GPU_SPECTRUM` defaults ON and auto-disables only below Qt 6.7, so the bump would have flipped QRhi rendering on as a silent side effect. Now set explicitly per-arch — see below. ## What must NOT be gated on `require_gpu` Worth recording, because this branch got it wrong once and it is a genuinely easy mistake: `REQUIRE_ASR_GPU` is the **release guard** — it makes a missing GPU toolchain *fatal* at configure time. It is not the enable switch. `ENABLE_ASR_VULKAN` defaults ON on everything non-Apple, so the aarch64 leg has been resolving `find_package(Vulkan COMPONENTS glslc)` against noble's own arm64 `glslc` package and compiling ggml-vulkan into the shipped AppImage all along. The v26.7.4.1 release run says so verbatim: ``` Get:2 http://ports.ubuntu.com/ubuntu-ports noble/universe arm64 glslc arm64 2023.8-1build1 -- ASR: Vulkan GPU backend enabled (glslc: /bin/glslc) -- Enabling coopmat glslc support ``` Gating the glslc install on `require_gpu` would have taken that backend away with no error at all — `Vulkan_glslc_FOUND` false, `GGML_VULKAN=OFF`, `REQUIRE_ASR_GPU=OFF` so nothing fails. Green build, backend gone. `glslc_source` avoids that: the ARM AppImage keeps exactly the ASR backends it ships today, and this PR changes only Qt and the spectrum renderer. ## GPU spectrum rendering on aarch64 Enabled deliberately. The CPU QPainter fallback on ARM was never a decision about ARM; it was Qt 6.4.2 sitting below the 6.7 QRhiWidget floor with CMake auto-disabling accordingly — the last release log shows exactly that: `GPU spectrum rendering disabled (requires Qt 6.7+, found 6.4.2)`. 6.8.3 clears it, so the Pi gets the same renderer as everything else. **Asserted, not assumed.** `=ON` is only a request — CMakeLists silently flips it back OFF when `Qt6GuiPrivate` isn't located, and it names aqtinstall specifically as a layout that ships private QtGui headers while omitting the `Qt6GuiPrivate` CMake package. That is exactly what both legs now use, so a release could ship the CPU fallback with a green workflow. A new step greps the configure output and fails the job otherwise. Confirmed this resolves on both legs rather than assumed: neither the `linux_gcc_64` nor the `linux_gcc_arm64` tree ships a `Qt6GuiPrivate` CMake package, and both ship `include/QtGui/6.8.3/QtGui/private/qhighdpiscaling_p.h`, which is what the `DEBIAN_PRIVATE_INC` fallback walks `Qt6::Gui`'s include dirs looking for. The x86_64 leg of the last release already prints the pair the assertion depends on: ``` -- Qt6GuiPrivate CMake package not found, searching for private headers directly... -- GPU spectrum rendering enabled (QRhi, Qt 6.8.3) ``` Configure also now tees under `set -o pipefail` so a cmake failure still fails the step. ## Verification and what is NOT verified Verified: aqt package/module/arch availability for `linux_arm64`; the installed arm64 tree's layout (`Qt/6.8.3/gcc_arm64/bin/qmake`, so the `${QT_DIR#linux_}` derivation is right), its `plugins/multimedia/*` and bundled `libav*`, and `bin/qsb`; `readelf -V` glibc requirements on both hosts' `libQt6Gui.so.6`; the absence of `Qt6GuiPrivate` and presence of the private headers on both; `ubuntu-24.04-arm` is a GA runner label; both v26.7.4.1 AppImage job logs for the ASR-Vulkan and GPU-spectrum evidence above; `actionlint` clean apart from the two pre-existing `SC2046` warnings on `-j$(nproc)` that also fire on `main`. Also verified, since it looks like a trap and isn't one: `pip3 install aqtinstall` needs no `--break-system-packages` on `ubuntu-24.04-arm`. GitHub's image build writes `/etc/pip.conf` with `break-system-packages = true` on every non-jammy Ubuntu image, arm64 included (`images/ubuntu/scripts/build/install-python.sh`, guarded by `if ! is_ubuntu22`). **Not verified:** this workflow only fires on tag pushes, so CI here will not exercise it — the first real run is a release. The Pi on hand is offline, so the resulting aarch64 AppImage is untested on hardware and whether Mesa V3D drives QRhi acceptably on a Pi 5 is unknown. The assertion guarantees the renderer is compiled in, not that it performs well; `AETHER_NO_GPU=1` (now documented in the README) is the no-rebuild fallback if it does not. A `workflow_dispatch` run on this branch before tagging would derisk the build itself. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 65222e8 commit 1931227

3 files changed

Lines changed: 157 additions & 42 deletions

File tree

.github/workflows/appimage.yml

Lines changed: 131 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,38 @@ jobs:
1616
include:
1717
- runner: ubuntu-22.04
1818
arch: x86_64
19-
use_aqt: true
19+
qt_host: linux
20+
qt_arch: linux_gcc_64
2021
require_gpu: 'ON' # x86_64 ships the whisper Vulkan GPU backend
22+
gpu_spectrum: 'ON' # unchanged: Qt 6.8.3 already enabled it here
23+
glslc_source: lunarg
24+
# Stays on noble, and must. Qt builds its linux_arm64 desktop binaries
25+
# on Ubuntu 24.04 (the packages are literally named
26+
# Linux-Ubuntu_24_04-GCC-...-AARCH64), and the shipped libQt6Gui.so.6
27+
# requires GLIBC_2.38 — verified with readelf on the downloaded 6.8.3
28+
# arm64 tree. Jammy is 2.35, so building this Qt there cannot work.
29+
# The x86_64 leg above CAN sit on jammy because Qt builds its x64
30+
# binaries against an older base; the asymmetry is Qt's, not ours.
2131
- runner: ubuntu-24.04-arm
2232
arch: aarch64
23-
use_aqt: false
24-
require_gpu: 'OFF' # ARM/Pi ships CPU-only (no Vulkan expected)
33+
qt_host: linux_arm64
34+
qt_arch: linux_gcc_arm64
35+
# require_gpu is the RELEASE GUARD, not the enable switch: it makes a
36+
# missing GPU toolchain fatal at configure time. ENABLE_ASR_VULKAN
37+
# defaults ON on non-Apple, so aarch64 has been building ggml-vulkan
38+
# all along from noble's own glslc — the v26.7.4.1 release log says
39+
# "ASR: Vulkan GPU backend enabled (glslc: /bin/glslc)". It stays OFF
40+
# here only because arm64 GPU support is best-effort: whether any
41+
# given ARM host has a Vulkan driver worth using is not something a
42+
# release should hard-fail on. Do not read this as "no Vulkan".
43+
require_gpu: 'OFF' # best-effort ASR GPU on ARM, not a hard requirement
44+
# QRhi spectrum rendering, ON deliberately. It was impossible on
45+
# aarch64 until now purely because Ubuntu's Qt 6.4.2 sits below the
46+
# 6.7 QRhiWidget floor — the CPU QPainter fallback was a symptom of
47+
# the stale Qt, not a choice about ARM. Qt 6.8.3 clears that floor,
48+
# so the Pi gets the same renderer as every other platform.
49+
gpu_spectrum: 'ON'
50+
glslc_source: apt
2551

2652
runs-on: ${{ matrix.runner }}
2753

@@ -42,8 +68,8 @@ jobs:
4268
# x86_64 stays on jammy deliberately: it keeps the AppImage's glibc floor
4369
# low enough for older distros, so bumping the runner would trade this
4470
# breakage for a wider, quieter one.
45-
- name: Add LunarG Vulkan SDK repository (Ubuntu 22.04)
46-
if: matrix.runner == 'ubuntu-22.04'
71+
- name: Add LunarG Vulkan SDK repository (jammy)
72+
if: matrix.glslc_source == 'lunarg'
4773
run: |
4874
wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc \
4975
| sudo tee /etc/apt/trusted.gpg.d/lunarg.asc > /dev/null
@@ -76,14 +102,23 @@ jobs:
76102
#
77103
# This workflow only runs on tag pushes, so a break here is invisible
78104
# until release day — hence the explicit assertions on both legs.
79-
- name: Install glslc (Ubuntu 24.04+)
80-
if: matrix.runner != 'ubuntu-22.04'
105+
#
106+
# BOTH legs need glslc; only the source differs, which is what the
107+
# glslc_source matrix key names. Gating on the runner label instead made
108+
# `!= 'ubuntu-22.04'` a proxy for "noble" that holds only by accident of
109+
# the current matrix and breaks the moment another jammy-family runner is
110+
# added. Do NOT gate this on require_gpu: that flag is the release guard
111+
# (fatal-if-missing), not the enable switch — ENABLE_ASR_VULKAN defaults
112+
# ON everywhere non-Apple, so gating glslc on require_gpu would silently
113+
# drop ggml-vulkan from the aarch64 AppImage with a green build.
114+
- name: Install glslc from apt (noble and newer)
115+
if: matrix.glslc_source == 'apt'
81116
run: |
82117
sudo apt-get install -y glslc
83118
glslc --version
84119
85-
- name: Install glslc + SDK headers from LunarG (Ubuntu 22.04)
86-
if: matrix.runner == 'ubuntu-22.04'
120+
- name: Install glslc + SDK headers from LunarG (jammy)
121+
if: matrix.glslc_source == 'lunarg'
87122
run: |
88123
sudo apt-get install -y shaderc vulkan-headers
89124
glslc --version
@@ -96,25 +131,59 @@ jobs:
96131
grep -q 'VK_EXT_pipeline_robustness' /usr/include/vulkan/vulkan_core.h \
97132
|| { echo "ERROR: Vulkan headers predate VK_EXT_pipeline_robustness — ggml-vulkan will not build"; exit 1; }
98133
99-
- name: Install system Qt (ARM only)
100-
if: matrix.use_aqt == false
101-
run: |
102-
sudo apt-get install -y qt6-base-dev qt6-multimedia-dev \
103-
qt6-websockets-dev qt6-serialport-dev qt6-base-private-dev \
104-
qt6-shader-baker qt6-shadertools-dev \
105-
libhidapi-dev portaudio19-dev libfftw3-dev
106-
107-
- name: Install Qt 6.8 LTS via aqtinstall (x86_64)
108-
if: matrix.use_aqt == true
134+
# Both arches now take aqt. aarch64 used to build against the distro's Qt
135+
# because, when the split landed (49ea8a50, 2026-03), Qt published no
136+
# prebuilt ARM64 Linux binaries — the commit says exactly that. Qt has
137+
# shipped linux_arm64 desktop builds since 6.7, so the reason expired and
138+
# nobody re-checked: aarch64 was still on Ubuntu's Qt 6.4.2 while every
139+
# other artifact shipped 6.8.3, and README's "Release binaries ship Qt
140+
# 6.8.3 LTS" was simply untrue for the Pi build.
141+
#
142+
# 6.8.7 is not reachable here: Qt's 6.8 LTS goes commercial-only after
143+
# 6.8.3, so 6.8.4 is source-only and 6.8.5+ are not published to the open
144+
# -source repo at all. 6.8.3 is the newest 6.8 LTS with prebuilt binaries
145+
# under the open-source licence, which is what every other artifact pins.
146+
#
147+
# The aarch64 AppImage's glibc floor has two contributors. Qt sets the hard
148+
# lower bound: the arm64 6.8.3 tree needs GLIBC_2.38 (readelf -V on the
149+
# shipped libQt6Gui.so.6), so no runner choice can take it below that. The
150+
# app's own objects then link against the builder's glibc on top, so the
151+
# artifact assembled on noble floors at 2.39. Target check against that: Pi
152+
# OS Trixie is glibc 2.41 (Debian 13, Mesa 25.0.7) and runs it; Pi OS
153+
# Bookworm is 2.36 and cannot. Bookworm is not a regression here — today's
154+
# aarch64 AppImage already builds on noble and already floors at 2.39 — but
155+
# it does mean Trixie is the supported Pi baseline, and that should stay
156+
# true when this Qt pin moves.
157+
- name: Install Qt 6.8.3 LTS via aqtinstall
109158
run: |
110159
pip3 install aqtinstall
111-
aqt install-qt linux desktop 6.8.3 linux_gcc_64 \
160+
aqt install-qt ${{ matrix.qt_host }} desktop 6.8.3 ${{ matrix.qt_arch }} \
112161
-m qtmultimedia qtwebsockets qtserialport qtshadertools \
113162
--outputdir ${{ github.workspace }}/Qt
114-
echo "Qt6_DIR=${{ github.workspace }}/Qt/6.8.3/gcc_64/lib/cmake/Qt6" >> $GITHUB_ENV
115-
echo "CMAKE_PREFIX_PATH=${{ github.workspace }}/Qt/6.8.3/gcc_64" >> $GITHUB_ENV
116-
echo "PATH=${{ github.workspace }}/Qt/6.8.3/gcc_64/bin:$PATH" >> $GITHUB_ENV
117-
echo "LD_LIBRARY_PATH=${{ github.workspace }}/Qt/6.8.3/gcc_64/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV
163+
# aqt lays the install down under <version>/<arch minus the host
164+
# prefix>: linux_gcc_64 -> gcc_64, linux_gcc_arm64 -> gcc_arm64.
165+
# Derive it instead of hardcoding — FOUR separate steps used to spell
166+
# out ".../Qt/6.8.3/gcc_64" by hand, so flipping aarch64 onto aqt
167+
# without catching all four would have pointed the ARM build at an
168+
# x86_64 Qt. QT_ROOT is exported once and reused everywhere below.
169+
QT_DIR="${{ matrix.qt_arch }}"
170+
QT_ROOT="${{ github.workspace }}/Qt/6.8.3/${QT_DIR#linux_}"
171+
# Assert the layout rather than trusting it: a silently-wrong QT_ROOT
172+
# would sail through configure (system Qt would satisfy it) and only
173+
# show up as a subtly mis-deployed AppImage.
174+
if [ ! -x "$QT_ROOT/bin/qmake" ]; then
175+
echo "ERROR: no qmake at $QT_ROOT — aqt layout changed"
176+
ls -la "${{ github.workspace }}/Qt/6.8.3/" || true
177+
exit 1
178+
fi
179+
{
180+
echo "QT_ROOT=$QT_ROOT"
181+
echo "Qt6_DIR=$QT_ROOT/lib/cmake/Qt6"
182+
echo "CMAKE_PREFIX_PATH=$QT_ROOT"
183+
echo "PATH=$QT_ROOT/bin:$PATH"
184+
echo "LD_LIBRARY_PATH=$QT_ROOT/lib:$LD_LIBRARY_PATH"
185+
} >> "$GITHUB_ENV"
186+
"$QT_ROOT/bin/qmake" -query QT_VERSION
118187
119188
- name: Cache DeepFilterNet3
120189
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
@@ -145,10 +214,11 @@ jobs:
145214

146215
- name: Configure
147216
run: |
148-
CMAKE_EXTRA=""
149-
if [ "${{ matrix.use_aqt }}" = "true" ]; then
150-
CMAKE_EXTRA="-DCMAKE_PREFIX_PATH=${{ github.workspace }}/Qt/6.8.3/gcc_64"
151-
fi
217+
# Without pipefail the step's exit status is tee's, so a cmake failure
218+
# would look green. Set it in the script rather than via `shell: bash`
219+
# (which also implies -eo pipefail) so the guard is self-contained and
220+
# survives anyone editing the step's shell.
221+
set -o pipefail
152222
cmake -B build -G Ninja \
153223
-DCMAKE_BUILD_TYPE=Release \
154224
-DCMAKE_INSTALL_PREFIX=/usr \
@@ -157,9 +227,28 @@ jobs:
157227
-DREQUIRE_ASR_ONNX=ON \
158228
-DREQUIRE_ASR_SHERPA=ON \
159229
-DREQUIRE_ASR_GPU=${{ matrix.require_gpu }} \
230+
-DAETHER_GPU_SPECTRUM=${{ matrix.gpu_spectrum }} \
160231
-DMQTT_TLS=OFF \
161232
-DENABLE_NVIDIA_AFX=ON \
162-
$CMAKE_EXTRA
233+
-DCMAKE_PREFIX_PATH="$QT_ROOT" 2>&1 | tee configure.log
234+
235+
# AETHER_GPU_SPECTRUM=ON is a request, not a guarantee: CMake silently
236+
# flips it back OFF if Qt6GuiPrivate can't be located, and CMakeLists.txt
237+
# calls out aqtinstall by name as a layout that ships the private QtGui
238+
# headers on disk while omitting the Qt6GuiPrivate CMake package — which
239+
# is exactly what both legs of this matrix now use. Without this check a
240+
# release could quietly ship the CPU QPainter fallback while the workflow
241+
# stayed green, which is the failure mode this repo keeps getting bitten
242+
# by. Assert on the configure output instead of trusting the flag.
243+
- name: Assert GPU spectrum rendering actually enabled
244+
if: matrix.gpu_spectrum == 'ON'
245+
run: |
246+
grep -q "GPU spectrum rendering enabled" configure.log || {
247+
echo "ERROR: -DAETHER_GPU_SPECTRUM=ON but CMake disabled it. Relevant output:"
248+
grep -i "GPU spectrum\|Qt6GuiPrivate\|private headers" configure.log || true
249+
exit 1
250+
}
251+
grep "GPU spectrum rendering enabled" configure.log
163252
164253
- name: Build Opus (RADE dependency)
165254
run: cmake --build build --target build_opus -j$(nproc)
@@ -184,14 +273,15 @@ jobs:
184273
AppDir/usr/bin/
185274
fi
186275
187-
# Bundle Qt6 multimedia backend plugin
188-
if [ "${{ matrix.use_aqt }}" = "true" ]; then
189-
QT_PLUGIN_PATH=${{ github.workspace }}/Qt/6.8.3/gcc_64/plugins
190-
else
191-
QT_PLUGIN_PATH=$(qmake6 -query QT_INSTALL_PLUGINS 2>/dev/null || echo "/usr/lib/$(uname -m)-linux-gnu/qt6/plugins")
192-
fi
276+
# Bundle Qt6 multimedia backend plugin. Fourth and last site that
277+
# hardcoded the x86_64 Qt path; now derived from QT_ROOT like the rest.
278+
QT_PLUGIN_PATH="$QT_ROOT/plugins"
193279
mkdir -p AppDir/usr/plugins/multimedia
194-
cp -v "$QT_PLUGIN_PATH"/multimedia/* AppDir/usr/plugins/multimedia/ 2>/dev/null || true
280+
# No `|| true` here. This used to swallow every failure, so a wrong
281+
# plugin path produced an AppImage with no multimedia backend and a
282+
# green build — audio would simply not work for users. If the plugins
283+
# are missing, that is a broken release and the job should say so.
284+
cp -v "$QT_PLUGIN_PATH"/multimedia/* AppDir/usr/plugins/multimedia/
195285
196286
# Bundle essential GStreamer plugins for audio
197287
GST_PATH=$(pkg-config --variable=pluginsdir gstreamer-1.0 2>/dev/null || echo "/usr/lib/$(uname -m)-linux-gnu/gstreamer-1.0")
@@ -219,11 +309,11 @@ jobs:
219309
# sanitization windows-installer.yml already applies.
220310
SAFE_REF="${GITHUB_REF_NAME//[^A-Za-z0-9._-]/_}"
221311
export LDAI_OUTPUT="AetherSDR-${SAFE_REF}-${{ matrix.arch }}.AppImage"
222-
if [ "${{ matrix.use_aqt }}" = "true" ]; then
223-
export QMAKE=${{ github.workspace }}/Qt/6.8.3/gcc_64/bin/qmake
224-
else
225-
export QMAKE=$(which qmake6 2>/dev/null || which qmake)
226-
fi
312+
# linuxdeploy-plugin-qt locates the Qt to bundle via $QMAKE. This is
313+
# the third place that used to hardcode the x86_64 ".../gcc_64" path;
314+
# it now reuses the QT_ROOT exported by the aqt step, so there is one
315+
# source of truth for which Qt gets built AND deployed.
316+
export QMAKE="$QT_ROOT/bin/qmake"
227317
# Let linuxdeploy resolve + bundle the NEEDED libs staged under
228318
# third_party (outside the standard search path): libqt6keychain.so,
229319
# libsherpa-onnx-c-api.so, and libonnxruntime.so (the app links sherpa's

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
5252

5353
### Added
5454

55+
- **The aarch64 (Raspberry Pi / ARM) AppImage now ships Qt 6.8.3 LTS and
56+
GPU spectrum rendering (#4670).** It was the only release artifact still
57+
building against the distro's Qt — 6.4.2, while x86_64, macOS and Windows all
58+
pinned 6.8.3 — because Qt published no prebuilt ARM64 Linux binaries when that
59+
split was made. Qt has shipped them since 6.7, so the ARM build now takes the
60+
same aqtinstall recipe as everything else. The visible consequence is the
61+
renderer: 6.4.2 sat below the Qt 6.7 floor for `QRhiWidget`, so the ARM
62+
AppImage silently fell back to the CPU `QPainter` spectrum path. On 6.8.3 it
63+
renders through QRhi like every other platform. If a GPU or driver renders the
64+
spectrum incorrectly, `AETHER_NO_GPU=1` forces software OpenGL without a
65+
rebuild.
66+
67+
The Qt bump raises the aarch64 AppImage's glibc floor to 2.38 (Qt's arm64
68+
binaries are built on Ubuntu 24.04). Raspberry Pi OS **Trixie** (glibc 2.41)
69+
is the supported Pi baseline; Bookworm (2.36) cannot run it — as was already
70+
the case for the 2.39-floored builds this replaces.
71+
5572
- **The TCI PTT slice-routing decision is now logged (#4547).** Reports of TCI
5673
keying the wrong slice have been arriving without logs because there were
5774
none to send: the server logged audio, IQ, DAX and client connections, but

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,15 @@ cmake --build build --target AetherSDR
216216

217217
### Qt 6.7+ for GPU Spectrum Rendering
218218

219-
GPU-accelerated spectrum/waterfall rendering requires Qt 6.7 or greater. If your distribution ships with an older version (e.g., Ubuntu 24.04, Debian 12, or Mint 21–22 include Qt 6.4.2), the build system automatically disables GPU rendering and falls back to the CPU-based `QPainter` path. (Release binaries ship Qt 6.8.3 LTS; the 6.7 floor is the source-build minimum for QRhi.)
219+
GPU-accelerated spectrum/waterfall rendering requires Qt 6.7 or greater. If your distribution ships with an older version (e.g., Ubuntu 24.04, Debian 12, or Mint 21–22 include Qt 6.4.2), the build system automatically disables GPU rendering and falls back to the CPU-based `QPainter` path. (Release binaries ship Qt 6.8.3 LTS — the aarch64 AppImage included — so every release binary renders via QRhi; the 6.7 floor is the source-build minimum.)
220+
221+
Going the other way, `AETHER_NO_GPU=1` forces software OpenGL on an already-built binary, without a rebuild:
222+
223+
```bash
224+
AETHER_NO_GPU=1 ./AetherSDR-*.AppImage
225+
```
226+
227+
That is the escape hatch if a GPU or driver renders the spectrum incorrectly — worth trying first on Raspberry Pi and other systems whose Mesa driver is newer than its hardware.
220228

221229
To use GPU acceleration on these systems, install Qt 6.7+ manually:
222230

0 commit comments

Comments
 (0)