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

标签 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)

./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 {
    }

}

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

我找到了以下关于该主题的指南,但我仍然不确定如何让它发挥作用。

QML Plugin Example

CMake Maunal

最佳答案

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

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

    module CirclePlugin
    plugin circleplugin
    
  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

有了这个,您可以 make install并且您的插件将像任何其他本身就是此类插件的 QtQuick 模块一样被发现。此过程也必须使用 cmake 复制如果需要类似的行为。这需要 QT_INSTALL_QML知道哪些可以通过执行 qmake -query QT_INSTALL_QML 查询. 重要说明:这不是沙盒方法,因为它修改了 Qt SDK 本身。请注意,这是邪恶的,但也是当前最好的解决方案。


* 虽然这适用于 Android(请参阅 What is the proper way of deploying C++ QML plugins on mobile device? ),但可以通过设置 QML2_IMPORT_PATH 在桌面上解决此问题或 QT_PLUGIN_PATH环境变量到您安装插件的位置(没有一个被很好地记录;事实上,整个问题直到今天仍然没有被很好地记录)。 Android 的问题在于,只要插件不在 QT_INSTALL_QML 中,它就不会捆绑到 apk 中。所以最终应用找不到插件;即它必须得到与其他官方 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 开发人员自己所说的那样“瘫痪”)。这意味着您作为开发人员将来可能会承担更多的维护工作,因为上述问题的解决方案可能会随新版本随机中断。

我也曾梦想用 cmake 构建我的 Qt 插件和应用程序也可能用 .toolchain.cmake 交叉编译它们就像https://github.com/taka-no-me/android-cmake .我很快发现这根本不值得做。

关于c++ - 使用 CMake 创建 Qt qml C++ 插件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37889951/

相关文章:

c++ - Qt + conan = 使用空输出设备,没有可用的

c++ - 链接 Boost 线程库

c++ - 在 CLion 中使用 GLib

cmake - 查找BLAS给出通往lib的路径

c++ - 需要一个宏来从 std::ostringstream 和 << arg 列表创建 std::string

C++模板函数问题

qt - 如何在 QGraphicsView 上锚定 QGraphicsWidget/Item(使它们静态)

java - 是否可以使用 Jambi 制作完全原生感觉的 GUI?

C++字符串数组char问题

C++:重载 "pointer to object"* 运算符