qt_add_protobuf

使用 protobuf 规范生成基于 Qt 的 C++ 源代码

注意:此命令目前处于技术预览阶段,可能在未来版本中发生变化。

此命令是在 Qt 6.5 中引入的。

通常,通过使用 qt_add_protobuf 命令通过 CMake 来调用 qtprotobufgen

qt_add_protobuf(<target>
    PROTO_FILES <file> ...
    [COPY_COMMENTS]
    [GENERATE_PACKAGE_SUBFOLDERS]
    [EXTRA_NAMESPACE <namespace>]
    [EXPORT_MACRO <infix>]
    [QML [QML_URI <uri>]]
    [PROTO_INCLUDES <path> ...]
    [OUTPUT_DIRECTORY <dir>]
    [OUTPUT_HEADERS <var>]
    [OUTPUT_TARGETS <var>]
)

qtprotobufgen 生成的源文件将被添加到目标中。如果目标已存在,文件将被 添加 到目标源列表中。如果目标不存在,它将作为一个库创建,您必须将其链接到您的程序中。

参数

  • COPY_COMMENTS.proto 文件中复制注释。如果提供在参数列表中,将与消息和字段相关的注释复制到生成的头文件中。
  • GENERATE_PACKAGE_SUBFOLDERS 为生成的文件生成与 .proto 文件包名匹配的文件夹结构。例如,package io.qt.test; 将生成的文件放入 io/qt/test/
  • EXTRA_NAMESPACE 是为生成的类将使用的可选命名空间。类始终在具有与 .proto 文件中指定的包名相同的命名空间中生成。如果使用此选项,则所有内容都将嵌套在额外命名空间内部。
  • EXPORT_MACRO 是用于生成代码的符号导出宏的基本名称。生成的宏名称构造为 QPB_<EXPORT_MACRO>_EXPORT。如果未设置此选项,则不生成宏。
  • QML 通过将它们注册为 QML 模块来启用 QML 上下文中的 QProtobufMessage 类型。Protobuf 类型可以扩展现有的 QML 模块。请参阅代码示例
    qt_add_qml_module(targetname
        ...
    )
    
    qt_add_protobuf(targetname
        QML
        ...
    )
    qt_add_executable(targetname
        ...
    )
    
    qt_add_protobuf(targetname
        QML
        ...
    )

    如果使用非现有目标调用 qt_add_protobuf 或目标不是 QML 模块,将隐式创建新的 QML 模块。如果创建新的 QML 模块,qt_add_qml_module 命令将在 qt_add_protobuf 命令内部调用。请参阅代码示例

    qt_add_executable(targetname
        ...
    )
    
    qt_add_protobuf(targetplugin
        QML
        QML_URI proto.uri.example
    )

    每个 QML 模块都必须定义一个 URI 名称。其他 QML 模块可以在 import 语句 中使用此名称导入用户应用程序。请使用 QML_URI 选项设置 URI 名称。它必须指定为点分表示法,例如 Qt.Protobuf.Package。如果省略 QML_URI,则将使用 protobuf 包名称作为模块的 URI

    注意:如果向 qt_add_protobuf 命令传递 QML_URItarget 已存在,则忽略 QML_URI 参数。

    注意: 如果跳过 QML_URI,则 qt_add_protobuf 命令中指定的所有 *.proto 文件应该具有相同的 protobuf 包名称,因为这将用作结果 QML 模块的默认 URI

    注意: 您应避免创建具有相同 QML_URI 或 proto 包名称的多个 QML 模块,因为这会导致 QML 上下文中的导入错误。

  • QML_URI 通过在提供的 URI 导入路径中注册它们,在 QML 上下文中启用 QProtobufMessage 类型。 URI 选项将用于生成的 qmldir 文件的行中,并且还用于通过替换点为正向斜杠来形成目标路径。

    注意: 请阅读 Identified Modules 以进一步深入讨论 URI

  • PROTO_FILES 是将用于生成过程的 .proto 文件列表。
  • PROTO_INCLUDES 是将搜索依赖项的目录列表。
  • OUTPUT_DIRECTORY 是放置生成文件的目录。默认情况下,使用当前目录(在评估函数时)。
  • OUTPUT_HEADERS 可以用于指定一个变量,该变量将保存函数创建的头文件列表。此列表对于自定义项目安装规则可能很有用。
  • OUTPUT_TARGETS 可以用于指定一个变量,该变量将保存函数创建的目标列表。此列表对于自定义项目安装规则可能很有用。

解决 protobuf 目标之间的依赖关系

qt_add_protobuf 命令未考虑用于为不同目标生成代码的 .proto 文件之间的依赖关系。

项目可能有两个或更多具有依赖关系的 .proto 文件

syntax = "proto3";

package test.messages;

message MyMessage {
    int32 myField = 1;
}
syntax = "proto3";

import "test_messages.proto";

package test.extensions;

message MyExtension {
    test.messages.MyMessage baseMessage = 1;
    int32 extension = 2;
}

上述 .proto 文件可以用于生成独立库

qt_add_protobuf(test_messages
    PROTO_FILES
        test_messages.proto
)
...
qt_add_protobuf(test_extensions
    PROTO_FILES
        test_extensions.proto
)
...

