Создание плагина Qt qml C++ с помощью CMake


Я пытаюсь создать плагин c++ qml, используя cmake (вместо использования QtCreator). Вот фиктивный проект, имитирующий мою настройку плагина:

./ 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)

./ включить / круг.ГЭС

#pragma once

#include <QObject>

namespace test {

class Circle: public QQuickItem {
    Q_OBJECT

public:
    Circle(QQuickItem* parent = nullptr);
    virtual ~Circle() = default;
};

} // namespace test

./ включить / плагин.ГЭС

#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

import QtQuick 2.2
import CirclePlugin 1.0

Item {

    Circle {
    }

}

Я связываюсь с circle_plugin из моего основного приложения. Всякий раз, когда я import CirclePlugin 1.0 в qml-файлах моего основного приложения, я получаю сообщение module "Circle" is not installed.

Я нашел следующее руководство по теме, но я все еще не уверен, как я могу заставить его работать.

Пример плагина QML

CMake Maunal

1 6

1 ответ:

Следуя комментариям в вопросе, мы выяснили, что плагины QtQuick действительно должны быть установлены, прежде чем быть найдены и использованы другими приложениями QtQuick или плагинами *. Это означает, что:

  1. Плагин должен быть в своем собственном проекте, который состоит из плагина .hpp и (по крайней мере) файл qmldir (предполагая, что плагин.hpp встроен в библиотеку плагинов с именем libcircleplugin.so ) что выглядит например:
    module CirclePlugin
    plugin circleplugin
    
  2. Плагин (то есть libcircleplugin.so и qmldir ) должны быть установлены внутри QT_ROOT/QT_VERSION/ARCHITECTURE/qml/CirclePlugin/

Некоторые подробные сведения об этой процедуре можно найти в http://doc.qt.io/qt-5/qtqml-modules-cppplugins.html

Конечно, это все при условии, что вы используете qmake с файлом circle-plugin.pro, таким как:

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

С этим, вы можете make install и ваш плагин будет найден так же, как и любой другой модуль QtQuick, который есть и сами такие плагины. Эта процедура также должна быть воспроизведена с помощью cmake, если требуется аналогичное поведение. Для этого требуется знать QT_INSTALL_QML, который можно запросить, выполнив qmake -query QT_INSTALL_QML. важное замечание : это не изолированный подход, так как он изменяет сам Qt SDK. Имейте в виду, что это зло, но также является лучшим решением в настоящее время.


* в то время как это верно для Android (см. каков правильный способ развертывания плагинов C++ QML на мобильном устройстве?), обойти эту проблему можно на рабочем столе, установив переменные окружения QML2_IMPORT_PATH или QT_PLUGIN_PATH в том месте, где вы установили свои плагины (ни один из которых не задокументирован; фактически, вся эта проблема до сих пор не задокументирована). Проблема с Android заключается в том, что плагин не входит в пакет apk, пока он не находится в QT_INSTALL_QML, поэтому конечное приложение не может найти плагин; то есть он должен получить такое же лечение, как и другие официальные Плагины qml. Ручная установка и связывание усилий были безрезультатно с нашей стороны, плагин просто не был найден во время выполнения, даже если его вручную принудительно вставили в apk (дойдя до написания пользовательских файлов android-libapplication.so-deployment-settings.json для каждого приложения). Дискуссия (которая практически нигде не выходила за рамки qmake -query QT_INSTALL_QML) по этой теме находится в https://bugreports.qt.io/browse/QTBUG-29987 это подводит меня к моей фактической точке, которая находится ниже:


Почему qmake должно быть предпочтительнее cmake при создании Qt плагинов/приложений?

Хотя я считаю, что cmake является не только более общей, но и в целом более совершенной системой сборки, чтобы qmake, qmake все еще имеет внутренние компоненты, которые иногда необходимы (такие как QT_INSTALL_QML) и фактически поддерживается Qt для Qt и его приложений/плагинов. Поддержка cmake для Qt всегда будет внешней (и" калечащей", как заявляют сами разработчики Qt). Это означает потенциально большую нагрузку по техническому обслуживанию в будущем на вашу сторону как разработчика, так как решения таких проблем, как выше, могут случайным образом ломаться с новыми версии.

Я тоже когда-то мечтал о создании своих Qt плагинов и приложений красиво с cmake , а также, возможно, кросс-компиляции их с .toolchain.cmake, как https://github.com/taka-no-me/android-cmake я быстро понял, что это просто не стоит делать.