Windows下CMake无法生成Protocol Buffers头文件与源文件
在Windows系统使用CMake 3.23.1编译.proto文件,参考相关文档后仍未生成对应的.cc与.h文件。
我的CMakeLists.txt文件
project(test_proto) cmake_minimum_required(VERSION 3.23) set(Protobuf_DIR "C:/grpc/debug/cmake") set(gRPC_DIR "C:/grpc/debug/lib/cmake/grpc") set(ZLIB_ROOT "C:/zlib/debug") set(c-ares_DIR "C:/grpc/debug/lib/cmake/c-ares") find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) set(PROTO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/proto/server.proto) add_library(test_proto ${PROTO_FILES}) target_link_libraries(test_proto PUBLIC protobuf::libprotobuf PUBLIC gRPC::grpc PUBLIC gRPC::grpc++ ) set(PROTO_BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tmp") set(PROTO_IMPORT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/proto") get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION) message(STATUS " The value of grpc cpp location is: ${grpc_cpp_plugin_location}") protobuf_generate( TARGET test_proto LANGUAGE cpp OUT_VAR PROTO_GENERATED_FILES IMPORT_DIRS ${PROTO_IMPORT_DIRS} PROTOC_OUT_DIR "${PROTO_BINARY_DIR}") protobuf_generate( TARGET test_proto OUT_VAR PROTO_GENERATED_FILES LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${grpc_cpp_plugin_location}" IMPORT_DIRS ${PROTO_IMPORT_DIRS} PROTOC_OUT_DIR "${PROTO_BINARY_DIR}") message(STATUS " The generated files are located in: ${PROTO_GENERATED_FILES}")
运行命令
cmake.exe -D CMAKE_BUILD_TYPE=Debug -G "Visual Studio 16 2019" -S D:\cmake-test -B D:\cmake-test
输出信息
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19042. -- The C compiler identification is MSVC 19.29.30137.0 -- The CXX compiler identification is MSVC 19.29.30137.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: c:/VS/MVS16117/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: c:/VS/MVS16117/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Found ZLIB: C:/zlib/debug/lib/zlibd.lib (found version "1.2.11") -- Found OpenSSL: optimized;C:/Program Files/OpenSSL-Win64/lib/VC/libcrypto64MD.lib;debug;C:/Program Files/OpenSSL-Win64/lib/VC/libcrypto64MDd.lib (found version "3.0.3") -- The value of grpc cpp location is: C:/grpc/debug/bin/grpc_cpp_plugin.exe -- The generated files are located in: D:/cmake-test/tmp/proto/server.grpc.pb.h;D:/cmake-test/tmp/proto/server.grpc.pb.cc;D:/cmake-test/tmp/proto/serverPLUGIN;D:/cmake-test/tmp/proto/serverprotoc-gen-grpc=C:/data/tools/grpc/v1.15.1-2/win64/release/bin/grpc_cpp_plugin.exe -- Configuring done -- Generating done -- Build files have been written to: D:/cmake-test
过程无报错,但对应的.h和.cc文件未生成,以下是解决思路:
解决思路
1. 执行Build命令而非仅Configure
protobuf_generate是在构建阶段执行的,不是配置阶段。你目前只运行了CMake的配置命令,生成了VS工程文件,但没有触发实际的代码生成动作。需要接着执行build命令:
cmake --build D:\cmake-test --config Debug
2. 修复grpc插件参数错误
从输出的生成文件列表可以看到异常条目:serverPLUGIN和serverprotoc-gen-grpc=...,这是因为protobuf_generate的PLUGIN参数格式错误。当使用LANGUAGE grpc时,不需要手动指定protoc-gen-grpc=前缀,且你已经通过find_package(gRPC)找到了插件,CMake会自动关联正确的grpc_cpp_plugin。
修改第二个protobuf_generate调用:
protobuf_generate( TARGET test_proto OUT_VAR PROTO_GENERATED_GRPC_FILES # 单独用变量,避免覆盖 LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc IMPORT_DIRS ${PROTO_IMPORT_DIRS} PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
3. 避免变量覆盖
两次protobuf_generate都使用了同一个OUT_VAR PROTO_GENERATED_FILES,会导致第一次生成的普通proto文件路径被覆盖。建议分开使用变量,比如第一次用PROTO_GENERATED_CPP_FILES,第二次用PROTO_GENERATED_GRPC_FILES,方便后续调试和追踪。
4. 显式关联生成文件到目标(可选)
虽然TARGET参数会自动关联生成文件到库,但如果仍有问题,可以显式添加生成的文件到目标源文件中:
# 在两次protobuf_generate调用后添加 target_sources(test_proto PRIVATE ${PROTO_GENERATED_CPP_FILES} ${PROTO_GENERATED_GRPC_FILES})
5. 检查路径合法性
确保PROTO_BINARY_DIR对应的D:/cmake-test/tmp目录存在,CMake默认会自动创建,但如果有权限问题可能导致创建失败,可以手动提前创建该目录。
内容的提问来源于stack exchange,提问作者TonySalimi