由于 test_extensions 目标依赖于来自 test_messages 目标的消息,因此用户需要在他们的 CMake 脚本中手动链接到此类目标。

target_link_libraries(test_extensions PUBLIC test_messages)

注意: 建议使用 PUBLIC 链接作用域,因为来自 test_messages 目标的消息在属于 test_extensions 目标的头文件中引用,因此链接到 test_extensions 的目标应将 test_messages 目标作为转译依赖项。

示例

使用 qt_add_protobuf

cmake_minimum_required(VERSION 3.16...3.22)
project(MyThings)

find_package(Qt6 REQUIRED COMPONENTS Protobuf)
qt_standard_project_setup()

qt_add_protobuf(MyMessages
    GENERATE_PACKAGE_SUBFOLDERS
    PROTO_FILES
        path/to/message.proto
        path/to/other_message.proto
    PROTO_INCLUDES
        /path/to/proto/include
)

qt_add_executable(MyApp main.cpp)

target_link_libraries(MyApp PRIVATE MyMessages)

在上面的示例中,我们生成一个名为 MyMessages 的库,该库包含通过 PROTO_FILES 选项传递的路径中定义的消息类型。 GENERATE_PACKAGE_SUBFOLDERS 选项用于生成生成文件的文件夹结构。并且 PROTO_INCLUDES 选项告诉 protoc 在指定的目录中查找依赖项或导入。我们创建一个名为 MyApp 的可执行文件目标,并将其链接到 MyMessages 库。

QML 扩展 protobuf 示例

cmake_minimum_required(VERSION 3.16...3.22)
project(MyThings)

find_package(Qt6 REQUIRED COMPONENTS Protobuf Quick)
qt_standard_project_setup()

qt_add_protobuf(MyMessagesPlugin
    QML
    QML_URI my.messages.module.uri
    PROTO_FILES
        path/to/message.proto
        path/to/other_message.proto
    PROTO_INCLUDES
        /path/to/proto/include
)

qt_add_protobuf(MyApp
    QML
    PROTO_FILES
        path/to/internal_message.proto
    PROTO_INCLUDES
        /path/to/proto/include
)

qt_add_qml_module(MyApp
    URI example.uri
    VERSION 1.0
    QML_FILES qml/main.qml
)

qt_add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE Quick)

在上面的 QML 扩展示例中,通过第一次调用 qt_add_protobuf,我们生成了一个名为 MyMessagesPlugin 的 QML 模块,其中包含传递给 PROTO_FILES 选项的路径中定义的消息类型。我们使用 QML 选项,该选项允许在 QML 上下文中注册 protobuf 消息类型。注册的类型可以通过导入由 QML_URI 设置的路径在 QML 中使用。通过第二次调用 qt_add_protobuf,我们将自动生成的代码添加到现有的 MyApp QML 模块中。在这种情况下不需要 QML_URI。最后,我们为名为 MyApp 的可执行文件创建了一个目标,该可执行文件包含图形部分的 QML 模块,并通过 my.messages.module.uri 导入将 MyMessagesPlugin 载入 main.qml 文件。

安装独立的 Qt Protobuf 库

qt_add_protobuf 命令还会生成用于进一步安装的工件列表。您可以通过指定以下参数来读取这些工件:

qt_add_protobuf(MyProtoLib
    PROTO_FILES
        mylib.proto
    OUTPUT_HEADERS
        public_headers
    OUTPUT_TARGETS
        generated_targets
)

该命令将 qt_add_protobuf 命令生成的头文件和目标的列表存储到相应的 public_headersgenerated_targets 变量中。

使用标准的 CMake install 命令安装工件并为您库生成 config 文件

include(GNUInstallDirs)
set_target_properties(MyProtoLib PROPERTIES
    PUBLIC_HEADER
        "${public_headers}"
    INTERFACE_INCLUDE_DIRECTORIES
        "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}>"
)
install(TARGETS ${generated_targets} EXPORT MyProtoLibTargets
    PUBLIC_HEADER
        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
install(EXPORT MyProtoLibTargets NAMESPACE MyProtoLib:: DESTINATION lib/cmake/MyProtoLib)

然后使用在包配置文件中生成的 MyProtoLibTargets 配置。您可以在官方的 CMake 文档 中了解更多关于包创建过程的信息。

安装后,该库作为独立的 CMake 包可用

find_package(Qt6 COMPONENTS Protobuf)
find_package(MyProtoLib CONFIG)

add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE MyProtoLib::MyProtoLib Qt6::Protobuf)

注意:qt_add_protobuf 不隐式地作为传递依赖项添加 Qt Protobuf 模块,无论是对于 MyProtoLib 目标还是 MyProtoLib CMake 包。因此,必须进行 Qt Protobuf 模块的查找并显式地将 MyApp 链接到 Qt6::Protobuf

另请参阅:qtprotobufgen 工具

© 2024 Qt 公司有限公司。此处包含的文档贡献的版权属于其各自的所有者。此处提供的文档根据自由软件基金会发布的 GNU 自由文档许可证版本 1.3 的条款进行许可。Qt 和相应的标志是 Finland 和/或其他国家和地区的 The Qt Company Ltd. 的商标。所有其他商标属于其各自的所有者。