Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 type

    QML 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
    

Log in to reply