【问题标题】:CMake with protobuf file in subdirectoryCMake 与子目录中的 protobuf 文件
【发布时间】:2017-05-16 19:21:02
【问题描述】:

我已经看到了很多类似的问题和答案,但直到现在,让它发挥作用似乎并不那么明显。我对 CMake 还是很陌生,到目前为止一切都很简单,除了与协议缓冲区的集成。

我有一个带有子目录的项目,其中每个子目录都有自己的 CMakeLists.txt

其中一个子目录包含一个 .proto 文件。如果执行 PROTOBUF_GENERATE_CPP 宏,它会生成源文件和头文件。这个宏是从包含 .proto 文件的子目录中的 CMakeLists.txt 调用的。

但似乎没有调用 make 文件,因为没有将源添加到目标中。我无法将源添加到目标,因为文件不存在,它们在生成后存在,所以这会导致 CMake 运行时出错。

将文件属性设置为生成似乎也无济于事。一般来说,在构建过程开始之前,应该已经运行宏来生成源文件。

如何做到这一点,任何工作示例?

例子:

./src/externals/protodef(来自其他存储库,仅包含 .proto 文件)
./src/generated(应该是protoc生成的c和头文件)

CMakeLists-1(项目根目录)

cmake_minimum_required (VERSION 2.6)
PROJECT (prototest)

ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src/externals/protodef")
ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src")

SET_SOURCE_FILES_PROPERTIES(${PROTO_SOURCES} ${PROTO_HEADERS} PROPERTIES GENERATED TRUE)

ADD_EXECUTABLE(prototest ${PROTO_SOURCES} ${SOURCE} )
TARGET_LINK_LIBRARIES(prototest ${EXTERNAL_LIBS} )

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

CMakeLists-2 (src)

SET(SOURCE ${SOURCE}
  ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp

  PARENT_SCOPE
)

CMakeLists-3 (src/externals/protodef)

SET(PROTOBUF_PATH "D:/protobuf-3.0.0/" )
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${PROTOBUF_PATH}")

# Changing PROTO_SRCS and PROTO_HDRS does not work for setting the location 
# of the generated files.
# Those variable are ignored by CMake for compiling the proto files.
# Using a dedicated CMakeLists.txt and settng CURRENT_BINARY dir is a 
# workaround to get them where we want.
SET(GENERATED_DIR ${PROJECT_SOURCE_DIR}/src/generated )
SET(CMAKE_CURRENT_BINARY_DIR ${GENERATED_DIR} )


INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)

PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS${CMAKE_CURRENT_SOURCE_DIR}/test1.proto)

SET( EXTERNAL_LIBS ${PROTOBUF_PATH}/lib/libprotobuf.a PARENT_SCOPE)

# Propagate sources to the parant project
SET(PROTO_SOURCES ${PROTO_SRCS}
PARENT_SCOPE
)

SET(PROTO_HEADERS ${PROTO_HDRS}
PARENT_SCOPE
)

【问题讨论】:

  • 您必须使用 GENERATED 属性标记生成的 .h 和 .cpp 文件,以便 cmake 在制作它们时知道它们会存在。
  • @Richard 我尝试设置 GENERATED 属性。似乎它唯一做的就是将“要生成”的文件的文件名填充到传递给宏的变量中。但在这种情况下,文件仍然不存在,并且将变量添加到项目源文件中会导致 cmake 错误,因为它包含不存在文件的名称。

标签: c++ cmake protocol-buffers


【解决方案1】:

首先生成 protobuf 文件,然后将它们添加到 CMake 目标中。

CMakeLists (src):

# Generate h/cpp proto files (./src/externals/protodef) into ./src/generated folder
PROTOBUF_GENERATE_CPP(...)

# Process subdir
ADD_SUBDIRECTORY(generated)

看来PROTOBUF_GENERATE_CPP只能在同一个子目录下使用。一种可能的解决方法是直接调用 protoc:

 FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/externals/protodef PROTOMODEL_PATH)
 FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/generated PROTOBINDING_PATH)

 FILE(GLOB DATAMODEL_PROTOS "${CMAKE_CURRENT_SOURCE_DIR}/externals/protodef/*.proto")

 FOREACH(proto ${DATAMODEL_PROTOS})
    FILE(TO_NATIVE_PATH ${proto} proto_native)
    EXECUTE_PROCESS(COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --proto_path=${PROTOMODEL_PATH} --cpp_out=${PROTOBINDING_PATH} ${proto_native}
    RESULT_VARIABLE rv)
    # Optional, but that can show the user if something have gone wrong with the proto generation 
    IF(${rv})
         MESSAGE("Generation of data model returned ${rv} for proto ${proto_native}")
    ENDIF()
 ENDFOREACH(proto)

CMakeLists(源/生成):

## List generated sources files
FILE(GLOB HDRS "*.h")
FILE(GLOB SRCS "*.cc")

ADD_LIBRARY(protoBinding ${HDRS} ${SRCS})
# ${PROTOBUF_LIBRARIES} should be defined by FIND_PACKAGE(Protobuf REQUIRED)
TARGET_LINK_LIBRARIES(protoBinding ${PROTOBUF_LIBRARIES})

这样 CMake 将首先生成头文件/源文件,然后才将生成的文件添加到 CMake 目标中。

然后您可以使用protoBinding 目标将生成的文件链接到其他目标(例如在src 的CMakeLists.txt 的末尾):

ADD_LIBRARY(myModel ${myFiles})
TARGET_LINK_LIBRARIES(myModel protoBinding)

【讨论】:

  • 我使用了第二个选项,它提供了更多的控制。它就像一个魅力。就我而言,PROTOBUF_LIBRARIES 指向 libprotobuf.dll.a 我想按照 Google 的建议静态链接 libprotobuf。目前我手动设置lib,可能有更清洁的方法。
  • 应该有办法在PROTOBUF_GENERATE_CPP中添加多个PROTO_PATH。目前,EXECUTE_COMMAND 是一个不错的解决方法。我不喜欢做 GLOB 的想法,所以我实现了一个循环并将所有 .h 和 .cc 文件存储在一个变量中。还是谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
  • 1970-01-01
  • 2011-12-20
  • 1970-01-01
  • 2016-03-30
  • 1970-01-01
相关资源
最近更新 更多