FindProtobuf¶
注意
如果Protobuf库是使用其基于CMake的构建系统构建和安装的,它会提供一个包配置文件,用于在配置模式下与find_package()
命令一起使用
find_package(Protobuf CONFIG)
在这种情况下,导入的目标和CMake命令,例如protobuf_generate()
,由上游包提供,而不是此模块。此外,此处记录的某些变量在配置模式下不可用,因为导入的目标是首选。有关使用详细信息,请参阅上游文档,这是使用CMake与Protobuf的推荐方式。
此模块仅在模块模式下工作。
此模块在模块模式下查找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::protoc
3.10 版本新增。
封装
protoc
编译器使用要求的导入可执行文件Target,如果找到Protobuf和protoc
则可用。
结果变量¶
此模块定义了以下变量
Protobuf_FOUND
布尔值,表示是否找到(请求版本的)Protobuf库。
Protobuf_VERSION
3.6 版本新增。
找到的Protobuf版本。
Protobuf_INCLUDE_DIRS
使用Protobuf所需的包含目录。
Protobuf_LIBRARIES
链接Protobuf所需的库。
Protobuf_PROTOC_LIBRARIES
链接
protoc
库所需的库。Protobuf_LITE_LIBRARIES
链接
protobuf-lite
库所需的库。
缓存变量¶
以下缓存变量也可以设置
Protobuf_INCLUDE_DIR
包含Protobuf头文件的包含目录。
Protobuf_LIBRARY
protobuf
库的路径。Protobuf_PROTOC_LIBRARY
protoc
库的路径。Protobuf_PROTOC_EXECUTABLE
protoc
编译器的路径。Protobuf_LIBRARY_DEBUG
protobuf
调试库的路径。Protobuf_PROTOC_LIBRARY_DEBUG
protoc
调试库的路径。Protobuf_LITE_LIBRARY
protobuf-lite
库的路径。Protobuf_LITE_LIBRARY_DEBUG
protobuf-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_DEBUG
3.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目标。当未使用
OUT_VAR <variable>
时,此选项是必需的。LANGUAGE <lang>
单个值:
cpp
或python
。确定要生成的源文件类型。默认为cpp
。对于其他语言,请使用GENERATE_EXTENSIONS
选项。OUT_VAR <variable>
将填充生成源文件路径的CMake变量的名称。
EXPORT_MACRO <macro>
应用于所有生成的Protobuf消息类和外部变量的预处理器宏的名称。例如,这可以用于声明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>
,这些文件将与该目标的所有.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
为每个包含.proto
文件的目录调用-I
参数)。GENERATE_EXTENSIONS <extensions>...
如果省略
LANGUAGE
,则必须设置此项以指定protoc
生成的扩展。PROTOC_OPTIONS <options>...
版本 3.28 新增。
直接传递给
protoc
编译器的附加命令行选项列表。PROTOC_EXE <executable>
4.0 版本新增。
用于生成Protobuf绑定的命令行程序、路径或CMake可执行文件。如果省略,默认使用
protobuf::protoc
导入目标。DESCRIPTORS
如果指定,命令行选项
--descriptor_set_out=<proto-file>
将附加到protoc
编译器,用于每个.proto
源文件,从而实现自描述消息的创建。此选项只能在<lang>
为cpp
且Protobuf在模块模式下找到时使用。注意
当Protobuf在配置模式下找到时,此选项不可用。
已废弃的命令¶
以下命令为了向后兼容而提供。
注意
protobuf_generate_cpp()
和protobuf_generate_python()
命令仅在调用find_package(Protobuf ...)
的同一目录范围内才能正确工作。
注意
如果Protobuf在配置模式下找到,自Protobuf 3.0.0版本起,protobuf_generate_cpp()
和protobuf_generate_python()
命令不可用,除非在调用find_package(Protobuf ...)
之前,上游包配置提示变量protobuf_MODULE_COMPATIBLE
设置为布尔真。
- 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)
命令选项。一个布尔变量,如果设置为布尔真,将导致
protoc
为每个包含.proto
文件的目录调用-I
参数。默认情况下,它设置为布尔真。
示例¶
示例:查找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并将其导入的库目标链接到项目目标
find_package(Protobuf)
target_link_libraries(example PRIVATE protobuf::libprotobuf)
示例:处理Proto模式文件¶
以下示例演示了如何将添加到目标的所有*.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})