本页内容

使用 CMake 将所有内容整合在一起

使用 CMake 命令 `qt_add_qml_module` 是定义 QML 模块的推荐方法。它可自动完成类型注册、资源嵌入、插件创建以及工具集成。本页将阐述 `qt_add_qml_module ` 背后的概念,并详细介绍常见的使用模式。

有关所有选项的完整参考,请参阅qt_add_qml_module。

关键概念

在查看示例之前,先了解qt_add_qml_module 实际创建了什么内容会很有帮助:

  • 后端目标—— 一个包含模块的 C++ 代码、已编译的 QML 文件以及资源的库(或可执行文件)。这是qt_add_qml_module 的第一个参数,也是您用于链接的目标。它可以是现有的目标(先前通过qt_add_executable 或qt_add_library 创建),也可以由qt_add_qml_module 为您自动创建。
  • 插件目标— 一个小型库,允许 QML 引擎在运行时动态加载该模块。它会自动创建,并与后端目标分开。当可执行文件直接链接到后端目标时,插件不会在运行时加载。可以通过NO_PLUGIN 完全省略该插件。
  • qmldir 文件——一种模块元数据文件,用于告知 QML 引擎该模块提供了哪些类型以及如何定位这些类型。该文件会自动生成。
  • typeinfo 文件(.qmltypes )—— QML 工具(qmlcachegen、qmllint、qmlls、Qt Creator )使用的机器可读类型信息。该文件同样会自动生成。

目录结构

源代码目录结构应与模块的 URI 保持一致。URI 通过将点替换为正斜杠转换为路径。例如,URI 为MyCompany.Controls 的模块应位于:

src/MyCompany/Controls/CMakeLists.txt
src/MyCompany/Controls/Button.qml
src/MyCompany/Controls/mywidget.cpp
src/MyCompany/Controls/mywidget.h

此约定使 QML 引擎和工具无需额外配置即可找到模块。 如果您的目录结构与 URI 不匹配,则需要设置OUTPUT_DIRECTORY,以确保构建输出位于与 URI 匹配的路径中,并设置 IMPORT_PATH,以便 QML 引擎和工具能够定位该模块。

常见模式

纯 QML 应用程序

最简单的情况:一个仅包含 QML 文件、不包含 C++ 类型的可执行文件。

cmake_minimum_required(VERSION 3.16)
project(myapp LANGUAGES CXX)

find_package(Qt6 REQUIRED COMPONENTS Quick)
qt_standard_project_setup(REQUIRES 6.8)

qt_add_executable(myapp)
qt_add_qml_module(myapp
    URI MyApp
    QML_FILES
        Main.qml
        Button.qml
    RESOURCES
        images/logo.png
)

target_link_libraries(myapp PRIVATE Qt6::Quick)

由于后端目标是一个可执行文件,因此不会创建任何插件。QML 文件会被编译并作为资源嵌入。RESOURCES 关键字将非 QML 文件(图像、字体等)添加到相同的资源层次结构中。

包含 C++ 类型的应用程序

向 QML 暴露 C++ 类型的应用程序:

qt_add_executable(myapp)
qt_add_qml_module(myapp
    URI MyApp
    QML_FILES
        Main.qml
    SOURCES
        backend.cpp backend.h
)

backend.h 中的C++类型必须使用QML_ELEMENT (或类似宏,如QML_NAMED_ELEMENT )进行注释,并且必须使用Q_OBJECT 或Q_GADGET 宏。类型注册会通过AUTOMOC 自动完成。有关可用注册宏的完整概述,请参阅《使用QML类型系统注册C++类型》。

可重用库模块

作为库打包的 QML 模块,其他项目或模块可以导入该模块:

# In src/MyCompany/Controls/CMakeLists.txt
qt_add_qml_module(mycontrols
    URI MyCompany.Controls
    QML_FILES
        Button.qml
        Slider.qml
    SOURCES
        theme.cpp theme.h
)

这将生成两个目标:mycontrols (底层库)和mycontrolsplugin (插件)。其他模块可通过在 QML 中使用import MyCompany.Controls 来导入它。直接链接到mycontrols 的应用程序无需在运行时加载该插件。

使用库模块的应用程序

以下示例使用上述“可重用库模块”示例中的mycontrols 模块:

# In the application's CMakeLists.txt
qt_add_executable(myapp)
qt_add_qml_module(myapp
    URI MyApp
    QML_FILES Main.qml
    DEPENDENCIES TARGET mycontrols
)

target_link_libraries(myapp PRIVATE mycontrols)

DEPENDENCIES行确保 QML 工具(qmlcachegen、qmllint、qmlls)能够找到MyCompany.Controls 提供的类型。

// In Main.qml
import MyCompany.Controls

Button { text: "Click me" }

包含单例的模块

提供单例类型的 QML 文件需要在调用 `qt_add_qml_module `之前设置源文件属性:

set_source_files_properties(Theme.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)

qt_add_qml_module(mymodule
    URI MyModule
    QML_FILES
        Theme.qml
        Main.qml
)

该 QML 文件还必须包含 `pragma Singleton`。CMake 属性与 QML 指令均不可或缺。

包含自定义插件的模块

当需要执行自定义初始化(例如注册图像提供程序)时,可以提供自己的QQmlEngineExtensionPlugin 子类。

# In CMakeLists.txt
qt_add_qml_module(mymodule
    URI MyModule
    NO_GENERATE_PLUGIN_SOURCE
    NO_PLUGIN_OPTIONAL
    CLASS_NAME MyModulePlugin
    QML_FILES
        Main.qml
    SOURCES
        myimageprovider.cpp myimageprovider.h
)

# Add the custom plugin source to the plugin target
target_sources(mymoduleplugin PRIVATE plugin.cpp)
// In plugin.cpp
#include <QtQml/QQmlEngineExtensionPlugin>
#include "myimageprovider.h"

class MyModulePlugin : public QQmlEngineExtensionPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
public:
    void initializeEngine(QQmlEngine *engine, const char *uri) override
    {
        engine->addImageProvider("myprovider", new MyImageProvider);
    }
};

#include "plugin.moc"

NO_GENERATE_PLUGIN_SOURCE指示构建系统不要生成默认的插件源代码。CLASS_NAME必须与您实现中的类名一致。NO_PLUGIN_OPTIONAL可确保插件始终被加载,因为其中包含的初始化逻辑否则会被跳过。

添加其他 QML 文件

对于在首次调用qt_add_qml_module 之后添加的 QML 文件,请使用qt_target_qml_sources:

qt_target_qml_sources(my_qml_module
    QML_FILES
        DynamicallyAddedType.qml
)

这有助于根据平台或配置条件性地包含文件。

详细的 CMake 参考

有关所有 CMake 命令、属性、变量和策略的完整详细信息,请参阅《QML 的 CMake 集成》。

另请参阅 《QML 模块》、《qt_add_qml_module》和《编写 QML 模块》。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.