- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
本文围绕 CMake 官方仓库中 FindProtobuf 模块 的完整文档展开,系统讲解如何在 CMake 工程中查找并链接 Protocol Buffers(Protobuf)库、利用
protobuf_generate系列命令在构建期自动从.proto文件生成 C++/Python 源码,并结合模块源码实现与仓库自带测试用例,帮助读者掌握从find_package到代码生成、链接、gRPC 扩展的全链路集成方案。
一、模块定位:module mode 与 config mode 的区别
Protocol Buffers 是 Google 开发的开源、语言中立、平台无关的结构化数据序列化机制,常用于程序间或网络间的数据交换。CMake 官方提供的FindProtobuf模块位于 Modules/FindProtobuf.cmake,其用途是在module mode下查找已安装的 Protobuf 库:
find_package(Protobuf [<version>] [...])需要特别注意的是(模块文档开篇即强调):
如果 Protobuf 库是使用其CMake 构建系统构建并安装的,它会提供一份package configuration file(配置模式包),此时应优先使用config mode:
find_package(Protobuf CONFIG)在 config mode 下,导入目标和
protobuf_generate等命令由上游 Protobuf 包自身提供,本模块文档中记录的部分变量在 config mode 下不可用(因为官方推荐直接使用导入目标),具体用法以 Protobuf 上游文档为准。官方明确表示:当 Protobuf 使用 CMake 构建时,config mode 是推荐用法。本模块仅在 module mode 下工作,即执行
find_package(Protobuf)且未命中 config 包、或设置CMAKE_FIND_PACKAGE_PREFER_CONFIG FALSE时,由 CMake 加载本模块完成查找。
从版本演进看,模块支持两个关键里程碑:
- 3.6:
find_package(Protobuf <version>)支持版本号参数;所有输入/输出变量统一改用Protobuf_前缀(PROTOBUF_前缀仅保留向后兼容)。 - 3.9 起:陆续引入
protobuf::libprotobuf、protobuf::libprotobuf-lite、protobuf::libprotoc导入库目标与protobuf::protoc导入可执行目标。
二、导入目标(Imported Targets)
当模块成功找到 Protobuf 后,会提供以下导入目标(均为::命名空间目标,可直接用于target_link_libraries):
| 目标名 | 引入版本 | 说明 |
|---|---|---|
protobuf::libprotobuf | 3.9 | 封装完整 Protobuf 库的使用要求,库存在即可用 |
protobuf::libprotobuf-lite | 3.9 | 封装精简版protobuf-lite库(体积更小,适用于嵌入式等受限场景) |
protobuf::libprotoc | 3.9 | 封装protoc库(编译器库,写编译器插件时使用) |
protobuf::protoc | 3.10 | 导入的protoc编译器可执行目标 |
从源码实现看,这些目标在 Modules/FindProtobuf.cmake 中以UNKNOWN IMPORTED/IMPORTED类型创建,并附带精确的使用要求:
INTERFACE_INCLUDE_DIRECTORIES指向Protobuf_INCLUDE_DIR;- 同时记录
IMPORTED_LOCATION以及按配置区分的IMPORTED_LOCATION_RELEASE/IMPORTED_LOCATION_DEBUG(由Protobuf_LIBRARY_RELEASE/Protobuf_LIBRARY_DEBUG驱动); - 若
Protobuf_VERSION不低于 3.6,目标会附加INTERFACE_COMPILE_FEATURES cxx_std_11,自动为下游目标启用 C++11 编译特性(见 Modules/FindProtobuf.cmake); - 在 Windows 且未使用静态库时,会自动附加
PROTOBUF_USE_DLLS编译定义以匹配 DLL 导出约定; - 在 UNIX 平台,若找到
Threads::Threads则自动追加链接Threads::Threads(Protobuf 头文件可能依赖线程)。
三、结果变量与缓存变量
3.1 结果变量(Result Variables)
查找结束后,模块会定义以下变量:
| 变量 | 引入版本 | 含义 |
|---|---|---|
Protobuf_FOUND | 3.3 | 是否找到(指定版本)Protobuf 库的布尔值 |
Protobuf_VERSION | 3.6 | 找到的 Protobuf 版本号 |
Protobuf_INCLUDE_DIRS | — | 使用 Protobuf 所需的头文件目录 |
Protobuf_LIBRARIES | — | 使用 Protobuf 需要链接的库列表 |
Protobuf_PROTOC_LIBRARIES | — | 使用protoc库需要链接的库列表 |
Protobuf_LITE_LIBRARIES | — | 使用protobuf-lite库需要链接的库列表 |
3.2 缓存变量(Cache Variables)
以下缓存变量也可供用户设置或查询:
| 缓存变量 | 含义 |
|---|---|
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 源码根目录(见下文) |
Protobuf_SRC_ROOT_FOLDER专用于 Windows/MSVC 场景:当使用 Protobuf 自带的 Visual Studio 工程构建产物时,设置该变量后,模块会去以下位置查找库和可执行文件:
<Protobuf_SRC_ROOT_FOLDER>/vsprojects/{Debug,Release}<Protobuf_SRC_ROOT_FOLDER>/vsprojects/x64/{Debug,Release}
3.3 向后兼容:双写大小写前缀
模块保留了大量向后兼容逻辑:查找前,会把已定义的PROTOBUF_*大写输入变量(如PROTOBUF_SRC_ROOT_FOLDER、PROTOBUF_IMPORT_DIRS、PROTOBUF_DEBUG等)映射为Protobuf_*形式;查找结束后,又会把全部Protobuf_*输出变量以string(TOUPPER)形式回写到PROTOBUF_*大写变量(见 Modules/FindProtobuf.cmake)。因此旧工程中依赖PROTOBUF_LIBRARIES等大写变量的代码仍然可用,但新代码应统一使用Protobuf_前缀。
四、查找前的 Hint 变量
在调用find_package(Protobuf)之前,可以设置以下可选变量影响查找行为:
Protobuf_DEBUG(3.6 引入):布尔值,置 ON 后模块会打印内部调试信息,便于排查查找路径、版本解析等问题。源码中大量使用if(Protobuf_DEBUG)输出message(STATUS ...),例如输出Protobuf_USE_STATIC_LIBS当前值、common.h位置、从common.h解析出的版本号、protoc --version结果等。Protobuf_USE_STATIC_LIBS(3.9 引入):置 ON 强制使用静态库,默认 OFF。实现上,置 ON 时模块会临时修改CMAKE_FIND_LIBRARY_SUFFIXES:Windows 下优先.lib/.a,其他平台直接置为.a,查找结束后恢复原值(见 Modules/FindProtobuf.cmake)。
五、核心命令:protobuf_generate
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] )5.1 各选项详解
| 选项 | 说明 |
|---|---|
TARGET <target> | 生成的源码文件作为源文件加入该 CMake 目标;当不使用OUT_VAR时必须指定 |
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>,则与目标上的所有.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 引入)用于生成绑定的命令行程序、路径或 CMake 可执行目标;省略时默认使用protobuf::protoc导入目标 |
DESCRIPTORS | 指定后,为每个.proto源文件附加--descriptor_set_out=<proto-file>选项,生成自描述消息描述文件;仅当<lang>为cpp且处于 module mode 时可用,config mode 下不可用 |
5.2 源码级执行机制
从 Modules/FindProtobuf.cmake 的实现可以看清该命令的完整工作流:
参数校验:
PROTOS与TARGET均未提供,或OUT_VAR与TARGET均未提供时,message(SEND_ERROR)报错并return();LANGUAGE缺省为cpp(统一转为小写);PROTOC_OUT_DIR缺省为${CMAKE_CURRENT_BINARY_DIR}。默认扩展名映射:
cpp→.pb.h .pb.cc;python→_pb2.py;其他语言若无GENERATE_EXTENSIONS会直接报错。收集
.proto文件:指定TARGET时,通过get_target_property(... SOURCES)取出目标源文件,筛选出以proto结尾的文件并入PROTOS。确定
protoc可执行文件:未显式传PROTOC_EXE时,要求存在protobuf::protoc目标,否则报错并提示三种补救方式:设置Protobuf_PROTOC_EXECUTABLE变量、给protobuf_generate传PROTOC_EXE、或确保protoc在 CMake 搜索路径中。构建
-I导入路径:APPEND_PATH为真时为每个.proto文件所在目录追加-I;随后追加IMPORT_DIRS(均取绝对路径并去重);若未启用APPEND_PATH,还会默认追加-I ${CMAKE_CURRENT_SOURCE_DIR}。计算生成文件路径:对每个
.proto文件计算相对目录(默认相对CMAKE_CURRENT_SOURCE_DIR),拼出<PROTOC_OUT_DIR>/<相对路径>/<基名><扩展名>;若启用DESCRIPTORS且语言为cpp,额外生成${CMAKE_CURRENT_BINARY_DIR}/<基名>.desc。生成自定义命令:最终通过
add_custom_command执行protoc,命令行形如:protoc [PROTOC_OPTIONS...] --<lang>_out [plugin-options]:<PROTOC_OUT_DIR> [--plugin=...] [--descriptor_set_out=...] [-I dir...] <abs.proto>依赖项包含
.proto文件本身、protobuf::protoc以及用户传入的DEPENDENCIES,并注明VERBATIM保证参数原样传递。产出与注入:所有生成文件被标记为
GENERATED TRUE;OUT_VAR结果写回父作用域(PARENT_SCOPE);指定TARGET时通过target_sources(... PRIVATE ...)注入目标。
仓库自带测试 Tests/FindProtobuf/Test/CMakeLists.txt 展示了多个典型用法,例如:
add_library(msgs_protoc_options msgs/example.proto) protobuf_generate(TARGET msgs_protoc_options DESCRIPTORS EXPORT_MACRO PROTO_EXPORT PLUGIN_OPTIONS speed PROTOC_OPTIONS --include_imports --include_source_info)并注释说明"多个 protoc/plugin 选项必须仍然汇成单一的 COMMENT 字符串"——这正是实现中对PLUGIN_OPTIONS用逗号拼接、对PROTOC_OPTIONS以空格替换分号的细节体现。
六、Deprecated 命令:protobuf_generate_cpp / protobuf_generate_python
为向后兼容,模块保留了旧版命令,4.1 起标记为 deprecated,应迁移到protobuf_generate。
6.1 protobuf_generate_cpp
在构建期从.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 引入):保存生成的描述文件列表;config mode 下不可用;EXPORT_MACRO <macro>:展开为__declspec(dllexport)/__declspec(dllimport)的宏名;<proto-files>...:一个或多个待处理的.proto文件。
6.2 protobuf_generate_python
(3.4 引入,4.1 起 deprecated)在构建期生成 Python 源码:
protobuf_generate_python(<python-sources-variable> <proto-files>...)6.3 两个旧命令共用的前置变量
调用旧命令前还可设置以下变量:
Protobuf_IMPORT_DIRS(4.1 deprecated):附加的.proto导入搜索目录列表;PROTOBUF_GENERATE_CPP_APPEND_PATH(4.1 deprecated,请改用protobuf_generate(APPEND_PATH)):布尔值,为真时让protoc对每个包含.proto文件的目录都传-I;默认值为真(见源码if(NOT DEFINED PROTOBUF_GENERATE_CPP_APPEND_PATH) set(PROTOBUF_GENERATE_CPP_APPEND_PATH TRUE))。
6.4 旧命令的作用域与 config mode 限制(重要)
- 两个旧命令只在与
find_package(Protobuf ...)相同的目录作用域内正确工作; - 若 Protobuf 以config mode找到,则自 Protobuf 3.0.0 起
protobuf_generate_cpp()与protobuf_generate_python()不可用,除非在调用find_package(Protobuf ...)之前将上游包配置提示变量protobuf_MODULE_COMPATIBLE设为布尔真。
实现上,两个旧函数本质是protobuf_generate的薄包装:PROTOBUF_GENERATE_CPP解析参数后转调protobuf_generate(... LANGUAGE cpp ...),再把输出的文件按扩展名.cc(源)、.desc(描述文件)、其余(头文件)分类回写;PROTOBUF_GENERATE_PYTHON则转调protobuf_generate(... LANGUAGE python ...)(见 Modules/FindProtobuf.cmake)。
七、完整实战示例
7.1 查找 Protobuf 的三种基本写法
# 只查找,未找到不报错 find_package(Protobuf) # 指定最低版本 find_package(Protobuf 30) # 必需,找不到则停止并报错 find_package(Protobuf REQUIRED)7.2 config mode 优先、module mode 兜底
某些 Protobuf 安装可能不提供 package configuration file。官方推荐的兜底写法是利用CMAKE_FIND_PACKAGE_PREFER_CONFIG:
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) find_package(Protobuf) unset(CMAKE_FIND_PACKAGE_PREFER_CONFIG)这样优先尝试 config mode,找不到配置文件时自动回退到 module mode。
7.3 链接导入目标
find_package(Protobuf) target_link_libraries(example PRIVATE protobuf::libprotobuf)7.4 完整工程:生成并编译 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; }注意:example目标把person.proto直接作为源文件加入,protobuf_generate(TARGET example)自动收集其中的.proto文件并生成person.pb.h/person.pb.cc注入目标;头文件生成在${CMAKE_CURRENT_BINARY_DIR},故需将该目录加入包含路径。
7.5 Protobuf + gRPC
gRPC 场景使用PLUGIN、PLUGIN_OPTIONS与GENERATE_EXTENSIONS组合生成服务桩代码:
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 )这里LANGUAGE grpc并非内置语言,必须配合GENERATE_EXTENSIONS指明插件输出扩展名;$<TARGET_FILE:...>生成器表达式在构建期解析为插件绝对路径。
仓库测试中对应的 gRPC 用例(受CMake_TEST_FindProtobuf_gRPC开关控制)还演示了IMPORT_DIRS与APPEND_PATH对输出目录布局的影响(见 Tests/FindProtobuf/Test/CMakeLists.txt):
- 默认(无 IMPORT_DIRS/APPEND_PATH):生成文件落在
${CMAKE_CURRENT_BINARY_DIR}/msgs/grpc/; - 带
IMPORT_DIRS msgs/:落在${CMAKE_CURRENT_BINARY_DIR}/grpc/; - 带
APPEND_PATH:直接落在${CMAKE_CURRENT_BINARY_DIR}/。
7.6 从旧命令升级到 protobuf_generate
旧式 C++ 生成:
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)升级后的等价写法:
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)旧式 Python 生成:
find_package(Protobuf) if(Protobuf_FOUND) protobuf_generate_python(python_sources foo.proto) endif() add_custom_target(proto_files DEPENDS ${python_sources})升级后:
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})八、模块内部查找流程与版本校验
理解模块的查找顺序有助于排查“找不到库”或“版本不匹配”的问题。从 Modules/FindProtobuf.cmake 源码看,主要流程如下:
- 库查找:通过内部函数
_protobuf_find_libraries依次查找Protobuf(protobuf)、Protobuf_LITE(protobuf-lite)、Protobuf_PROTOC(protoc),每个库同时查找 release 与 debug 变体(debug 名自动加d后缀),再借助SelectLibraryConfigurations.cmake的select_library_configurations合成*_LIBRARIES;UNIX 下若启用了线程还会追加${CMAKE_THREAD_LIBS_INIT}。 - 头文件查找:
find_path(Protobuf_INCLUDE_DIR google/protobuf/service.h ...)。 - 编译器查找:
find_program(Protobuf_PROTOC_EXECUTABLE NAMES protoc ...),MSVC 下额外搜索vsprojects/{x64/}{Debug,Release}目录。 - 版本解析:读取
${Protobuf_INCLUDE_DIR}/google/protobuf/stubs/common.h中的GOOGLE_PROTOBUF_VERSION宏(形如3023002的整数),通过math(EXPR ...)拆出主/次/修订号组成Protobuf_VERSION。 - 版本一致性校验:执行
protoc --version解析libprotoc <version>,与库版本比对,不一致时输出WARNING;实现中还特别注释:protoc 22 及以后版本不再打印主版本号,因此比对逻辑额外兼容minor.subminor形式(见 Modules/FindProtobuf.cmake)。 - 最终判定:调用
find_package_handle_standard_args(Protobuf REQUIRED_VARS Protobuf_LIBRARIES Protobuf_INCLUDE_DIR VERSION_VAR Protobuf_VERSION)生成标准的Protobuf_FOUND结果与错误提示。
模块还针对 MSVC 做了特殊兼容:由于 Google 提供的 vcproj 工程在 Windows 上生成的库带lib前缀,模块会临时把CMAKE_FIND_LIBRARY_PREFIXES改为"lib" ""再恢复,确保libprotobuf这类命名也能被正确匹配。
九、官方回归测试:验证模块与生成命令
仓库为 FindProtobuf 提供了完整回归测试(位于 Tests/FindProtobuf/CMakeLists.txt 与 Tests/FindProtobuf/Test/CMakeLists.txt),通过ctest --build-and-test在临时目录独立构建TestFindProtobuf工程,覆盖:
- 分别用导入目标(
protobuf::libprotobuf、protobuf::libprotobuf-lite、protobuf::libprotoc)和传统变量(${Protobuf_INCLUDE_DIRS}、${Protobuf_LIBRARIES}、${Protobuf_LITE_LIBRARIES}、${Protobuf_PROTOC_LIBRARIES})两种风格链接并运行测试程序; - 通过
protobuf::protoc --version验证导入的可执行目标可用; - 调用
protobuf_generate_cpp生成msgs/example.proto与msgs/example_desc.proto的源码与描述文件,编译后运行test_generate、test_desc验证生成代码可编译、可运行; - 在 gRPC 开关开启时,验证
PLUGIN、IMPORT_DIRS、APPEND_PATH三种模式下生成的 gRPC 桩代码均可构建运行。
测试目标属性中设置的FAIL_REGULAR_EXPRESSION PROTOC_EXE还用于捕获PROTOC_EXE相关错误输出。这些用例可直接作为读者本地集成 Protobuf 的参考模板。
十、快速决策清单
- 用 config mode 还是 module mode?Protobuf 由 CMake 构建安装 → 优先
find_package(Protobuf CONFIG);否则用本模块(module mode),并可用CMAKE_FIND_PACKAGE_PREFER_CONFIG实现“config 优先、module 兜底”。 - 链接用目标还是变量?优先
protobuf::libprotobuf等命名空间目标(自动携带包含目录、C++11 特性、Windows DLL 定义、线程依赖);老代码可继续用Protobuf_LIBRARIES系列变量。 - 生成代码用什么命令?新工程一律用
protobuf_generate;旧命令仅在维护遗留代码时使用,并注意其目录作用域与 config mode 限制。 - 多语言/插件怎么办?非 cpp/python 语言必须提供
GENERATE_EXTENSIONS;gRPC 等插件用PLUGIN+PLUGIN_OPTIONS。 - 排查问题开什么开关?设置
Protobuf_DEBUG=ON可观察模块完整查找过程;Protobuf_USE_STATIC_LIBS=ON强制静态链接。
- 构建工具
- 开发工具
- CLI
【免费下载链接】CMake
Mirror of CMake upstream repository
相关推荐
鸣潮后台自动战斗与自动刷声骸如何配置:ok-ww 自动化工具 15 分钟上手实录
鸣潮后台自动战斗与自动刷声骸如何配置:ok ww 自动化工具 15 分钟上手实录 晚上十一点,一局打完正准备关游戏,突然想起来:今天的日常还没清,体力也还剩大半
构建工具开发工具CLINumPy F2PY 与 CMake 集成实战:构建 Fortran 扩展模块的完整指南
NumPy F2PY 与 CMake 集成实战:构建 Fortran 扩展模块的完整指南 导读 本文围绕 doc/source/f2py/buildtools/
科学计算数据分析【免费下载】 Protocol Buffers CMake集成指南:protobuf_generate函数详解
Protocol Buffers CMake集成指南:protobuf_generate函数详解 前言 在现代C++项目中,Protocol Buffers(简
序列化代码生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考