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

如何避免CMake中Protobuf生成文件的不必要重编译?

解决Protobuf/GRPC文件重复生成问题

你当前使用add_custom_target的方式会导致每次构建都重新生成文件,原因是该目标没有关联输出文件,CMake无法判断是否需要重新执行。正确的做法是使用add_custom_command关联输入输出文件,让CMake通过文件时间戳自动判断是否需要重新生成。

具体实现步骤

  1. 定义所有生成的输出文件
    先遍历你的proto文件列表,明确每个文件会生成的C++输出文件(包括pb、grpc.pb以及mock文件):

    # 遍历proto文件,生成对应的输出文件路径
    foreach(proto_file ${those_proto_files})
      get_filename_component(proto_name ${proto_file} NAME_WE)
      list(APPEND proto_generated_files
        ${the_output_dir}/${proto_name}.pb.h
        ${the_output_dir}/${proto_name}.pb.cc
        ${the_output_dir}/${proto_name}.grpc.pb.h
        ${the_output_dir}/${proto_name}.grpc.pb.cc
        ${the_output_dir}/mock_${proto_name}.h
      )
    endforeach()
    
  2. 用add_custom_command生成文件
    使用add_custom_command关联输入(proto文件、protoc和grpc插件目标)和输出文件,CMake会自动检查文件更新情况:

    add_custom_command(
      OUTPUT ${proto_generated_files}
      COMMAND 
        $<TARGET_FILE:${proto_target}>
          --grpc_out=generate_mock_code=true:${the_output_dir}
          --cpp_out=${the_output_dir}
          --plugin=protoc-gen-grpc=$<TARGET_FILE:${grpc_cpp_plugin_target}>
          -I ${that_dir}
          ${those_proto_files}
      DEPENDS ${those_proto_files} ${proto_target} ${grpc_cpp_plugin_target}
      COMMENT "Generating C++ code from Protobuf/GRPC files"
    )
    
  3. 关联到依赖目标
    你可以直接让业务目标依赖生成的文件,或者创建一个聚合目标来管理:

    # 方式1:直接让业务目标依赖生成的文件
    add_dependencies(${that_dependent_target_name} ${proto_generated_files})
    
    # 方式2:创建聚合目标,方便手动触发生成
    add_custom_target(ThatThing ALL DEPENDS ${proto_generated_files})
    add_dependencies(${that_dependent_target_name} ThatThing)
    

为什么之前的方法无法生效

  • add_custom_target本身没有输出文件,CMake会默认每次构建都执行该目标的命令。
  • execute_process在CMake配置阶段运行,而$<TARGET_FILE>是生成阶段的表达式,配置阶段还未确定目标的最终路径,因此无法识别。
  • LOCATION属性已被CMake废弃,禁止直接读取目标路径,必须使用$<TARGET_FILE>这类生成表达式。
  • find_program用于在系统中查找已安装的程序,无法识别CMake目标或生成表达式。

注意事项

  • 确保所有生成的输出文件都被列在OUTPUT参数中,否则CMake可能漏检部分文件导致重复生成。
  • 如果proto文件存在导入关系,要确保-I参数包含所有依赖的proto文件目录。
  • 当proto文件修改、protoc或grpc_cpp_plugin更新时,CMake会自动重新生成文件,这是合理的更新逻辑,无需避免。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 10:02:33