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

如何通过CMake从.proto文件生成Python gRPC Protobuf文件?

问题描述

我用Python开发gRPC服务端,C++实现客户端,需要通过CMake从.proto文件生成Python Protobuf相关文件。手动执行以下命令能正常生成文件:

python3 -m grpc_tools.protoc -I ../protos --python_out=. --pyi_out=. --grpc_python_out=. ../helloworld.proto

但整合到CMakeLists.txt后,始终无法生成目标文件。原CMake配置如下:

cmake_minimum_required(VERSION 3.15)

# Project
project(myproj)

# Protobuf
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${protobuf_VERSION}")

# Protobuf-compiler
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)

 # gRPC
 find_package(gRPC CONFIG REQUIRED)
 message(STATUS "Using gRPC ${gRPC_VERSION}")
 set(_GRPC_GRPCPP gRPC::grpc++)
 set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
 set(_GRPC_PY_TOOL $<TARGET_FILE:gRPC::grpc_tools::protoc>)

 # Proto file
get_filename_component(hw_proto "helloworld.proto" ABSOLUTE)
get_filename_component(hw_proto_path "${hw_proto}" PATH)

# Generated sources

set(hw_grpc_src_py "${CMAKE_CURRENT_BINARY_DIR}/helloworld_pb2_grpc.py")
set(hw_proto_src_py "${CMAKE_CURRENT_BINARY_DIR}/helloworld_pb2.py")
set(hw_proto_src_pyi "${CMAKE_CURRENT_BINARY_DIR}/helloworld_pb2.pyi")


find_package(PythonInterp REQUIRED)
find_package(Python3 REQUIRED)
add_custom_command(
  OUTPUT "${hw_grpc_src_py}" "${hw_proto_src_py}" "${hw_proto_src_pyi}"
  COMMAND python3 
  ARGS -m  "${_GRPC_PY_TOOL}"
   -I "${hw_proto_path}"
  --python_out "${CMAKE_CURRENT_BINARY_DIR}"
  --pyi_out "${CMAKE_CURRENT_BINARY_DIR}"
  --grpc_python_out "${CMAKE_CURRENT_BINARY_DIR}"
  "${hw_proto}"
  DEPENDS "${hw_proto}")

尝试添加以下自定义目标也无效:

add_custom_target(run ALL
DEPENDS "${hw_proto}")

修改add_custom_command的DEPENDS为生成的Python文件后,问题依然存在。

问题分析与修复

你的CMake配置存在以下几个关键问题,逐一修复即可:

1. 错误定义Python gRPC工具调用方式

手动命令是通过python3 -m grpc_tools.protoc调用Python模块,而非直接调用protoc二进制文件。原配置中set(_GRPC_PY_TOOL $<TARGET_FILE:gRPC::grpc_tools::protoc>)完全错误,不需要找这个目标,直接使用grpc_tools.protoc作为模块名即可。

2. add_custom_command参数传递错误

原配置中ARGS -m "${_GRPC_PY_TOOL}"会把protoc二进制路径当作模块名传入,不符合Python模块调用语法,应改为-m grpc_tools.protoc。

3. 自定义目标未正确依赖生成文件

原自定义目标run依赖原始.proto文件,而非add_custom_command生成的Python输出文件,导致CMake无法触发生成命令。需要让自定义目标依赖add_custom_command的OUTPUT列表。

修复后的完整CMake配置

cmake_minimum_required(VERSION 3.15)

# Project
project(myproj)

# Protobuf
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${protobuf_VERSION}")

# gRPC
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
set(_GRPC_GRPCPP gRPC::grpc++)
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)

# Proto file
get_filename_component(hw_proto "helloworld.proto" ABSOLUTE)
get_filename_component(hw_proto_path "${hw_proto}" PATH)

# Generated sources
set(hw_grpc_src_py "${CMAKE_CURRENT_BINARY_DIR}/helloworld_pb2_grpc.py")
set(hw_proto_src_py "${CMAKE_CURRENT_BINARY_DIR}/helloworld_pb2.py")
set(hw_proto_src_pyi "${CMAKE_CURRENT_BINARY_DIR}/helloworld_pb2.pyi")

find_package(Python3 REQUIRED COMPONENTS Interpreter)

add_custom_command(
  OUTPUT "${hw_grpc_src_py}" "${hw_proto_src_py}" "${hw_proto_src_pyi}"
  COMMAND ${Python3_EXECUTABLE}
  ARGS -m grpc_tools.protoc
       -I "${hw_proto_path}"
       --python_out="${CMAKE_CURRENT_BINARY_DIR}"
       --pyi_out="${CMAKE_CURRENT_BINARY_DIR}"
       --grpc_python_out="${CMAKE_CURRENT_BINARY_DIR}"
       "${hw_proto}"
  DEPENDS "${hw_proto}"
  COMMENT "Generating Python gRPC/Protobuf files from ${hw_proto}"
)

# 自定义目标依赖生成的文件,ALL关键字会让CMake默认构建这个目标
add_custom_target(gen_python_protos ALL
  DEPENDS "${hw_grpc_src_py}" "${hw_proto_src_py}" "${hw_proto_src_pyi}"
)

额外说明

  • 使用${Python3_EXECUTABLE}替代硬编码的python3,增强跨平台兼容性。
  • 在--python_out等参数后添加等号,和手动命令格式保持一致(CMake也支持空格,但等号更贴近原生protoc语法)。
  • 添加COMMENT参数,构建时可看到生成文件的提示信息,方便调试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:25:21