Skip to content

Build system: define a safe QML cache policy for packaged upgrades #854

Description

@johnny9

Related build-time/AOT work: #695

Problem

Packaged builds currently embed QML through the manual resource file and allow Qt to read and write host-generated runtime cache files. That makes the persistent qmlcache part of the application upgrade contract even though it is not deployed with the executable.

This caused a reproducible Linux preview failure after upgrading with a cache created by an older preview:

  • affected artifact: v0.0.24/bitcoin-core-app-signet-x86_64-linux-gnu, SHA256 09370e03ea0170d5468d714b5bdb651863d508403c28a576e20543f8ce3b70f9
  • result with the existing cache: SIGSEGV in Qt's QQmlPropertyCacheCreator
  • result with a clean XDG_CACHE_HOME or after removing the QML cache: the same executable remains running

Qt documents source- and Qt-version checks for host cache files, but a stale cache must not be able to crash the application even if one of those checks does not protect an upgrade in practice.

Scope

#695 already tracks moving the QML sources to qt6_add_qml_module() so qmlcachegen compiles them ahead of time and catches invalid QML during the build. This issue tracks the complementary deployment policy:

  • packaged builds should use the ahead-of-time units embedded in the executable;
  • packaged builds should neither load nor write host-generated .qmlc/.jsc files for embedded application QML;
  • once Build system: enable Qt 6 QML cachegen for build-time QML syntax errors #695 supplies AOT units, set QML_DISK_CACHE=aot (or an equivalent Qt API/build configuration) before Qt initializes, so AOT units remain enabled while qmlc-read and qmlc-write remain disabled;
  • if any runtime-generated cache remains necessary, give it an explicit version/invalidation contract across application and Qt upgrades;
  • cover both cold launches and upgrades with a cache directory populated by the previous packaged build.

Qt's deployment guidance recommends qt_add_qml_module() and defines QML_DISK_CACHE=aot as loading only ahead-of-time native code and bytecode: https://doc.qt.io/qt-6/qmldiskcache.html

Immediate preview mitigation

The preview publisher can set QML_DISABLE_DISK_CACHE=1 before constructing the Qt application. That is intentionally temporary: without AOT units it recompiles embedded QML from source on each launch, but it removes the unsafe persistent cache from preview upgrades. A Linux launch smoke test should start with no cache-related environment variables supplied externally and fail if the app exits early or writes .qmlc/.jsc files.

Acceptance criteria

  • Release-style depends/Guix builds embed cachegen output for all packaged QML and JavaScript files.
  • The packaged app uses embedded AOT units and does not read or write host-generated QML cache files for those resources.
  • Linux and macOS cold-launch tests pass from an empty cache directory.
  • Linux and macOS upgrade tests pass when reusing a cache directory populated by the previous packaged build.
  • Cache policy initialization happens before Qt reads the relevant environment/configuration.
  • The temporary full disk-cache disable can be removed after the AOT-only policy is verified.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

  • Status
    Review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions