CMake 目标依赖项以编译 protobuf 文件



我想用一些protobuf定义构建一个 c++ 静态库 cmake/make .
我做了一个自定义COMMAND来编译protobuf c++,并将其设置为静态库的PRE_BUILD依赖项。

project(mylib)
set(PROTO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proto_definitions")
file(GLOB PROTO_FILES "${PROTO_PATH}/*.proto")
foreach(PROTO_FILE in ${PROTO_FILES})
    string(REGEX REPLACE "[.]proto$" ".pb.cc" OUTPUT_SOURCE ${PROTO_FILE})
    list(APPEND OUTPUT_SOURCES ${OUTPUT_SOURCE}) 
endforeach()
add_custom_command(TARGET ${PROJECT_NAME}
                   PRE_BUILD
                   COMMAND protoc --cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/compiled_proto ${PROTO_FILES}
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                   COMMENT "some comment")
add_library(${PROJECT_NAME} STATIC ${OUTPUT_SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

运行cmake时出现以下错误:
CMake 错误:无法确定目标"mylib"的链接语言

不管这个错误如何,都会生成生成文件,但是当我制作mylib时,它不会触发任何原型编译

CMake 更原生的方法是添加具有OUTPUT签名的自定义命令以生成.cc文件,然后通常将它们用作库的源。这样,他们就会知道它们是什么以及如何生产它们:

project(mylib)
set(PROTO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proto_definitions")
file(GLOB PROTO_FILES "${PROTO_PATH}/*.proto")
foreach(PROTO_FILE in ${PROTO_FILES})
    string(REGEX REPLACE "[.]proto$" ".pb.cc" OUTPUT_SOURCE ${PROTO_FILE})
    list(APPEND OUTPUT_SOURCES ${OUTPUT_SOURCE}) 
endforeach()
add_custom_command(OUTPUT ${OUTPUT_SOURCES}
                   COMMAND protoc --cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/compiled_proto ${PROTO_FILES}
                   DEPENDS ${PROTO_FILES}
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                   COMMENT "some comment")
add_library(${PROJECT_NAME} STATIC ${OUTPUT_SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

这样,将有一个命令读取所有.proto文件并生成所有.cc文件 - 这意味着如果任何.proto文件发生更改,将重新生成所有.cc文件。我不熟悉原始缓冲器,所以我不知道这是否理智。如果它们是独立的,则最好为每个输出文件引入一个add_custom_command

此外,给定要传递给 protocc 的参数,您可能必须修改 OUTPUT_SOURCES 中的路径以正确指向生成的文件。

另请注意,CMake 附带了一个 FindProtobuf 模块,该模块定义了protobuf_generate_cpp()命令,因此您可能希望使用它而不是手动编码 Protobuf 支持。

对上述答案的评论:cmake foreach中没有in,这花了我一些时间来解决这个问题。

在研究了他的回答(非常感谢!(之后,我总结了一个适合我的方法,它具有以下特点:

  1. 原型目录和输出目录可以不同
  2. 生成grpc_output
  3. 为每个原型创建一个custom_command

我的项目目标是:

  • HWPB/(超级项目的库(
    • .cpp/
      • hwpb/(store *.pb.cc, *.pb.h(
      • CMakeList.txt
    • 原型
    • /(存储原型(
    • go/(和其他语言,这里未提及(

这是我的CMakeListx.txt:

set(PROTO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../proto")
set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/hwpb")
file(GLOB PROTO_FILES "${PROTO_DIR}/*.proto")
foreach(PROTO_FILE ${PROTO_FILES})
    get_filename_component (FILENAME ${PROTO_FILE} NAME_WLE)
    set(PROTO_SRC "${OUTPUT_DIR}/${FILENAME}.pb.cc")
    set(PROTO_HDR "${OUTPUT_DIR}/${FILENAME}.pb.h")
    set(GRPC_SRC "${OUTPUT_DIR}/${FILENAME}.grpc.pb.cc")
    set(GRPC_HDR "${OUTPUT_DIR}/${FILENAME}.grpc.pb.h")
    add_custom_command(
        OUTPUT "${PROTO_SRC}" "${PROTO_HDR}" "${GRPC_SRC}" "${GRPC_HDR}"
        COMMAND ${_PROTOBUF_PROTOC}
        ARGS --plugin=protoc-gen-grpc=${_GRPC_CPP_PLUGIN_EXECUTABLE}
            --cpp_out="${OUTPUT_DIR}" --grpc_out="${OUTPUT_DIR}"
            -I"${PROTO_DIR}" "${PROTO_FILE}"
        DEPENDS ${PROTO_FILE}
    )
    list(APPEND OUTPUT_SOURCES ${PROTO_SRC} ${GRPC_HDR})
endforeach()
add_library(hwpb ${OUTPUT_SOURCES})
target_link_libraries(hwpb ${_GRPC_GRPCPP_UNSECURE} ${_PROTOBUF_LIBPROTOBUF})
target_include_directories(hwpb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

最新更新