【问题标题】:Using cmake to create protobuf / grpc cc files使用cmake创建protobuf/grpc cc文件
【发布时间】:2015-12-25 17:29:39
【问题描述】:

如果我想在 cmake 中重新创建以下 protoc 命令:

protoc -I ../proto/ --cpp_out=. service.proto

我在 cmake 中使用以下几行:

file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles})

如果我想重新创建下面的 protoc 命令:

protoc -I ../proto/ --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` service.proto

在上述情况下我无法确定如何更改 cmake 文件,请帮助!

问题是我该如何解决:

--plugin=EXECUTABLE           Specifies a plugin executable to use.
                              Normally, protoc searches the PATH for
                              plugins, but you may specify additional
                              executables not in the path using this flag.
                              Additionally, EXECUTABLE may be of the form
                              NAME=PATH, in which case the given plugin name
                              is mapped to the given executable even if
                              the executable's own name differs.

我一直在阅读 PROTOBUF_GENERATE_CPP 文档,但没有找到答案!

【问题讨论】:

    标签: cmake protocol-buffers grpc


    【解决方案1】:

    对我来说,https://www.falkoaxmann.de/dev/2020/11/08/grpc-plugin-cmake-support.html 的博文会带来成功,因为它提供了一个完整的示例(感谢 @powerpete)。

    我将代码放在这里,因此它可以作为答案而不仅仅是作为评论:

    project(my-service VERSION 1.0 LANGUAGES CXX C)
    
    find_package(protobuf CONFIG REQUIRED)
    find_package(gRPC CONFIG REQUIRED)
    find_package(Threads)
    
    set(PROTO_FILES
        MyService.proto
    )
    
    # protobuf source files go into the lib just like any other CPP source file
    add_library(my-service ${PROTO_FILES})
    target_link_libraries(my-service
        PUBLIC
            protobuf::libprotobuf
            gRPC::grpc
            gRPC::grpc++
    )
    
    target_include_directories(my-service
        PUBLIC
            ${CMAKE_CURRENT_BINARY_DIR}
    )
    
    get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
    
    # compile the message types
    protobuf_generate(TARGET my-service LANGUAGE cpp)
    
    # compile the GRPC services
    protobuf_generate(
        TARGET
            my-service
        LANGUAGE
            grpc
        GENERATE_EXTENSIONS
            .grpc.pb.h
            .grpc.pb.cc
        PLUGIN
            "protoc-gen-grpc=${grpc_cpp_plugin_location}"
    )
    

    【讨论】:

      【解决方案2】:

      从 3.12 版本开始,protobuf_generate 支持 PLUGIN 参数

      https://github.com/protocolbuffers/protobuf/blob/v3.12.0/cmake/protobuf-config.cmake.in#L46

      所以您可以尝试以下方法: PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles} PLUGIN protoc-gen-grpc=${GRPC_CPP_PLUGIN_PATH})

      【讨论】:

      【解决方案3】:

      模块 findProtobuf.cmake 仅为常见的 protoc 调用定义函数包装器:PROTOBUF_GENERATE_CPP - 用于 --cpp_out 和 PROTOBUF_GENERATE_PYTHON - 用于 --py_out。但是您可以为所需的插件实现自己的函数包装器。下面的代码基于PROTOBUF_GENERATE_CPP 实现。

      find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin) # Get full path to plugin
      
      function(PROTOBUF_GENERATE_GRPC_CPP SRCS HDRS)
        if(NOT ARGN)
          message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files")
          return()
        endif()
      
        if(PROTOBUF_GENERATE_CPP_APPEND_PATH) # This variable is common for all types of output.
          # Create an include path for each file specified
          foreach(FIL ${ARGN})
            get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
            get_filename_component(ABS_PATH ${ABS_FIL} PATH)
            list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
            if(${_contains_already} EQUAL -1)
                list(APPEND _protobuf_include_path -I ${ABS_PATH})
            endif()
          endforeach()
        else()
          set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
        endif()
      
        if(DEFINED PROTOBUF_IMPORT_DIRS)
          foreach(DIR ${Protobuf_IMPORT_DIRS})
            get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
            list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
            if(${_contains_already} EQUAL -1)
                list(APPEND _protobuf_include_path -I ${ABS_PATH})
            endif()
          endforeach()
        endif()
      
        set(${SRCS})
        set(${HDRS})
        foreach(FIL ${ARGN})
          get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
          get_filename_component(FIL_WE ${FIL} NAME_WE)
      
          list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.cc")
          list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.h")
      
          add_custom_command(
            OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.cc"
                   "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.h"
            COMMAND  ${Protobuf_PROTOC_EXECUTABLE}
            ARGS --grpc_out=${CMAKE_CURRENT_BINARY_DIR}
                 --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
                 ${_protobuf_include_path} ${ABS_FIL}
            DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}
            COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}"
            VERBATIM)
        endforeach()
      
        set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
        set(${SRCS} ${${SRCS}} PARENT_SCOPE)
        set(${HDRS} ${${HDRS}} PARENT_SCOPE)
      endfunction()
      

      用法同PROTOBUF_GENERATE_CPP:

      file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
      PROTOBUF_GENERATE_GRPC_CPP(ProtoGRPCSources ProtoGRPCHeaders ${ProtoFiles})
      

      【讨论】:

      • 你还会推荐这个解决方案吗?什么是好的选择?谢谢。
      • 这只是一个执行所需操作的代码。您可以出于自己的目的修改(或重写)它。
      • 这段代码非常完美,但唯一的缺点是如果用户将PROTOBUF_GENERATE_CPP_APPEND_PATH 变量定义为关闭,脚本将无法正确填充SRCS 和HDRS 列表。
      • 要解决我上面评论的问题,我们应该将这些行:list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.cc") list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.grpc.pb.h") 替换为:get_filename_component(DIR_FIL ${FIL} DIRECTORY) list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${DIR_FIL}/${FIL_WE}.grpc.pb.cc") list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${DIR_FIL}/${FIL_WE}.grpc.pb.h")
      • 该代码仅用于生成 .grps.pb.cc 和 .grps.pb.hh 文件。 protoc 实用程序的对应参数由 add_custom_command() 调用的 ARGS 部分指定。
      猜你喜欢
      • 1970-01-01
      • 2022-11-29
      • 1970-01-01
      • 1970-01-01
      • 2021-04-21
      • 2018-06-28
      • 2017-02-15
      • 1970-01-01
      • 2020-05-29
      相关资源
      最近更新 更多