传递的add_custom_command依赖项未被转移

时间:2017-11-28 16:38:59

标签: c++ cmake

我有一些protobuf文件位于我的cmake项目之外的目录中(它们位于 <{1>}旁边的根目录中,我们的主CMakeLists.txt文件是)。

${CMAKE_SOURCE_DIR}

我的目标是创建一个custom_command,它将生成root/ +--- src/ | +--- CMakeLists.txt # main CMakeLists | +--- messages/ | +--- CMakeLists.txt # protocol generation CMakeLists | +--- base/ | +--- header.pb.cc | +--- header.pb.h +--- protocols/ +--- base/ | +--- header.proto # protocol definitions . . .pb.cc个文件,并将它们链接到一个库中,以便在我的项目中使用。

因此,在上面的示例中,.pb.h是从root/src/messages/base/header.pb.cc创建的。

Protobuf生成:

我创建了一个函数(root/protocols/base/header.proto),它遍历一个protobuf protoc源文件列表,并调用add_custom_command来调用每个文件上的protobuf编译器。

.proto

请注意,我已指定function(protoc SRCS_OUT HDRS_OUT) set(options) set(values CPP_OUT CWD) set(lists PROTO) cmake_parse_arguments(ARG "${options}" "${values}" "${lists}" "${ARGN}") set(GENERATED_SRCS) set(GENERATED_HDRS) foreach(FILE ${ARG_PROTO}) # find the absolute path to the .proto file get_filename_component(ABS_FILE ${FILE} ABSOLUTE) # replace source-dir with dest-dir and generate the path where the # .pb.cc and .pb.h files will be created string(REPLACE ${ARG_CWD} ${ARG_CPP_OUT} PROTO_DEST ${ABS_FILE}) get_filename_component(FILE_WE ${PROTO_DEST} NAME_WE) get_filename_component(DEST_DIR ${PROTO_DEST} DIRECTORY) set(GENERATED_SRC "${DEST_DIR}/${FILE_WE}.pb.cc") set(GENERATED_HDR "${DEST_DIR}/${FILE_WE}.pb.h") # run the protoc compiler on the .proto file, specifying the generated # .pb.cc and .pb.h files as OUTPUT, and the .proto file as the # MAIN_DEPENDENCY add_custom_command( OUTPUT ${GENERATED_SRC} ${GENERATED_HDR} COMMAND protoc ARGS --cpp_out ${ARG_CPP_OUT} ${ABS_FILE} WORKING_DIRECTORY ${ARG_CWD} MAIN_DEPENDENCY ${ABS_FILE} COMMENT "Running C++ protocol buffer compiler on ${FILE}" VERBATIM ) set_source_files_properties(${GENERATED_SRC} ${GENERATED_HDR} PROPERTIES GENERATED TRUE) list(APPEND GENERATED_SRCS ${GENERATED_SRC}) list(APPEND GENERATED_HDRS ${GENERATED_HDR}) endforeach() set(${SRCS_OUT} ${GENERATED_SRCS} PARENT_SCOPE) set(${HDRS_OUT} ${GENERATED_HDRS} PARENT_SCOPE) endfunction() .pb.cc文件与.pb.h文件之间的依赖关系:

  • .proto:我指定了生成的OUTPUT.pb.cc文件的完整路径
  • .pb.h:我指定MAIN_DEPENDENCY文件的完整路径

然后我使用上面的.proto函数创建一个由生成的protoc文件组成的库:

.pb.cc

root/src/messages/CMakeLists.txt

因此,get_filename_component(PROTOCOLS_DIR "${CMAKE_SOURCE_DIR}/../protocols" ABSOLUTE) protoc( PROTO_SRCS PROTO_HDRS PROTO ${PROTOCOLS_DIR}/base/header.proto CWD ${PROTOCOLS_DIR} CPP_OUT ${CMAKE_CURRENT_SOURCE_DIR} ) add_library( msg_base STATIC ${PROTO_SRCS} ${PROTO_HDRS} ) 的命令将具有protoc参数

  • PROTO

/home/steve/root/protocols/messages/base/header.proto将作为其来源

  • msg_base
  • /home/steve/root/src/messages/base/header.pb.cc

我的期望是,现在任何链接/home/steve/root/src/messages/base/header.pb.h 传递的目标都依赖于msg_base个文件

.proto

例如:

target -> msg_base -> header.pb.cc -> header.proto

问题:

有时add_executable(foo ${FOO_SRCS}) target_link_libraries(foo msg_base) # transitive dependency on header.proto 会过时,但header.proto会链接旧版foo

msg_base在链接msg_base之前使用新的header.pb.cc文件重建(过期foo)。

问题:

  • 我是否允许在与CMakeLists.txt(msg_base文件和.proto等文件)相同的目录中使用的文件路径?

我问这个是因为add_custom_command的帮助确实引用了在同一目录中创建的目标,我想知道这是否与此相悖?

  • 另请注意,我们正在使用并行构建

1 个答案:

答案 0 :(得分:1)

研究让我看到了一篇名为“How can I add a dependency to a source file which is generated in a subdirectory?

的cmake wiki的帖子

事实证明,cmake目前不知道如何将生成的文件作为依赖关系链接到不同目录中的目标

这听起来非常像是这个问题的根本原因。

这是一个开放的bug report / feature request,但截至撰写时,它仍然是开放的。

“修复”是将包含生成的protobuf文件的每个库的创建移动到生成这些文件的子目录中。

即,将msg_base的创建从root/src/messages/CMakeLists.txt移至root/src/messages/base/CMakeLists.txt

生成的树将如下所示:

root/
+--- src/
|    +--- CMakeLists.txt            # main CMakeLists
|    +--- messages/
|         +--- base/
|              +--- CMakeLists.txt  # protocol generation CMakeLists
|              +--- header.pb.cc
|              +--- header.pb.h
+--- protocols/
     +--- base/
     |    +--- header.proto         # protocol definitions
     .    .