我有一些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
创建的。
我创建了一个函数(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
)。
问题:
msg_base
文件和.proto
等文件)相同的目录中使用不的文件路径? 我问这个是因为add_custom_command
的帮助确实引用了在同一目录中创建的目标,我想知道这是否与此相悖?
答案 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
. .