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

CMake中protobuf_generate执行成功但未生成代码求助

问题:CMake配置成功但未生成gRPC/Protobuf的C++代码

使用CMake v3.26.4构建基于gRPC的C11项目,已从源码编译gRPC并关联proto文件处理步骤,CMake配置无错误提示,但始终未生成.pb/.grpc.pb对应的C头文件和源文件,全磁盘搜索无果;已通过官方protoc工具验证.proto文件语法正确且可生成服务定义。

项目文件结构

root/
├─CMakeList.txt
├─service/
| ├─CMakeLists.txt
| ├─proto
|   ├─CMakeLists.txt
|   ├─service.proto
├─third_party
| ├─CMakeLists.txt
| ├─grpc
| ├─abseil

proto目录下的CMakeLists.txt内容

find_package(Threads REQUIRED)
if(MSVC)
  add_definitions(-D_WIN32_WINNT=0x600)
endif()

# Link in third_party libraries needed for code generation
target_link_libraries(my_project
    PRIVATE
        protobuf
        grpc++
        grpc_plugin_support)


# Get the environment variables needed for later.
set(pb_cmake ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/third_party/grpc/third_party/protobuf/cmake/protobuf/protobuf-generate.cmake)
message("protobuf_generate function defined at ${pb_cmake}") #for sanity check
include(${pb_cmake})

target_include_directories(cengine PRIVATE ${_GRPC_CPP_PLUGIN_INCLUDE_DIRS})

set(grpc_cpp_plugin_location $<TARGET_FILE:grpc_cpp_plugin>)
message("gRPC plugin is at ${grpc_cpp_plugin_location}") #for sanity check

# Protobuf/Grpc source files
set(PROTO_SRC_DIR ${PROJECT_SOURCE_DIR}/service/proto)
set(PROTO_GEN_DIR ${PROJECT_SOURCE_DIR}/gen)
set(PROTO_FILES
    ${PROTO_SRC_DIR}/first_service.proto
    ${PROTO_SRC_DIR}/second_service.proto
)

# Add Library target with protobuf sources
add_library(service_proto OBJECT ${PROTO_FILES})
target_link_libraries(service_proto
    PUBLIC
        protobuf::libprotobuf
        grpc
        grpc++
)
target_include_directories(service_proto PUBLIC ${PROTO_GEN_DIR})

# Compile protobuf and grpc files in myproto target to cpp
protobuf_generate(
    TARGET service_proto
    LANGUAGE cpp
    GENERATE_EXTENSIONS .pb.hpp .pb.cpp
    PROTOC_OUT_DIR "${PROTO_GEN_DIR}"
)
protobuf_generate(
    TARGET service_proto
    LANGUAGE grpc
    GENERATE_EXTENSIONS .grpc.pb.hpp .grpc.pb.cpp
    PLUGIN "protoc-gen-grpc=${grpc_cpp_plugin_location}"
    PROTOC_OUT_DIR "${PROTO_GEN_DIR}"
)

CMake执行输出

>cmake -B ../out -S . -G "MinGW Makefiles"
--
-- 23.0.0
CMake Deprecation Warning at third_party/grpc/third_party/zlib/CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


protobuf_generate function defined at [REDACTED]
gRPC plugin is at $<TARGET_FILE:grpc_cpp_plugin>
-- Configuring done (1.2s)
-- Generating done (13.5s)
-- Build files have been written to: C:/src/out

排查与解决思路

1. 确认代码生成的触发时机

protobuf_generate默认不会在CMake配置阶段生成代码,而是在构建阶段(执行make/ninja等命令时)触发protoc编译。仅执行cmake配置不会生成文件,需进入out目录运行构建命令:

mingw32-make

之后检查gen目录是否生成目标文件。

2. 修正gRPC插件路径的延迟展开问题

CMake输出中gRPC plugin is at $<TARGET_FILE:grpc_cpp_plugin>是生成器表达式,该表达式仅在构建阶段解析为实际路径,但protobuf_generate的PLUGIN参数在配置阶段就需要明确路径,直接使用会导致protoc找不到插件。

修改方式:

# 替换原grpc_cpp_plugin_location设置,通过find_program获取插件实际路径
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin HINTS ${CMAKE_BINARY_DIR}/third_party/grpc/bin)

然后在protobuf_generate的PLUGIN参数中使用:

PLUGIN "protoc-gen-grpc=${GRPC_CPP_PLUGIN}"

3. 确保生成目录存在且有权限

  • CMake不会自动创建PROTO_GEN_DIR,需手动添加创建命令:
file(MAKE_DIRECTORY ${PROTO_GEN_DIR})
  • 检查Windows系统下${PROJECT_SOURCE_DIR}/gen目录的读写权限,避免因权限问题导致文件无法生成。

4. 显式关联proto文件到生成命令

尝试在protobuf_generate中显式指定PROTO_FILES参数,避免自动查找的潜在问题:

protobuf_generate(
    TARGET service_proto
    LANGUAGE cpp
    GENERATE_EXTENSIONS .pb.hpp .pb.cpp
    PROTOC_OUT_DIR "${PROTO_GEN_DIR}"
    PROTO_FILES ${PROTO_FILES}
)
protobuf_generate(
    TARGET service_proto
    LANGUAGE grpc
    GENERATE_EXTENSIONS .grpc.pb.hpp .grpc.pb.cpp
    PLUGIN "protoc-gen-grpc=${GRPC_CPP_PLUGIN}"
    PROTOC_OUT_DIR "${PROTO_GEN_DIR}"
    PROTO_FILES ${PROTO_FILES}
)

5. 启用构建日志排查细节

执行构建命令时开启详细日志,查看protoc的具体调用情况,排查隐藏错误:

mingw32-make VERBOSE=1

通过日志可确认protoc是否被正确调用、插件路径是否有效、输出目录是否正确等。

6. 修正无关目标的引用问题

原CMakeLists中target_link_libraries(my_project ...)和target_include_directories(cengine ...)中的my_project、cengine目标若未在当前CMakeLists中定义,需移除这些无关语句(或确保上级目录已正确导出这些目标),避免干扰proto生成流程。


内容的提问来源于stack exchange,提问作者user5859728

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:43:15