qt_add_protobuf
使用 protobuf 模式生成基于 Qt 的 C++ 源代码
注意: 此命令为技术预览版,可能会在以后的版本中更改。
此命令在 Qt 6.5 中引入。
使用 qt_add_protobuf 在 CMake 脚本中调用qtprotobufgen
,并从 .proto 方案为项目生成代码。qtprotobufgen
将通过 CMake 使用qt_add_protobuf
命令调用。
qt_add_protobuf(<target> PROTO_FILES <file> ... [PROTO_INCLUDES <path> ...] [QML [QML_URI <uri>]] [OUTPUT_DIRECTORY <dir>] [GENERATE_PACKAGE_SUBFOLDERS] [COPY_COMMENTS] [EXPORT_MACRO <infix>] [OUTPUT_HEADERS <var>] [OUTPUT_TARGETS <var>] [HEADER_GUARD <pragma|filename>] )
qtprotobufgen
生成的源文件将被添加到目标中。如果目标已经存在,生成的文件将被添加到目标源代码列表中。如果目标不存在,则会将其创建为一个库,您必须链接到该库。
参数
PROTO_FILES
指定代码生成过程使用的.proto文件列表。PROTO_INCLUDES
指定要搜索的 protobuf 依赖目录列表。注意:
PROTO_FILES
的位置隐含地视为 protobuf 包含路径的一部分。QML
启用从 protobuf 定义生成 QML 兼容的消息类型,并将它们注册为 QML 模块。如果在不存在的目标或不是 QML 模块的目标上调用 ,将隐式创建一个新的 QML 模块。qt_add_protobuf
find_package(Qt6 6.8 REQUIRED COMPONENTS Quick Protobuf ProtobufQuick) ... qt_add_executable(target ... ) // creates a new QML module qt_add_protobuf(target QML ... )
如果目标是现有的 QML 模块,
qt_add_protobuf
会将生成的 protobuf 类型附加到该模块。find_package(Qt6 6.8 REQUIRED COMPONENTS Quick Protobuf ProtobufQuick) ... qt_add_qml_module(target ... ) // adds to existing QML module qt_add_protobuf(target QML ... )
注意: 如果使用 QML 参数,则必须在 find_package 调用中添加 ProtobufQuick。请参阅上面的示例。
QML_URI
定义了 QML 模块使用的 。URI
每个 QML 模块都必须定义一个
URI
,它在导入语句中用于向 QML 公开它的 protobuf 类型。qt_add_protobuf(target QML QML_URI proto.uri.example )
如果
QML_URI
被省略,protobuf 包名将被用作模块的URI
。注意: 如果省略
QML_URI
,在PROTO_FILES
部分指定的所有.proto文件必须共享相同的 protobuf 包名,因为它将被用作生成的 QML 模块的默认URI
。注意: 应避免用相同的
QML_URI
或 proto 包名创建多个 protobuf QML 模块,因为这会导致 QML 上下文中的导入错误。注意: 如果
QML_URI
传递给qt_add_protobuf
函数,但目标已经存在,QML_URI
参数将被忽略。有关
URI
的进一步深入讨论,请阅读Identified Modules。OUTPUT_DIRECTORY
定义生成文件的放置目录。默认情况下,使用当前构建目录。GENERATE_PACKAGE_SUBFOLDERS
使用 文件中的软件包名称指定符来创建生成文件的文件夹结构。例如,如果软件包定义为,生成的文件将放在.proto
package io.qt.test
OUTPUT_DIRECTORY/io/qt/test/ 目录下。COPY_COMMENTS
将 文件中的注释复制到生成的代码中。.proto
EXPORT_MACRO
仅适用于从<target> 创建新的共享库。该选项指定生成代码中使用的导出宏的基本名称。最终的宏名构造为 。如果未设置该选项,则目标名称为 。QPB_<EXPORT_MACRO>_EXPORT
EXPORT_MACRO
请阅读创建共享库获取更多深入信息。
OUTPUT_HEADERS
指定一个变量,用于存储生成的头文件列表。该列表可用于定义自定义项目安装规则。OUTPUT_TARGETS
指定一个变量,用于存储生成的目标列表。该列表有助于定义自定义项目安装规则。HEADER_GUARD
指定用于防止生成的头文件被多重包含的机制。可能的值是 , 。默认值为 。将该选项设置为 会生成现代 pragma 头文件防护:pragma
filename
filename
pragma
#pragma once ...
省略该选项或将该选项设置为
filename
会生成ifdef
封装保护,并使用".proto "文件名作为保护后缀:#ifdef MYMESSAGES_QPB_H #define MYMESSAGES_QPB_H ... #endif // MYMESSAGES_QPB_H
根据项目结构选择首选的保护方式。
解决 protobuf 目标之间的依赖关系
qt_add_protobuf
命令不会考虑用于为不同目标生成代码的.proto
文件之间的依赖关系。
项目可能有两个或更多带有依赖关系的.proto
文件:
// test_messages.proto syntax = "proto3"; package test.messages; message MyMessage { int32 myField = 1; }
// test_extensions.proto 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)
注意: 来自test_messages
目标文件的消息被用于属于test_extensions
目标文件的头文件,因此链接到test_extensions
的目标文件应将test_messages
目标文件作为传递依赖关系。建议使用PUBLIC
链接范围,以便为 protobuf 库目标提供适当的INTERFACE_INCLUDE_DIRECTORIES
和INTERFACE_LINK_LIBRARIES
属性。
示例
使用 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 ProtobufQuick 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
上下文中启用 proto 消息类型注册。通过导入QML_URI
设置的路径,注册的类型可在QML
中使用。通过第二次qt_add_protobuf
调用,我们将自动生成的代码添加到现有的MyApp
QML 模块中。在这种情况下,不需要QML_URI
。最后,我们为名为MyApp
的可执行文件创建一个目标,该目标有一个用于图形部分的 QML 模块,并通过my.messages.module.uri
导入将MyMessagesPlugin
加载到 main.qml 文件中。
安装独立的Qt Protobuf 库
qt_add_protobuf命令还会生成用于进一步安装的工件列表。你可以通过指定OUTPUT_HEADERS
, 和OUTPUT_TARGETS
参数来读取这些工件,如下所示:
qt_add_protobuf(MyProtoLib PROTO_FILES mylib.proto OUTPUT_HEADERS public_headers OUTPUT_TARGETS generated_targets )
该命令会将qt_add_protobuf
命令生成的头文件和目标文件列表相应存储到public_headers
和generated_targets
变量中。
使用标准 CMakeinstall
命令安装工件并为库生成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 工具。
© 2025 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.