使用CMake创建Qt qml C++插件

Mar*_*ark 6 c++ qt cmake qml

我正在尝试使用cmake(而不是使用QtCreator)创建C++ qml插件.这是一个模仿我的插件设置的虚拟项目:

./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)
Run Code Online (Sandbox Code Playgroud)

./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
Run Code Online (Sandbox Code Playgroud)

./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
Run Code Online (Sandbox Code Playgroud)

./qml/View.qml

import QtQuick 2.2
import CirclePlugin 1.0

Item {

    Circle {
    }

}
Run Code Online (Sandbox Code Playgroud)

我正在circle_plugin从我的主应用程序链接.每当我import CirclePlugin 1.0在主应用程序的qml文件中时,我都会收到消息module "Circle" is not installed.

我已经找到了关于这个主题的以下指南,但我仍然不确定如何让它工作.

QML插件示例

CMake Maunal

Ayb*_*gür 0

根据问题中的评论,我们发现 QtQuick 插件确实必须先安装,然后才能被其他 QtQuick 应用程序或插件发现和使用*。这意味着:

  1. 该插件必须位于其自己的项目中,该项目由Plugin.hpp和(至少)一个qmldir文件组成(假设Plugin.hpp内置于名为libcircleplugin.so的插件库中),如下所示:

    module CirclePlugin
    plugin circleplugin
    
    Run Code Online (Sandbox Code Playgroud)
  2. 插件(即libcircleplugin.soqmldir)必须安装在里面QT_ROOT/QT_VERSION/ARCHITECTURE/qml/CirclePlugin/

有关此过程的一些详细信息可以在http://doc.qt.io/qt-5/qtqml-modules-cppplugins.html中找到

当然,这一切都假设您使用以下文件qmakecircle-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
Run Code Online (Sandbox Code Playgroud)

有了这个,你就可以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 中,它就不会被捆绑到 apk 中,QT_INSTALL_QML因此最终应用程序无法找到该插件;即它必须得到与其他官方 qml 插件相同的待遇。手动安装和捆绑工作对我们来说是徒劳的,即使手动强制进入 apk(通过为android-libapplication.so-deployment-settings.json每个应用程序编写自定义文件),在运行时也找不到该插件。关于此主题的讨论(几乎没有任何其他qmake -query QT_INSTALL_QML内容)位于https://bugreports.qt.io/browse/QTBUG-29987中。这让我想到了我的实际观点,如下:


为什么在构建 Qt 插件/应用程序时应该qmake优先考虑?cmake

尽管我相信这cmake不仅更通用,而且总体上是一个优于 的构建系统qmake,但qmake仍然具有有时需要的内部结构(例如QT_INSTALL_QML),并且实际上由 Qt维护Qt 及其应用程序/插件。对 Qt 的支持cmake始终是外部的(正如 Qt 开发人员自己所说,这是“严重的”)。这意味着作为开发人员,您将来可能会承担更多的维护负担,因为上述问题的解决方案可能会随着新版本的出现而随机中断。

我也曾经梦想过用https://github.com/taka-no-me/android-cmake之类的工具很好地构建我的 Qt 插件和应用程序cmake,也可以使用它们进行交叉编译。我很快发现这根本不值得做。.toolchain.cmake