【问题标题】:How to compile .proto file using CMake to generate .grpc.pb.cc and .grpc.pb.h files?如何使用 CMake 编译 .proto 文件以生成 .grpc.pb.cc 和 .grpc.pb.h 文件?
【发布时间】:2020-06-09 23:40:24
【问题描述】:

我正在尝试使用 C++ 中的 gRPC 创建服务器和客户端设置。我在 CMake 中生成 .grpc.pb.h.grpc.pb.cc 文件时遇到问题。以下是我的项目设置。

gRPCStarter
  |__build
  |__proto
  |    |__ file.proto
  |    |__ CMakeLists.txt
  |__main.cpp
  |__CMakeLists.txt

以下是我当前的 CMakeLists.txt 文件

proto 目录内:

INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER file.proto)
ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC})

source 目录内(在this advice 之后):

cmake_minimum_required(VERSION 3.16)
project(gRPCStarter)

set(CMAKE_CXX_STANDARD 14)

include(FetchContent)
FetchContent_Declare(
        gRPC
        GIT_REPOSITORY https://github.com/grpc/grpc
        GIT_TAG        v1.27.1
)
FetchContent_MakeAvailable(gRPC)

add_subdirectory(proto)

include_directories($(CMAKE_CURRENT_BINARY_DIR))

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()

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

add_executable(main main.cpp)
target_link_libraries(main proto ${PROTOBUF_LIBRARY} grpc++)

当我执行以下操作时,我没有得到任何 .gpc.pb.h.grpc.pb.cc 文件:

cd build
cmake .. && make -j4

这是我的CMakeOutput.log

【问题讨论】:

  • make 运行期间是否出现任何错误?在此运行期间,应生成PROTO_SRCPROTO_HEADER 变量中列出的文件。这些变量的内容是什么? (您可以通过message() 命令打印变量的内容)。在make 期间是否打印过消息“正在运行 gRPC C++ 协议缓冲区编译器”?如果它被打印,那么proto 实际运行。使用make VERBOSE=1,您可能会看到在构建期间执行的确切命令行。
  • 您的 CMake 项目是否甚至找到 Protobuf?您还可以提供 CMake 输出日志吗?另外,您似乎在致电PROTOBUF_GENERATE_GRPC_CPP 两次?一次在 proto CMake 文件中,又一次在顶级 CMake 文件中,这是为什么呢?
  • @Tsyvarev 我刚刚验证过。 "Running gRPC C++ protocol buffer compiler" 消息在 make 期间永远不会被打印
  • 我尝试打印一条自定义消息以查看在 make 过程中是否曾调用过 PROTOBUF_GENERATE_GRPC_CPP。以下代码行在make 期间不打印任何内容:function(PROTOBUF_GENERATE_GRPC_CPP SRCS HDRS) message("Command execution started") 看起来这个函数从未被调用过。因此 grpc 文件永远无法生成。
  • 您调用PROTOBUF_GENERATE_GRPC_CPP,但从不使用它的结果(ProtoGRPCSourcesProtoGRPCHeaders 变量中列出的文件)。由于未使用这些文件,因此 CMake 不会生成它们。 (与 PROTOBUF_GENERATE_CPP 调用相比,它创建在 PROTO_SRCPROTO_HEADER 变量中列出的文件。您在 add_executable 调用中使用这些文件,因此它们是在构建可执行文件之前生成的)。

标签: c++ cmake compilation protocol-buffers grpc


【解决方案1】:

我通过关注this CMake architecture解决了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    相关资源
    最近更新 更多