You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CMake构建过程中生成protoc和grpc_cpp_plugin并用于生成gRPC/Protobuf代码

如何在CMake构建过程中生成protoc和grpc_cpp_plugin并用于生成gRPC/Protobuf代码

你说得太对了,硬编码本地绝对路径确实是个头疼的坏习惯,完全把构建过程绑死在你的机器上,换台环境直接就炸。其实咱们完全可以借助CMake的特性,让构建系统自动编译出protoc和grpc_cpp_plugin,再用这些本地构建的工具生成代码,全程不用写死任何路径。下面我给你一步步拆解怎么做:

核心思路

当你用FetchContent引入gRPC时,它会自动拉取并构建依赖的Protobuf库(包括protoc编译器);同时gRPC本身在构建时也会生成grpc_cpp_plugin插件。CMake会帮我们管理这些工具的构建路径,我们只需要用正确的方式引用它们就行,不用自己硬编码。

完整的CMake配置示例

我把你的代码修改成了符合要求的版本,关键修改点会标出来:

# 1. 引入依赖:保留你原来的FetchContent配置,补充工具构建选项
FetchContent_Declare(
  abseil
  GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git
  GIT_TAG 20250512.1
)
FetchContent_Declare(
  gRPC
  GIT_REPOSITORY https://github.com/grpc/grpc.git
  GIT_TAG v1.74.1
)
# 显式开启protoc和grpc_cpp_plugin的构建(gRPC默认会开启,但显式设置更稳妥)
set(gRPC_BUILD_CPP_PLUGIN ON CACHE BOOL "Build gRPC C++ code generation plugin" FORCE)
set(protobuf_BUILD_PROTOC_BINARIES ON CACHE BOOL "Build protoc compiler" FORCE)

FetchContent_MakeAvailable(abseil gRPC)

# 2. 定义proto文件与生成文件路径(优化:把生成文件放到二进制目录,避免污染源码)
file(GLOB proto_files "${CMAKE_CURRENT_SOURCE_DIR}/proto/*.proto")
# 生成文件存到构建目录下的子目录,不污染源码仓库
set(proto_gen_dir "${CMAKE_CURRENT_BINARY_DIR}/proto_generated")
file(MAKE_DIRECTORY ${proto_gen_dir}) # 确保目录提前创建

set(proto_srcs "${proto_gen_dir}/test.pb.cc")
set(proto_hdrs "${proto_gen_dir}/test.pb.h")
set(grpc_srcs "${proto_gen_dir}/test.grpc.pb.cc")
set(grpc_hdrs "${proto_gen_dir}/test.grpc.pb.h")

# 3. 自动获取构建好的工具路径(重点!完全替代硬编码)
# 用生成器表达式获取目标文件路径,CMake会在构建阶段自动解析实际路径
set(protoc_path $<TARGET_FILE:protoc>)
set(grpc_plugin_path $<TARGET_FILE:grpc_cpp_plugin>)

# 4. 修改自定义命令,使用自动获取的工具并添加依赖
add_custom_command(
  OUTPUT "${proto_srcs}" "${proto_hdrs}" "${grpc_srcs}" "${grpc_hdrs}"
  COMMAND ${protoc_path}
  ARGS
    --grpc_out "${proto_gen_dir}"
    --cpp_out "${proto_gen_dir}"
    -I "${CMAKE_CURRENT_SOURCE_DIR}/proto"
    --plugin=protoc-gen-grpc="${grpc_plugin_path}"
    "${proto_files}"
  DEPENDS
    ${proto_files}
    protoc          # 确保protoc先编译完成再生成代码
    grpc_cpp_plugin # 确保grpc插件先编译完成
  COMMENT "Generating gRPC/Protobuf code from .proto files..."
)

关键修改点说明

  1. 显式启用工具构建:
    虽然gRPC默认会构建protoc和cpp插件,但显式设置gRPC_BUILD_CPP_PLUGIN和protobuf_BUILD_PROTOC_BINARIES为ON,能避免不同环境下的默认配置差异,让构建更稳定。

  2. 生成文件与源码分离:
    把生成的.pb.cc、.pb.h放到构建目录(CMAKE_CURRENT_BINARY_DIR)下的子目录,不会污染你的源码仓库,还能避免Debug/Release等不同构建配置的生成文件互相覆盖。

  3. 自动解析工具路径:
    用$<TARGET_FILE:protoc>和$<TARGET_FILE:grpc_cpp_plugin>这两个生成器表达式,CMake会在构建阶段自动解析出工具的实际路径,完全摆脱硬编码的束缚。

  4. 添加工具依赖:
    在DEPENDS里加上protoc和grpc_cpp_plugin目标,CMake会严格保证:先编译好这两个工具,再运行代码生成命令,不会出现“工具还没编译就想用”的错误。

后续衔接:把生成代码加入项目

当你把生成的源文件添加到可执行文件或库时,记得把生成目录加入头文件搜索路径:

add_executable(your_service main.cpp ${proto_srcs} ${grpc_srcs})
# 让编译器能找到生成的头文件
target_include_directories(your_service PRIVATE ${proto_gen_dir})
# 链接gRPC和Protobuf依赖库
target_link_libraries(your_service PRIVATE grpc++ grpc protobuf::libprotobuf)

这样整个构建流程就完全脱离了本地环境的硬编码路径,在任何机器上只要能拉取依赖源码,就能自动完成工具构建、代码生成和项目编译。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 06:54:32