This is mostly handled by Qt itself, with some issues.
Statically-compiled QML plugins can be loaded on demand using `qt_import_qml_plugins()` ([[ https://doc.qt.io/qt-6/qt-import-qml-plugins.html | Qt6 ]], [[ https://doc.qt.io/qt-5/qtqml-cmake-qt5-import-qml-plugins.html#example | Qt5]]).
This macro uses `qmlimportscanner` tool underneath to scan the source directory for qml files (including ones embedded in qrc) and pull the `import` calls to build a list of libraries which it then `target_link_libraries()` against the indicated target (also see note [1] below):
```
message(STATUS \"Running qmlimportscanner to find used QML plugins. \")
execute_process(COMMAND
\"${tool_path}\" \"${arg_PATH_TO_SCAN}\" -importPath \"${qml_path}\"
-cmake-output
OUTPUT_FILE \"${qml_imports_file_path}\")
```
The docs say:
> If target was created using qt_add_executable(), projects would not normally need to call qt_import_qml_plugins() directly. **When Qt is built statically**, the command is called automatically as part of target finalization if target links to the Qml library. By default, this finalization occurs at the end of the same directory scope in which the target was created. If the target was created using the standard CMake add_executable() command instead, the project needs to call qt_import_qml_plugins() itself.
So this excludes [[ https://invent.kde.org/frameworks/extra-cmake-modules/-/blob/master/modules/ECMAddTests.cmake#L92 | ECMAddTests ]] from taking advantage of it, as it uses the generic `add_executable()` macro, and some extra code with `qt_import_qml_plugins()` calls is needed.
As an examply, to fix the issues with some of the frameworks running tests against their own QML plugins, something like this — in theory — should work:
```
if (TARGET Qt${QT_MAJOR_VERSION}::Qml)
ecm_add_tests(
${kconcatenaterows_qml_SRC}
ksortfilterproxymodel_qml.cpp
LINK_LIBRARIES KF5::ItemModels Qt${QT_MAJOR_VERSION}::Test Qt${QT_MAJOR_VERSION}::Qml Qt${QT_MAJOR_VERSION}::Gui
TARGET_NAMES_VAR qml_tests_targets
)
find_package(Qt${QT_MAJOR_VERSION}QmlImportScanner)
foreach(test_target IN LISTS qml_tests_targets)
qt_import_qml_plugins(${test_target})
endforeach()
endif()
```
// (an extension of the code from here: https://invent.kde.org/frameworks/kitemmodels/-/blob/master/autotests/CMakeLists.txt#L42) //
Unfortunately, as highlighted in the quote above, this //only works for statically compiled Qt//. Moreover, the Qt manual is not too precise here, though, because — quite surprisingly — the complete `qt_import_qml_plugins()` function becomes a mere stub in a dynamically-compiled Qt:
> When Qt is built in a shared library config, the introduced function is a no-op.
// (from https://codereview.qt-project.org/c/qt/qtdeclarative/+/268048) //
This dictates that we would have to have statically-built Qt seeded into the CI job for this to work.
But this is not the end of it: while `qt_import_qml_plugins()` takes an (undocumented) `PATH_TO_SCAN` parameter, which it passes to `qmlimportscanner` to search for the qml files, it //hardcodes// the `-importPath` to `${_qt5Core_install_prefix}/qml/`, which is where it performs the actual plugin lookup. This obviously means is that the `qt_import_qml_plugins()` macro can currently only be used against the previously installed plugins, and not against the in-tree ones. `qmlimportscanner` tool can take multiple `-importPath`s, so not adding it as a parameter to `qt_import_qml_plugins()` seems like a weird omission, to say the least.
So, to summarize, using my local statically-compiled Qt5.15.6, after hacking the `qt5_import_qml_plugins()` macro and literally hardcoding an extra `-importPath "~/Sourcecode/kitemmodels/cmake-build-debug/bin/"`, and fixing a minor `ECMAddTests` issue ([1]), I was able to successfully run the QML tests:
```
/Users/cromo/Documents/Sourcecode/kitemmodels/cmake-build-debug-vcpkg/bin/kconcatenaterows_qml
********* Start testing of tst_KConcatenateRowsQml *********
Config: Using QtTest library 5.15.5, Qt 5.15.5 (arm64-little_endian-lp64 static debug build; by Clang 13.1.6 (clang-1316.0.21.2.5) (Apple)), osx 12.6
PASS : tst_KConcatenateRowsQml::initTestCase()
PASS : tst_KConcatenateRowsQml::testQmlLoad()
PASS : tst_KConcatenateRowsQml::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 31ms
********* Finished testing of tst_KConcatenateRowsQml *********
Process finished with exit code 0
```
PS. It's worth noting that as of 6.2.1 one can link against the plugin target names with `target_link_libraries` (e.g. `Qt6::qmlplugin`) instead of the backing lib (`Qt6::Qml`), and that will also properly link the object file that contains `Q_IMPORT_PLUGIN`. I would assume this fixes the static consumption as well. (See [[ https://bugreports.qt.io/browse/QTBUG-92887?focusedCommentId=588539&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-588539 | this ]] comment)
[1] One additional issue is that internally, `qt_import_qml_plugins()` macro calls `target_link_libraries()` with `PRIVATE` modifier, whereas the `ECMAddTests` doesn't, which results in:
```
The plain signature for target_link_libraries has already been used with
the target "ksortfilterproxymodel_qml". All uses of target_link_libraries
with a target must be either all-keyword or all-plain.
```
Hacking the `ECMAddTests` to also link PRIVATEly fixes the issue, but this can have side-effects.