使用FetchContent安装Protobuf时,如何解决protobuf_generate未识别问题?
问题描述
使用gRPC编写客户端/服务端程序时,通过FetchContent安装Protobuf后,执行CMake报错:Unknown CMake command "protobuf_generate"。但预先本地安装Protobuf时,protobuf_generate命令可正常使用。
代码示例:
cmake_minimum_required(VERSION 3.16) project(ProtoObjects) include(FetchContent) set(FETCHCONTENT_QUIET OFF) FetchContent_Declare( gRPC GIT_REPOSITORY https://github.com/grpc/grpc GIT_TAG v1.49.2 ) FetchContent_Declare( Protobuf GIT_REPOSITORY https://github.com/protocolbuffers/protobuf GIT_TAG v21.12 SOURCE_SUBDIR cmake ) FetchContent_MakeAvailable(gRPC Protobuf) add_library( proto-objects PUBLIC grpc++ ) target_include_directories(proto-objects PUBLIC "$<BUILD_INTERFACE:${PROTO_GENERATED_DIR}>") protobuf_generate( TARGET proto-objects IMPORT_DIRS ${PROTO_IMPORT_DIRS} PROTOC_OUT_DIR ${PROTO_GENERATED_DIR} ) protobuf_generate( TARGET proto-objects LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>" IMPORT_DIRS ${PROTO_IMPORT_DIRS} PROTOC_OUT_DIR "${PROTO_GENERATED_DIR}" )
错误信息:
Unknown CMake command "protobuf_generate".
解决方法
问题根源是:用FetchContent拉取的Protobuf,它的CMake模块不会自动加载到当前项目中,得手动引入对应的配置文件才能用protobuf_generate这类命令。
按以下步骤修改代码:
- 手动引入Protobuf的CMake模块
在FetchContent_MakeAvailable(gRPC Protobuf)这行之后,添加两行引入模块的代码:
include(${Protobuf_SOURCE_DIR}/cmake/protobuf-generate.cmake) include(${Protobuf_SOURCE_DIR}/cmake/protobuf-module.cmake)
这两个文件定义了protobuf_generate命令和相关的Protobuf CMake逻辑。
- 显式关联Protobuf目标
FetchContent拉取的Protobuf会生成官方的CMake目标,把它们加到你的库依赖里,避免依赖缺失:
修改add_library部分,补充Protobuf的目标:
add_library( proto-objects PUBLIC grpc++ Protobuf::libprotobuf Protobuf::protoc )
- 确认路径正确
你代码里的SOURCE_SUBDIR cmake是对的,Protobuf v21.12的CMake配置文件确实在cmake子目录下,后续换版本的话记得核对这个路径。
修改后的完整代码示例:
cmake_minimum_required(VERSION 3.16) project(ProtoObjects) include(FetchContent) set(FETCHCONTENT_QUIET OFF) FetchContent_Declare( gRPC GIT_REPOSITORY https://github.com/grpc/grpc GIT_TAG v1.49.2 ) FetchContent_Declare( Protobuf GIT_REPOSITORY https://github.com/protocolbuffers/protobuf GIT_TAG v21.12 SOURCE_SUBDIR cmake ) FetchContent_MakeAvailable(gRPC Protobuf) # 引入Protobuf的CMake模块 include(${Protobuf_SOURCE_DIR}/cmake/protobuf-generate.cmake) include(${Protobuf_SOURCE_DIR}/cmake/protobuf-module.cmake) add_library( proto-objects PUBLIC grpc++ Protobuf::libprotobuf Protobuf::protoc ) target_include_directories(proto-objects PUBLIC "$<BUILD_INTERFACE:${PROTO_GENERATED_DIR}>") protobuf_generate( TARGET proto-objects IMPORT_DIRS ${PROTO_IMPORT_DIRS} PROTOC_OUT_DIR ${PROTO_GENERATED_DIR} ) protobuf_generate( TARGET proto-objects LANGUAGE grpc GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>" IMPORT_DIRS ${PROTO_IMPORT_DIRS} PROTOC_OUT_DIR "${PROTO_GENERATED_DIR}" )
内容的提问来源于stack exchange,提问作者Tom McLean
相关产品推荐
相关产品推荐

