Reputation: 187
Im developing a custom QML module (let's call it MyModule) containing some special types. It is used as precompiled library on other application projects (i.e. the source code is not available to them, it's used via import MyModule 1.0, setting the necessary import paths etc.). The module contains C++-bases QML types as well as QML files that themselves import QtQuick modules like QtQuick.Controls and QtQuick.Window.
When I try to deploy and execute an application developed using MyModule to Android, the dependencies of MyModule are not picked up by androiddeployqt/qmlimportscanner and included in the APK, which results in messages like: module "QtQuick.Controls" is not installed
Is there a way to have these QML dependencies included in the APK without having to create a dummy qml file containing all imports in the applications source directory, so they can be picked up by qmlimportscanner?
Upvotes: 3
Views: 1627
Reputation: 16849
You can place your module MyModule
anywhere below the base directory of the Android application that uses MyModule
. For example into a folder ./my-module
or ./lib/my-module
.
While running qmake / CMake, qmlimportscanner
will be run on the folder containing the project definition file. For qmake based projects that's the .pro
file and for CMake based projects that's the CMakeLists.txt
file. It will look for all *.qml
files in this directory and any sub-directories and include their QML dependencies into the Android APK package. At least that is the behavior observed for qmlimportscanner
.
You can still manage your QML module MyModule
and your Android application in different Git repositories. Just make sure to .gitignore
the contents of the ./lib/
folder in your Android application. (You can of course also use more complex approaches like Git submodules.)
Here is a list of alternative solutions that I found around the web. Either they did not work for my case or have some disadvantage, but might be useful for your situation.
As also mentioned in the question, this is the usual workaround:
The workaround consists in declaring a resource file on the project dir with a dummy qml file including the necessary imports.
Some more details with an example, from here:
I created a simple .qml file in the same directory as the .pro file. Then I only added the import lines that are used within all my .qml files in other folders. Since this lead to a syntax complaint I also added the text Page {} after the last import line.
import QtQuick 2.9 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.4 # [...] Page { }
Note that this file is not referenced in the
.pro
file and is of course not part of the project / application at all. It only exists for the purpose thatqmlimportscanner
includes the correct modules.
.qrc
filesSine Qt 5.14, this is the official resolution of the issue, which was tracked as QTBUG-55259. See there for details. Now, qmlimportscanner
will consider all QML files listed in your project's .qrc
files as available for import statements. So if your project says import MyModule.Something
in a QML file, it will work, as that import can now be resolved.
However, if your module MyModule
resides outside of the project's source tree and itself imports a QML module ExternalModule
that is not imported by your Android application, that import would still fail. (I hope I got this point right, since I did not test it myself.)
Somebody reported in late 2018 that qmlimportscanner
will follow symlinks from the project's source tree to external trees when looking for QML files that contain import
statements.
I tried this, but could not confirm that behavior.
qmlimportscanner
with multiple pathsqmlimportscanner
is capable of considering multiple root paths (where to scan for QML files that import other QML files) and import paths (where to resolve these imports), like this:
qmlimportscanner -rootPath dir1 -rootPath dir2 -importPath dir3 -importPath dir4
However, this capability is currently not used by androiddeployqt
as per QTBUG-75187. So you could only use it if you use an alternative build system for Android anyway. The ECM build system also calls androiddeployqt
internally though. Perhaps qt-android-cmake could help.
qml_import_qml_plugins()
from qmake / CMakeStarting with Qt 5.14, you can call qmlimportscanner
from your qmake / CMake files. It's only useful for static Qt builds, though:
Runs
qmlimportscanner
at configure time to find the static QML plugins used and links them to the given target.Note: When used with a non-static Qt build, this function does nothing.
(source)
At first glance, there does not seem to be a way to hand it multiple locations to look for QML dependencies, so it might not improve anything compared to the current situation. But I did not explore this in detail yet.
Upvotes: 1
Reputation: 24416
You can try adding the depends
keyword to your qmldir
file:
Declares that this module depends on another.
Example:
depends MyOtherModule 1.0
This declaration is necessary only in cases when the dependency is hidden: for example, when the C++ code for one module is used to load QML (perhaps conditionally) which then depends on other modules. In such cases, the depends declaration is necessary to include the other modules in application packages.
For some inspiration, check out this one:
http://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/src/imports/controls/qmldir
Upvotes: 4