Solved How to create static plugin using cmake?
-
I wrote qml plugin using cmake. the source code is presented below. It works fine.
Now I want built it as static plugin . I have added next changes in project.- add my plugin to link libraries in CMakeLists.txt
target_link_libraries( ${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::Qml myplugin )
- add plugin import to main.cpp
#include <QtPlugin> Q_IMPORT_PLUGIN(MyPlugin)
- build STATIC plugin version with QT_STATICPLUGIN difinition in my/plugin/CMakeLists.txt
add_library( ${PLUGIN_NAME} STATIC Plugin.h QuickItem.h Plugin.cpp QuickItem.cpp plugin.qrc qmldir ) target_compile_definitions(${PLUGIN_NAME} PUBLIC QT_STATICPLUGIN )
- change plugin to classname i n qmldir
classname Plugin
Project is built fine but I have runtime error:
QQmlApplicationEngine failed to load component
qrc:/main.qml:11 MyQuickItem is not a typeQML engine parses "import my.plugin 1.0" it's mean qmldir is found
But MyPlugin::registerTypes is never called (I think for calling this function need add classname to qmldir but unfortunately it doesn't work ). I have checked this code with Qt 5.12.4 and 5.15.1, result is same.
What else should I do?My file system:
┣━ CMakeLists.txt ┣━ app.qrc ┣━ main.cpp ┣━ main.qml ┗━ my ┗━ plugin ┣━ CMakeLists.txt ┣━ MyButton.qml ┣━ Plugin.cpp ┣━ Plugin.h ┣━ QuickItem.cpp ┣━ QuickItem.h ┣━ plugin.qrc ┗━ qmldir
CMakeLists.txt:
cmake_minimum_required(VERSION 3.0) project(app VERSION 1.0 LANGUAGES CXX) find_package(Qt5 REQUIRED COMPONENTS Quick Core Qml) add_executable( ${PROJECT_NAME} main.cpp app.qrc ) set_target_properties( ${PROJECT_NAME} PROPERTIES AUTOMOC ON AUTORCC ON ) target_link_libraries( ${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::Qml ) add_subdirectory(my/plugin)
app.qrc
<RCC> <qresource prefix="/"> <file>main.qml</file> </qresource> </RCC>
main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) { return -1; } return app.exec(); }
main.qml
import QtQuick.Controls 2.0 import my.plugin 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: "Lyzer" // 'myplugin' C++ class MyQuickItem { id: pluginItem color: "green" width: 100 height: 50 anchors.centerIn: parent } // 'myplugin' QML file MyButton { anchors.top: pluginItem.bottom anchors.horizontalCenter: pluginItem.horizontalCenter width: pluginItem.width onClicked: { pluginItem.color = '#' + Math.floor(Math.random() * 0x1000000).toString(16); } } }
CMakeLists.txt for plugin
set(PLUGIN_NAME myplugin) add_library( ${PLUGIN_NAME} SHARED Plugin.h QuickItem.h Plugin.cpp QuickItem.cpp plugin.qrc qmldir ) set_target_properties( ${PLUGIN_NAME} PROPERTIES AUTOMOC ON AUTORCC ON ) target_link_libraries( ${PLUGIN_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::Qml ) add_custom_command( TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/qmldir $<TARGET_FILE_DIR:myplugin>/qmldir )
MyButton.qml
import QtQuick.Controls 2.0 Button { text: "Click me!" }
Plugin.cpp
#include "Plugin.h" #include "QuickItem.h" void MyPlugin::registerTypes(const char* uri) { qmlRegisterType<My::QuickItem>(uri, 1, 0, "MyQuickItem"); }
plugin.h
#pragma once #include <QtQml/QQmlExtensionPlugin> class MyPlugin: public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "my.plugin/1.0") public: void registerTypes(const char* uri) override; };
QuickItem.cpp
#include "QuickItem.h" #include <QPen> #include <QPainter> namespace My { QuickItem::QuickItem(QQuickItem* parent) : QQuickPaintedItem(parent) { } QColor QuickItem::getColor() const { return color; } void QuickItem::setColor(const QColor& color) { if (color != this->color) { this->color = color; update(); emit colorChanged(); } } void QuickItem::paint(QPainter* painter) { QPen pen(color, 2); painter->setPen(pen); painter->fillRect(QRectF(0, 0, width(), height()), color); } }
QuickItem.h
#pragma once #include <QtQuick/QQuickPaintedItem> #include <QColor> namespace My { class QuickItem: public QQuickPaintedItem { Q_OBJECT Q_PROPERTY(QColor color READ getColor WRITE setColor NOTIFY colorChanged) public: QuickItem(QQuickItem* parent = nullptr); QColor getColor() const; void setColor(const QColor &color); void paint(QPainter *painter) override; signals: void colorChanged(); private: QColor color; }; }
plugin.qrc
<RCC> <qresource prefix="/plugin"> <file>MyButton.qml</file> </qresource> </RCC>
qmldir
module my.plugin plugin myplugin MyButton 1.0 qrc:/plugin/MyButton.qml