FindProtobuf¶
注意
如果 Protobuf 库是使用其基于 CMake 的构建系统构建和安装的,它会提供一个包配置文件,供find_package()命令在配置模式下使用。
find_package(Protobuf CONFIG)
在这种情况下,导入的目标和 CMake 命令,如protobuf_generate(),由上游包提供,而不是由本模块提供。此外,此处记录的某些变量在配置模式下不可用,因为导入的目标是首选的。有关使用详细信息,请参阅上游文档,这是 Protobuf 与 CMake 结合使用的推荐方式。
本模块仅在模块模式下工作。
本模块在模块模式下查找 Protocol Buffers 库 (Protobuf)。
find_package(Protobuf [<version>] [...])
Protobuf 是由 Google 开发的一种开源、语言中立、平台中立的数据结构化序列化机制。它通常用于程序之间或网络之间的数据交换。
版本 3.6 中添加: 支持在find_package(Protobuf <version>)命令中使用 <version> 参数。
版本 3.6 中更改: 所有输入和输出变量都使用 Protobuf_ 前缀。为向后兼容支持带有 PROTOBUF_ 前缀的变量。
导入的目标¶
此模块提供以下 导入目标
protobuf::libprotobuf版本 3.9 中添加。
封装 Protobuf 库使用需求的 Target,在找到 Protobuf 库时可用。
protobuf::libprotobuf-lite版本 3.9 中添加。
封装
protobuf-lite库使用需求的 Target,在找到 Protobuf 及其 lite 库时可用。protobuf::libprotoc版本 3.9 中添加。
封装
protoc库使用需求的 Target,在找到 Protobuf 及其protoc库时可用。protobuf::protoc3.10 版本新增。
导入的 executable target,封装
protoc编译器使用需求,在找到 Protobuf 和protoc时可用。
结果变量¶
此模块定义了以下变量
Protobuf_FOUND3.3 版本中新增。
布尔值,指示是否找到 (所请求版本的) Protobuf 库。
Protobuf_VERSION3.6 版本新增。
找到的 Protobuf 版本。
Protobuf_INCLUDE_DIRS使用 Protobuf 所需的包含目录。
Protobuf_LIBRARIES链接 Protobuf 所需的库。
Protobuf_PROTOC_LIBRARIES链接
protoc库所需的库。Protobuf_LITE_LIBRARIES链接
protobuf-lite库所需的库。
缓存变量¶
以下缓存变量也可以设置
Protobuf_INCLUDE_DIR包含 Protobuf 头文件的目录。
Protobuf_LIBRARYprotobuf库的路径。Protobuf_PROTOC_LIBRARYprotoc库的路径。Protobuf_PROTOC_EXECUTABLEprotoc编译器的路径。Protobuf_LIBRARY_DEBUGprotobuf调试库的路径。Protobuf_PROTOC_LIBRARY_DEBUGprotoc调试库的路径。Protobuf_LITE_LIBRARYprotobuf-lite库的路径。Protobuf_LITE_LIBRARY_DEBUGprotobuf-lite调试库的路径。Protobuf_SRC_ROOT_FOLDER使用 MSVC 编译时,如果设置了此缓存变量,则会搜索 protobuf 默认的 Visual Studio 项目构建位置以查找库和二进制文件。
<Protobuf_SRC_ROOT_FOLDER>/vsprojects/{Debug,Release},或<Protobuf_SRC_ROOT_FOLDER>/vsprojects/x64/{Debug,Release}
提示¶
在调用 find_package(Protobuf) 之前,本模块接受以下可选变量:
Protobuf_DEBUG3.6 版本新增。
布尔变量,启用本模块的调试消息以供调试之用。
Protobuf_USE_STATIC_LIBS版本 3.9 中添加。
设置为 ON 以强制使用静态库。默认为 OFF。
命令¶
如果找到 Protobuf,本模块将提供以下命令:
生成源文件¶
- protobuf_generate¶
3.13 版本新增。
在构建时自动从
.proto模式文件中生成源文件。protobuf_generate( [TARGET <target>] [LANGUAGE <lang>] [OUT_VAR <variable>] [EXPORT_MACRO <macro>] [PROTOC_OUT_DIR <out-dir>] [PLUGIN <plugin>] [PLUGIN_OPTIONS <plugin-options>] [DEPENDENCIES <dependencies>...] [PROTOS <proto-files>...] [IMPORT_DIRS <dirs>...] [APPEND_PATH] [GENERATE_EXTENSIONS <extensions>...] [PROTOC_OPTIONS <options>...] [PROTOC_EXE <executable>] [DESCRIPTORS] )
TARGET <target>要将生成的文件添加为源的 CMake Target。当未使用
OUT_VAR <variable>时,此选项是必需的。LANGUAGE <lang>单个值:
cpp或python。确定要生成的源文件的类型。默认为cpp。对于其他语言,请使用GENERATE_EXTENSIONS选项。OUT_VAR <variable>将包含生成源文件路径的 CMake 变量的名称。
EXPORT_MACRO <macro>应用于所有生成的 Protobuf 消息类和 extern 变量的预处理器宏的名称。例如,这可以用于声明 DLL 导出。该宏应展开为
__declspec(dllexport)或__declspec(dllimport),具体取决于正在编译的内容。此选项仅在
LANGUAGE为cpp时使用。PROTOC_OUT_DIR <out-dir>生成源文件的输出目录。默认为:
CMAKE_CURRENT_BINARY_DIR。PLUGIN <plugin>3.21 版本新增。
一个可选的插件可执行文件。这可能是
grpc_cpp_plugin的路径。PLUGIN_OPTIONS <plugin-options>版本 3.28 新增。
传递给插件的其他选项,例如 gRPC C++ 插件的
generate_mock_code=true。DEPENDENCIES <dependencies>...版本 3.28 新增。
文件生成所依赖的依赖项。这些将转发给底层的
add_custom_command(DEPENDS)调用。版本 4.1 中更改: 此参数现在接受多个值 (
DEPENDENCIES a b c...)。以前只能指定一个值 (DEPENDENCIES "a;b;c;...")。PROTOS <proto-files>...要处理的
.proto模式文件列表。如果同时指定了<target>,则这些文件将与该 Target 的所有.proto源文件合并。IMPORT_DIRS <dirs>...一个或多个模式文件公共父目录的列表。例如,如果模式文件是
proto/helloworld/helloworld.proto,并且导入目录是proto/,则生成的文件将是<out-dir>/helloworld/helloworld.pb.h和<out-dir>/helloworld/helloworld.pb.cc。APPEND_PATH如果指定,所有 proto 模式文件的基本路径将附加到
IMPORT_DIRS(它会导致protoc使用-I参数调用,为包含.proto文件的每个目录)。GENERATE_EXTENSIONS <extensions>...如果省略了
LANGUAGE,则必须设置此项以指定protoc生成的扩展。PROTOC_OPTIONS <options>...版本 3.28 新增。
直接传递给
protoc编译器的其他命令行选项列表。PROTOC_EXE <executable>4.0 版本新增。
用于生成 Protobuf 绑定的命令行程序、路径或 CMake 可执行文件。如果省略,默认使用
protobuf::protoc导入的目标。DESCRIPTORS如果指定,则为每个
.proto源文件,将命令行选项--descriptor_set_out=<proto-file>附加到protoc编译器,从而能够创建自描述消息。此选项仅在<lang>为cpp且 Protobuf 在模块模式下找到时可用。注意
当 Protobuf 在配置模式下找到时,此选项不可用。
已弃用的命令¶
以下命令是为了向后兼容而提供的。
注意
命令 protobuf_generate_cpp() 和 protobuf_generate_python() 仅在相同的目录范围内,即 find_package(Protobuf ...) 被调用的地方,才能正常工作。
注意
如果 Protobuf 在配置模式下找到,从 Protobuf 版本 3.0.0 开始,protobuf_generate_cpp() 和 protobuf_generate_python() 命令**不可用**,除非在上游包配置提示变量 protobuf_MODULE_COMPATIBLE 在调用 find_package(Protobuf ...) 之前设置为布尔 true。
- protobuf_generate_cpp¶
版本 4.1 已弃用: 使用
protobuf_generate()。在构建时自动从
.proto模式文件中生成 C++ 源文件。protobuf_generate_cpp( <sources-variable> <headers-variable> [DESCRIPTORS <variable>] [EXPORT_MACRO <macro>] <proto-files>... )
<sources-variable>要定义的变量名,它将包含一个生成的 C++ 源文件列表。
<headers-variable>要定义的变量名,它将包含一个生成的头文件列表。
DESCRIPTORS <variable>3.10 版本新增。
要定义的变量名,如果请求,它将包含一个生成的描述符文件列表。
注意
当 Protobuf 在配置模式下找到时,此选项不可用。
EXPORT_MACRO <macro>一个宏的名称,它应该展开为
__declspec(dllexport)或__declspec(dllimport),具体取决于正在编译的内容。<proto-files>...一个或多个要处理的
.proto文件。
- protobuf_generate_python¶
版本 4.1 已弃用: 使用
protobuf_generate()。3.4 版本新增。
在构建时自动从
.proto模式文件中生成 Python 源文件。protobuf_generate_python(<python-sources-variable> <proto-files>...)
<python-sources-variable>要定义的变量名,它将包含一个生成的 Python 源文件列表。
<proto-files>...一个或多个要处理的
.proto文件。
命令 protobuf_generate_cpp() 和 protobuf_generate_python() 在调用前接受以下可选变量:
Protobuf_IMPORT_DIRS版本 4.1 已弃用。
用于搜索导入的
.proto文件的其他目录列表。PROTOBUF_GENERATE_CPP_APPEND_PATH版本 4.1 已弃用: 使用
protobuf_generate(APPEND_PATH)命令选项。一个布尔变量,如果设置为布尔 true,则会导致
protoc使用-I参数调用,为包含.proto文件的每个目录。默认情况下,它设置为布尔 true。
示例¶
示例:查找 Protobuf¶
查找 Protobuf 库
find_package(Protobuf)
或者,查找 Protobuf 并指定最低必需版本
find_package(Protobuf 30)
或者,查找 Protobuf 并将其设为必需 (如果未找到,处理将停止并显示错误消息)
find_package(Protobuf REQUIRED)
示例:在配置模式下查找 Protobuf¶
当 Protobuf 库使用其基于 CMake 的构建系统构建和安装时,可以在配置模式下找到它。
find_package(Protobuf CONFIG)
然而,一些 Protobuf 安装可能仍然不提供包配置文件。下面的示例展示了如何使用CMAKE_FIND_PACKAGE_PREFER_CONFIG变量在配置模式下查找 Protobuf,并在找不到配置文件时回退到模块模式。
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
find_package(Protobuf)
unset(CMAKE_FIND_PACKAGE_PREFER_CONFIG)
示例:使用 Protobuf¶
查找 Protobuf 并将其导入的库 Target 链接到项目 Target。
find_package(Protobuf)
target_link_libraries(example PRIVATE protobuf::libprotobuf)
示例:处理 Proto 模式文件¶
以下示例演示了如何将添加到 Target 的所有 *.proto 模式源文件处理为 C++ 源文件。
CMakeLists.txt¶cmake_minimum_required(VERSION 3.24)
project(ProtobufExample)
add_executable(example main.cxx person.proto)
find_package(Protobuf)
if(Protobuf_FOUND)
protobuf_generate(TARGET example)
endif()
target_link_libraries(example PRIVATE protobuf::libprotobuf)
target_include_directories(example PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
person.proto¶syntax = "proto3";
message Person {
string name = 1;
int32 id = 2;
}
main.cxx¶#include <iostream>
#include "person.pb.h"
int main()
{
Person person;
person.set_name("Alice");
person.set_id(123);
std::cout << "Name: " << person.name() << "\n";
std::cout << "ID: " << person.id() << "\n";
return 0;
}
示例:使用 Protobuf 和 gRPC¶
以下示例展示了如何使用 Protobuf 和 gRPC。
CMakeLists.txt¶find_package(Protobuf REQUIRED)
find_package(gRPC CONFIG REQUIRED)
add_library(ProtoExample Example.proto)
target_link_libraries(ProtoExample PUBLIC gRPC::grpc++)
protobuf_generate(TARGET ProtoExample)
protobuf_generate(
TARGET ProtoExample
LANGUAGE grpc
PLUGIN protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>
PLUGIN_OPTIONS generate_mock_code=true
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc
)
示例:升级已弃用的命令¶
以下示例展示了如何使用已弃用的命令及其现代替代命令来处理 .proto 文件并生成 C++ 代码。
CMakeLists.txt (使用已弃用命令)¶find_package(Protobuf)
if(Protobuf_FOUND)
protobuf_generate_cpp(
proto_sources
proto_headers
EXPORT_MACRO DLL_EXPORT
DESCRIPTORS proto_descriptors
src/protocol/Proto1.proto
src/protocol/Proto2.proto
)
endif()
target_sources(
example
PRIVATE ${proto_sources} ${proto_headers} ${proto_descriptors}
)
target_link_libraries(example PRIVATE protobuf::libprotobuf)
CMakeLists.txt (已升级代码)¶find_package(Protobuf)
if(Protobuf_FOUND)
protobuf_generate(
TARGET example
EXPORT_MACRO DLL_EXPORT
IMPORT_DIRS src/protocol
DESCRIPTORS
PROTOS
src/protocol/Proto1.proto
src/protocol/Proto2.proto
)
endif()
target_link_libraries(example PRIVATE protobuf::libprotobuf)
以下示例展示了如何使用已弃用的命令及其现代替代命令来处理 .proto 文件并生成 Python 代码。
CMakeLists.txt (使用已弃用命令)¶find_package(Protobuf)
if(Protobuf_FOUND)
protobuf_generate_python(python_sources foo.proto)
endif()
add_custom_target(proto_files DEPENDS ${python_sources})
CMakeLists.txt (已升级代码)¶find_package(Protobuf)
if(Protobuf_FOUND)
protobuf_generate(
LANGUAGE python
PROTOS foo.proto
OUT_VAR python_sources
)
endif()
add_custom_target(proto_files DEPENDS ${python_sources})