【问题标题】:CMake how to collect auto generated source and header filesCMake如何收集自动生成的源文件和头文件
【发布时间】:2020-10-02 09:32:23
【问题描述】:

首先介绍一下上下文,我试图解耦一个包含 protobuf 定义以及使用 proto 的实体的 repo。我想创建一个仅包含 protobuf 定义和脚本的存储库,这些定义和脚本以不同语言导出生成的类,以供使用它们的其他项目导入。

在 c++ 中生成 protobuf 类实际上非常简单(几行 python 脚本),但之后就变得棘手了。您最终会得到一组杂乱无章的源文件。我想使用 CMake 收集所有文件并生成库。文件结构应如下所示:

/root
    /proto-package-1
        foo.pb.h
        foo.pb.cc
    /proto-package-2
        /proto-package-3
            bar.pb.h
            bar.pb.cc
        bazz.pb.h
        bazz.pb.cc

我在 CMake 中有点菜鸟,但我读过在 CMakeLists.txt 文件中明确列出所有源文件是一种很好的做法。但我想让这个 c++ 库的生成完全自动化。这会是违反此规则的充分理由吗?哪些 CMake 命令可以帮助我?

cmake_minimum_required (VERSION 3.5)

project ("CMakeProject1")
set(TARGET_NAME CMakeProject1)

# Include sub-projects.
include_directories(${CMAKE_SOURCE_DIR})

add_library(${TARGET_NAME} STATIC 
${CMAKE_SOURCE_DIR}/root/proto-package-1/foo.pb.h
${CMAKE_SOURCE_DIR}/root/proto-package-1/foo.pb.cc
//This is not going to cut it. Cannot add a proto and auto-generate.
)

【问题讨论】:

  • 您知道protobuf_generate_cpp 函数,它使用protobuf 生成文件,不是吗?这个函数用生成的文件的路径分配输出变量,所以你只需要在add_library调用中使用这个变量。
  • 问题:CMake 模块是否喜欢、维护和使用?它是否编译 .proto 文件并将其分配给目标?如果是这样,我该如何指定要使用的 protoc 版本?
  • 最后一次更新是十天前。有一种(遗憾的是未记录)模式,它检查目标的源并添加规则以将 protoc 生成的文件添加到目标。至于 protoc 版本,您可以尝试将所需版本传递给 find_package 命令。
  • 我会尝试让它工作(这在 Windows 中是一个痛苦)。看起来它确实是为了将原型定义包含在同一个 repo 中,与我正在尝试的相反

标签: c++ cmake protocol-buffers


【解决方案1】:

您也可以在cmake中生成它们并创建生成文件的列表

# Get list of .proto files
file(GLOB_RECURSE proto_files RELATIVE ${PROJECT_SOURCE_DIR} "*.proto")

## Get Protobuf include dirs
get_target_property(protobuf_dirs protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
foreach(dir IN LISTS protobuf_dirs)
  if ("${dir}" MATCHES "BUILD_INTERFACE")
    message(STATUS "Adding proto path: ${dir}")
    list(APPEND PROTO_DIRS "--proto_path=${dir}")
  endif()
endforeach()

# Generate Protobuf cpp sources
set(PROTO_HDRS)
set(PROTO_SRCS)
foreach(PROTO_FILE IN LISTS proto_files)
  #message(STATUS "protoc proto(cc): ${PROTO_FILE}")
  get_filename_component(PROTO_DIR ${PROTO_FILE} DIRECTORY)
  get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)
  set(PROTO_HDR ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.h)
  set(PROTO_SRC ${PROJECT_BINARY_DIR}/${PROTO_DIR}/${PROTO_NAME}.pb.cc)
  #message(STATUS "protoc hdr: ${PROTO_HDR}")
  #message(STATUS "protoc src: ${PROTO_SRC}")
  add_custom_command(
    OUTPUT ${PROTO_SRC} ${PROTO_HDR}
    COMMAND protobuf::protoc
    "--proto_path=${PROJECT_SOURCE_DIR}"
    ${PROTO_DIRS}
    "--cpp_out=${PROJECT_BINARY_DIR}"
    ${PROTO_FILE}
    DEPENDS ${PROTO_FILE} protobuf::protoc
    COMMENT "Generate C++ protocol buffer for ${PROTO_FILE}"
    VERBATIM)
  list(APPEND PROTO_HDRS ${PROTO_HDR})
  list(APPEND PROTO_SRCS ${PROTO_SRC})
endforeach()

# [optional] Create a library of all generated C++ files
add_library(${PROJECT_NAME}_proto ${PROTO_SRCS} ${PROTO_HDRS})
set_target_properties(${PROJECT_NAME}_proto PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD 11)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_STANDARD_REQUIRED ON)
set_target_properties(${PROJECT_NAME}_proto PROPERTIES CXX_EXTENSIONS OFF)
target_include_directories(${PROJECT_NAME}_proto PRIVATE
  ${PROJECT_SOURCE_DIR}
  ${PROJECT_BINARY_DIR}
  $<TARGET_PROPERTY:protobuf::libprotobuf,INTERFACE_INCLUDE_DIRECTORIES>
  )
target_link_libraries(${PROJECT_NAME}_proto PRIVATE protobuf::libprotobuf)

参考:https://github.com/google/or-tools/blob/a0a56698ba8fd07b7f84aee4fc45d891a8cd9828/cmake/cpp.cmake#L234-L294

【讨论】:

    【解决方案2】:

    我相信您可以使用internal function of the FindProtobuf package 来生成包含 protobuf 实现的静态库:

    find_package(Protobuf 3.12 REQUIRED)
    add_library(protopackage1 STATIC proto-package-1/foo.proto)
    protobuf_generate(LANGUAGE cpp TARGET protopackage1)
    

    您可以将额外的参数传递给protobuf_generate,但您必须弄清楚 protobuf_generate_cpp 是如何传递它们的。

    【讨论】:

    • 这可能是我正在寻找的功能。超级方便,他们将它包含在如何使用它的清晰文档中。
    • 您可以随时提出问题,甚至提交文档补丁;也许他们根本还没有考虑过您的用例。正如他们所说:“欢迎使用补丁”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 2020-06-23
    • 2017-07-20
    • 1970-01-01
    • 2010-11-27
    相关资源
    最近更新 更多