[PR #2900] fix: build and run on distro Qt by dropping 6.5+ API dependencies #3007

Open
opened 2026-10-14 21:06:50 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/amnezia-vpn/amnezia-client/pull/2900
Author: @Mezo-oz
Created: 7/29/2026
Status: 🔄 Open

Base: dev ← Head: feat/context-menu-qt64-compat


📝 Commits (3)

  • 7f0356c fix: drop Qt 6.7+ API dependencies so the client builds on distro Qt
  • 2e717b3 fix: support the pre-6.5 deploy script signature on both call sites
  • e523c5d fix: let the question drawers load their content on older Qt

📊 Changes

8 files changed (+110 additions, -26 deletions)

View changed files

📝 client/CMakeLists.txt (+31 -7)
📝 client/ui/qml/Components/QuestionDrawer.qml (+0 -2)
📝 client/ui/qml/Components/SubscriptionExpiredDrawer.qml (+0 -2)
📝 client/ui/qml/Controls2/ContextMenuType.qml (+18 -1)
📝 client/ui/qml/Controls2/TextAreaType.qml (+15 -3)
📝 client/ui/qml/Controls2/TextAreaWithFooterType.qml (+15 -3)
📝 client/ui/qml/Controls2/TextFieldWithHeaderType.qml (+15 -3)
📝 service/server/CMakeLists.txt (+16 -5)

📄 Description

The client required Qt 6.9 without ever declaring it, so on older Qt it built cleanly and then failed at runtime. Every version-gated API involved turned out to be avoidable, so this removes the dependencies rather than raising the minimum.

Five blockers, in the order a build hits them:

API Requires Change
OUTPUT_SCRIPT (was FILENAME_VARIABLE) 6.5 branch on Qt6_VERSION
DEPLOY_TOOL_OPTIONS 6.7 passed only on ≥ 6.7
popupType: Popup.Native 6.8 removed
ContextMenu.menu attached type 6.9 explicit MouseArea + Menu.popup()
pragma ComponentBehavior: Bound 6.5 removed from two files — see below

There are two deploy-script call sites, not one: client/CMakeLists.txt uses qt_generate_deploy_qml_app_script (Qt6QmlMacros) and service/server/CMakeLists.txt uses qt_generate_deploy_app_script (Qt6CoreMacros). They live in different Qt modules and changed signature together.

The keyword sets were read off the Qt 6.4 sources rather than the documentation, which describes only the current signature — Qt 6.4 accepts TARGET / FILENAME_VARIABLE and no multi-value options at all.

The context menu

ContextMenu.menu is replaced by a MouseArea accepting only Qt.RightButton, so left press and drag still reach the text control for cursor placement, selection and flicking. Confirmed by hand on a real display: the menu opens on right-click, Cut/Copy enable and disable with the selection, and normal editing is unaffected.

One decision worth the team's call

QuestionDrawer.qml and SubscriptionExpiredDrawer.qml carry pragma ComponentBehavior: Bound, and DrawerType2 instantiates their content through an always-active Loader — outside its creation context, which Qt 6.4 rejects:

Cannot instantiate bound component outside its creation context

The Loader then reports status Error and its item stays null, so the drawer opens with no text and no buttons. The confirmation dialogs in the server, protocol and config removal flows cannot be acted on. Isolated reproduction, same code on both versions:

Qt 6.4.2 Qt 6.10.2
Loader status 3 (Error) 1 (Ready)
item null created

The pragma can be dropped from these two files without any behaviour change: it was added in b457ef9a together with qualifying every reference (text: headerText → text: root.headerText), so the files already satisfy what it enforces. Verified identical results on 6.4.2 and 6.10.2 after removal.

That said, it does remove a lint guard — a future edit could introduce unqualified access in those two files without a compile-time error. Happy to restore the pragma and set the minimum at 6.5 instead if you prefer that trade. AwgTextField.qml keeps its pragma either way, since it is used as a direct type and never instantiated through a Loader.

Declaring the minimum

find_package(Qt6 ...) had no version constraint, which is why an unsupported Qt produced a runtime QML failure instead of a configure-time error. It now declares 6.4, so falling below the supported minimum fails immediately and names both versions:

Could not find a configuration file for package "Qt6" that is compatible
with requested version "6.4".

6.4.2, 6.8.2 and 6.10.2 were each built and run; 6.5 through 6.7 were not tested, as no distro to hand ships them. The floor is set to the lowest version actually exercised. If you would rather it track the oldest Qt you intend to support, that number is easy to change — the point is that it is declared rather than implicit.

Verification

Raspberry Pi 5, aarch64. Built and run on each:

Qt Source Build Runs
6.4.2 Debian 12 bookworm client + service ✅
6.8.2 Debian 13 trixie, native client + service ✅ + right-click menu confirmed on a real display
6.10.2 Ubuntu 26.04 — ✅

"Runs" means the QML engine loads and the client reaches Started AmneziaVPN version 5.0.0.2; before these changes it failed with QQmlApplicationEngine failed to load component.

CI is unaffected — the workflows install Qt 6.10.1, which takes the same branches as today.

Related: #1324, where ARM64 Linux users are affected first because Qt publishes no official aarch64 desktop binaries, making distro Qt the only option there.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/amnezia-vpn/amnezia-client/pull/2900 **Author:** [@Mezo-oz](https://github.com/Mezo-oz) **Created:** 7/29/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `feat/context-menu-qt64-compat` --- ### 📝 Commits (3) - [`7f0356c`](https://github.com/amnezia-vpn/amnezia-client/commit/7f0356c52a2dce067fd5a07cd0562d020577b1b4) fix: drop Qt 6.7+ API dependencies so the client builds on distro Qt - [`2e717b3`](https://github.com/amnezia-vpn/amnezia-client/commit/2e717b324dc1328b221fff40a614654c28cb197f) fix: support the pre-6.5 deploy script signature on both call sites - [`e523c5d`](https://github.com/amnezia-vpn/amnezia-client/commit/e523c5dd37d076128153088bf624191b4294da31) fix: let the question drawers load their content on older Qt ### 📊 Changes **8 files changed** (+110 additions, -26 deletions) <details> <summary>View changed files</summary> 📝 `client/CMakeLists.txt` (+31 -7) 📝 `client/ui/qml/Components/QuestionDrawer.qml` (+0 -2) 📝 `client/ui/qml/Components/SubscriptionExpiredDrawer.qml` (+0 -2) 📝 `client/ui/qml/Controls2/ContextMenuType.qml` (+18 -1) 📝 `client/ui/qml/Controls2/TextAreaType.qml` (+15 -3) 📝 `client/ui/qml/Controls2/TextAreaWithFooterType.qml` (+15 -3) 📝 `client/ui/qml/Controls2/TextFieldWithHeaderType.qml` (+15 -3) 📝 `service/server/CMakeLists.txt` (+16 -5) </details> ### 📄 Description The client required Qt 6.9 without ever declaring it, so on older Qt it built cleanly and then failed at runtime. Every version-gated API involved turned out to be avoidable, so this removes the dependencies rather than raising the minimum. Five blockers, in the order a build hits them: | API | Requires | Change | |---|---|---| | `OUTPUT_SCRIPT` (was `FILENAME_VARIABLE`) | 6.5 | branch on `Qt6_VERSION` | | `DEPLOY_TOOL_OPTIONS` | 6.7 | passed only on ≥ 6.7 | | `popupType: Popup.Native` | 6.8 | removed | | `ContextMenu.menu` attached type | 6.9 | explicit `MouseArea` + `Menu.popup()` | | `pragma ComponentBehavior: Bound` | 6.5 | removed from two files — see below | There are **two** deploy-script call sites, not one: `client/CMakeLists.txt` uses `qt_generate_deploy_qml_app_script` (Qt6QmlMacros) and `service/server/CMakeLists.txt` uses `qt_generate_deploy_app_script` (Qt6CoreMacros). They live in different Qt modules and changed signature together. The keyword sets were read off the Qt 6.4 sources rather than the documentation, which describes only the current signature — Qt 6.4 accepts `TARGET` / `FILENAME_VARIABLE` and no multi-value options at all. ### The context menu `ContextMenu.menu` is replaced by a `MouseArea` accepting only `Qt.RightButton`, so left press and drag still reach the text control for cursor placement, selection and flicking. Confirmed by hand on a real display: the menu opens on right-click, Cut/Copy enable and disable with the selection, and normal editing is unaffected. ### One decision worth the team's call `QuestionDrawer.qml` and `SubscriptionExpiredDrawer.qml` carry `pragma ComponentBehavior: Bound`, and `DrawerType2` instantiates their content through an always-active `Loader` — outside its creation context, which Qt 6.4 rejects: ``` Cannot instantiate bound component outside its creation context ``` The `Loader` then reports status `Error` and its `item` stays null, so the drawer opens with no text and no buttons. The confirmation dialogs in the server, protocol and config removal flows cannot be acted on. Isolated reproduction, same code on both versions: | | Qt 6.4.2 | Qt 6.10.2 | |---|---|---| | Loader status | 3 (Error) | 1 (Ready) | | `item` | null | created | The pragma can be dropped from these two files without any behaviour change: it was added in b457ef9a together with qualifying every reference (`text: headerText` → `text: root.headerText`), so the files already satisfy what it enforces. Verified identical results on 6.4.2 and 6.10.2 after removal. That said, it does remove a lint guard — a future edit could introduce unqualified access in those two files without a compile-time error. **Happy to restore the pragma and set the minimum at 6.5 instead if you prefer that trade.** `AwgTextField.qml` keeps its pragma either way, since it is used as a direct type and never instantiated through a `Loader`. ### Declaring the minimum `find_package(Qt6 ...)` had no version constraint, which is why an unsupported Qt produced a runtime QML failure instead of a configure-time error. It now declares `6.4`, so falling below the supported minimum fails immediately and names both versions: ``` Could not find a configuration file for package "Qt6" that is compatible with requested version "6.4". ``` 6.4.2, 6.8.2 and 6.10.2 were each built and run; 6.5 through 6.7 were not tested, as no distro to hand ships them. The floor is set to the lowest version actually exercised. If you would rather it track the oldest Qt you intend to support, that number is easy to change — the point is that it is declared rather than implicit. ### Verification Raspberry Pi 5, aarch64. Built and run on each: | Qt | Source | Build | Runs | |---|---|---|---| | 6.4.2 | Debian 12 bookworm | client + service | ✅ | | 6.8.2 | Debian 13 trixie, native | client + service | ✅ + right-click menu confirmed on a real display | | 6.10.2 | Ubuntu 26.04 | — | ✅ | "Runs" means the QML engine loads and the client reaches `Started AmneziaVPN version 5.0.0.2`; before these changes it failed with `QQmlApplicationEngine failed to load component`. CI is unaffected — the workflows install Qt 6.10.1, which takes the same branches as today. Related: #1324, where ARM64 Linux users are affected first because Qt publishes no official aarch64 desktop binaries, making distro Qt the only option there. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#3007
No description provided.