I'm trying to create a C++ qml plugin using cmake
(instead of using QtCreator
). Here's a dummy project mimicking my plugin setup:
./CMakeLists.txt
project(circle_plugin)
find_package(Qt5 COMPONENTS Core Qml Quick REQUIRED)
set(HEADERS
include/Circle.hpp
include/Plugin.hpp
)
add_library(circle_plugin STATIC ${HEADERS})
set_target_properties(circle_plugin PROPERTIES AUTOMOC ON)
target_link_libraries(circle_plugin PUBLIC Qt5::Core Qt5::Qml Qt5::Quick)
target_include_directories(circle_plugin PUBLIC include)
./include/Circle.hpp
#pragma once
#include <QObject>
namespace test {
class Circle: public QQuickItem {
Q_OBJECT
public:
Circle(QQuickItem* parent = nullptr);
virtual ~Circle() = default;
};
} // namespace test
./include/Plugin.hpp
#pragma once
#include <QObject>
namespace test {
class CirclePlugin : public QQmlExtensionPlugin {
Q_OBJECT
Q_PLUGIN_METADATA(IID "com.test.CirclePlugin")
public:
CirclePlugin();
~CirclePlugin();
void registerTypes(const char *uri) {
Q_ASSERT(uri == QLatin1String("CirclePlugin"));
qmlRegisterType<Circle>(uri, 1, 0, "Circle");
}
};
} // namespace test
./qml/View.qml
import QtQuick 2.2
import CirclePlugin 1.0
Item {
Circle {
}
}
I'm linking to circle_plugin
from my main application. Whenever I import CirclePlugin 1.0
in my main app's qml files, I get the message module "Circle" is not installed
.
I've found the following guides on the topic, but I'm still unsure how I can get it working.
Following the comments in the question, we found out that QtQuick plugins must indeed be installed before being found and used by other QtQuick applications or plugins * . This means that:
The plugin must be in its own project which is composed of Plugin.hpp and (at least) a qmldir file (assuming that Plugin.hpp is built into a plugin library named libcircleplugin.so ) that looks like:
module CirclePlugin plugin circleplugin
The plugin (ie libcircleplugin.so and qmldir ) must be installed inside QT_ROOT/QT_VERSION/ARCHITECTURE/qml/CirclePlugin/
Some detailed information about this procedure can be found at http://doc.qt.io/qt-5/qtqml-modules-cppplugins.html
Of course, this is all assuming that you use qmake
with a circle-plugin.pro
file such as:
QT += qml quick
CONFIG += qt c++ nostrip plugin
CONFIG -= android_install #If you care about Android
HEADERS += Plugin.hpp
TEMPLATE = lib
TARGET = circleplugin
TARGET = $$qtLibraryTarget($$TARGET)
uri = CirclePlugin
qmldir.files = qmldir
OTHER_FILES += qmldir.files
installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /)
qmldir.path = $$installPath
target.path = $$installPath
INSTALLS += target qmldir
With this, you can make install
and your plugin will be found just like any other QtQuick module which are themselves such plugins. This procedure must also be replicated using cmake
if similar behavior is desired. This requires QT_INSTALL_QML
to be known which can be queried by executing qmake -query QT_INSTALL_QML
. Important note : This is not a sandboxed approach since it modifies the Qt SDK itself. Be aware that this is evil but also is the current best solution.
* While this is true for Android (see What is the proper way of deploying C++ QML plugins on mobile device? ), a work around is possible on desktop by setting QML2_IMPORT_PATH
or QT_PLUGIN_PATH
environment variables to where you installed your plugins (none of which is well documented; in fact, this whole issue is still not well documented to this day). The problem with Android is that the plugin does not get bundled into the apk as long as it is not in QT_INSTALL_QML
so the final application cannot find the plugin; ie it must get the same treatment as the other official qml plugins. Manual installation and bundling efforts were fruitless from our side, the plugin was just not found during runtime even if manually forced into the apk (by going as far as writing custom android-libapplication.so-deployment-settings.json
files per application). A discussion (that went pretty much nowhere beyond qmake -query QT_INSTALL_QML
) on this topic is in https://bugreports.qt.io/browse/QTBUG-29987 . This brings me to my actual point which is below:
qmake
be preferred over cmake
when building Qt plugins/apps? Although I believe that cmake
is not only more general but altogether a superior build system to qmake
, qmake
still has internals that are sometimes needed (such as QT_INSTALL_QML
) and is actually maintained by Qt for Qt and its applications/plugins. Support for cmake
for Qt will always be external (and "crippling" as stated by Qt developers themselves). This means potentially more maintenance load in the future on your side as developer, as the solutions to such problems as the above may randomly break with new versions.
I too once dreamed of building my Qt plugins and apps nicely with cmake
and also maybe cross-compiling them with .toolchain.cmake
's like https://github.com/taka-no-me/android-cmake . I quickly found out that it is simply not worth doing.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.