From db151c2920629a709ae9cbca371da420ed3b7516 Mon Sep 17 00:00:00 2001 From: jwinterm Date: Sat, 12 Sep 2026 20:49:23 -0400 Subject: [PATCH] fix(ci/macos): bundle the QML modules the app actually imports 5.1.2 shipped a grey mining tab on macOS while Linux was fine. The app said why: 'qrc:/qml/mining.qml:2:1: module "QtQuick.Layouts" is not installed', and Contents/Resources held only appicon.icns and qt.conf, with no qml directory at all. macdeployqt cannot scan .qrc resources, and it was called without -qmldir, so the bundle shipped no QML modules; scene.qml survived only because it imports nothing beyond QtQuick. Pass -qmldir, then blanket-copy the QtQuick and QtQml trees as the AppImage build already does, because qmlimportscanner does not follow a module's own qmldir depends chain. Both happen before the dylib passes so new plugin deps resolve, and before signing, which already sweeps every non-framework Mach-O. A guard fails the build when a module is missing, because an absent QML module is invisible until someone opens the tab. --- .gitea/workflows/build-macos.yml | 35 ++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/build-macos.yml b/.gitea/workflows/build-macos.yml index 0e4f32d2..ddaecaa4 100644 --- a/.gitea/workflows/build-macos.yml +++ b/.gitea/workflows/build-macos.yml @@ -103,8 +103,39 @@ jobs: # for the dormant `installed/` layout) mkdir -p dist/Wowlet.app/Contents/Resources cp ../src/assets/images/appicons/appicon.icns dist/Wowlet.app/Contents/Resources/ - # bundle Qt frameworks/plugins so the app runs off-machine - /opt/homebrew/opt/qt/bin/macdeployqt dist/Wowlet.app + # bundle Qt frameworks/plugins so the app runs off-machine. + # -qmldir is not optional: our QML lives in .qrc resources, which + # macdeployqt cannot scan, so without it the bundle ships no QML + # modules at all and every page importing anything beyond QtQuick + # fails to load. That is how 5.1.2 shipped a grey mining tab on mac + # while Linux was fine: Contents/Resources held no qml directory, and + # the app logged 'module "QtQuick.Layouts" is not installed'. + /opt/homebrew/opt/qt/bin/macdeployqt dist/Wowlet.app -qmldir=../src/assets/qml + + # qmlimportscanner reads only the `import` lines in our QML and does + # not follow a module's own qmldir depends chain, so transitive + # modules (QtQuick -> QtQml.WorkerScript/Models) are silently skipped. + # The AppImage build hit this twice and blanket-copies the trees; do + # the same here, before the dylib passes below so their deps resolve. + # Ask Qt where its QML modules live rather than assuming a brew + # layout; the AppImage build asks qmake the same question. + QTPREFIX="$(brew --prefix qt)" + QMLSRC="$("$QTPREFIX/bin/qmake6" -query QT_INSTALL_QML 2>/dev/null || echo "$QTPREFIX/share/qt/qml")" + [ -d "$QMLSRC" ] || { echo "ERROR: Qt QML modules not found at $QMLSRC" >&2; exit 1; } + mkdir -p dist/Wowlet.app/Contents/Resources/qml + for m in QtQuick QtQml; do + cp -Rn "$QMLSRC/$m" dist/Wowlet.app/Contents/Resources/qml/ 2>/dev/null || true + done + + # Guard: the module the mining tab needs has to be in the bundle. A + # missing QML module is invisible until someone opens the tab, so it + # fails the build instead of shipping a page that paints grey. + for m in QtQuick QtQuick/Layouts; do + [ -d "dist/Wowlet.app/Contents/Resources/qml/$m" ] || { + echo "ERROR: $m missing from the bundle; QML pages will not load" >&2 + exit 1 + } + done # macdeployqt bundles Qt frameworks but not the plain-dylib brew deps # of Qt's image plugins (libwebp/libsharpyuv/libbrotli...), which are