【问题标题】:Creating a Qt qml C++ Plugin with CMake使用 CMake 创建 Qt qml C++ 插件
【发布时间】:2016-06-17 20:32:40
【问题描述】:

我正在尝试使用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

【问题讨论】:

  • qml 源码在哪里?它是否包括适当的包含?
  • 我会用 qml 更新。
  • 好的,我看到qml文件没问题。此外,您必须将扩展库放在正确的路径上。 $QT_INSTALL_QML/Circle 或 imports/Circle
  • 抱歉,您的意思是在我的 CMakeLists.txt 文件中,我需要在某处显式安装插件吗? cmake 不应该自动处理吗?
  • 我真的不知道如何使用 Cmake 设置安装过程。至于我,我用 qmake 来做。您可以在帖子中的链接中的 .pro 文件中看到该示例

标签: c++ qt cmake qml


【解决方案1】:

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

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

    module CirclePlugin
    plugin circleplugin
    
  2. 插件(即libcircleplugin.so和qmldir)必须安装在QT_ROOT/QT_VERSION/ARCHITECTURE/qml/CirclePlugin/

  3. 中

可以在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(请参阅 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。这让我明白了我的实际观点:


在构建 Qt 插件/应用程序时,为什么应该优先使用 qmake 而不是 cmake?

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

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

【讨论】:

  • “对 Qt 的 cmake 的支持将始终是外部的”——嗯,它不像葡萄酒那样陈年。 CMake 目前正受到 Qt 的官方支持,而 qmake 正在衰落,只能提供最低限度的生命支持。
猜你喜欢
  • 1970-01-01
  • 2020-11-03
  • 2017-02-15
  • 1970-01-01
  • 2022-08-07
  • 1970-01-01
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
相关资源
最近更新 更多