cammy/CMakeLists.txt # Root CMakeLists.txt cammy/protofiles/test.proto # protofile cammy/protofiles/CMakeLists.txt
我在protobuf文件夹中的CMakeLists.txt文件中包含include(FindProtobuf),find_package调用和对PROTOBUF_GENERATE_CPP的调用.
可执行构建步骤在根CMakeLists.txt文件中,我添加生成的文件
到该文件中的目标可执行文件
即.
add_executable( ${EXEC} ${SRCS} ${PROTO_SRC} ${PROTO_HEADER} ) target_link_libraries( ${EXEC} ${PROTOBUF_LIBRARIES} )
都在根CMakeLists.txt中定义
当我运行cmake时,它不会运行protoc来生成Source文件,即使我将生成的资源与可执行文件相关联,从而创建一个依赖关系.
当我将protofiles文件夹中的CMakeLists.txt的所有内容移动到根CMakeLists.txt根目录下时,会编译原始文件.
谁能帮我这个?我想要所有的协议缓冲区构建的东西去在protofiles文件夹中创建的CMakeLists.txt文件.
我也注意到内部CMakeLists.txt(如PROTO_SRC)中生成的变量在打印时在内部文件中定义(即我得到正确生成的CPP文件名),但是当我在根文件中打印相同的变量时,它是空的.它几乎就像我需要“导出”(如果有一个方法在cmake)变量到根文件夹.
任何帮助将不胜感激.
谢谢
卡尔蒂克
FindProtobuf
不是真的意思是用这种方式.从其文档:
NOTE: The
PROTOBUF_GENERATE_CPP
macro &add_executable()
oradd_library()
calls only work properly within the same directory.
您尝试在子目录中使用PROTOBUF_GENERATE_CPP宏,虽然CMake文档并没有真正清楚,但是子目录为变量引入了一个新的范围.这意味着在subdir范围内设置或修改的任何变量不会影响父作用域中类似命名的变量.因此,PROTO_SRC在原始目录中可用的原因,但不在父级中.
将变量传递到范围的方法是使用set(... PARENT_SCOPE)
,因此在protofiles / CMakeLists.txt中可以执行以下操作:
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER test.proto) set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE) set(PROTOBUF_LIBRARIES ${PROTOBUF_LIBRARIES} PARENT_SCOPE) set(PROTO_SRC ${PROTO_SRC} PARENT_SCOPE) set(PROTO_HEADER ${PROTO_HEADER} PARENT_SCOPE)
然而,这仍然不能让我们一路走来!
CMake实际上并没有调用protoc编译器来生成.pb.h和.pb.cc文件 – 它使用add_custom_command
来执行此操作.自定义命令将.pb.h和.pb.cc文件指定为输出,并且仅在构建依赖于这些文件的后续目标时才调用自定义命令(即,执行protoc).
所以在配置时(CMake执行时)这些文件不存在.如果您尝试将它们添加为add_library或add_executable命令的源,则这是一个问题 – 需要告知CMake运行时这些文件不存在,但是它们将在构建时存在.
这样做的方法是将这些文件的GENERATED
属性设置为TRUE. PROTOBUF_GENERATE_CPP宏自动执行,但与变量一样,属性未填充到父作用域中.所以在你的顶级CMakeLists.txt中,你还需要添加:
set_source_files_properties(${PROTO_SRC} ${PROTO_HEADER} PROPERTIES GENERATED TRUE)
正如你所看到的,使用PROTOBUF_GENERATE_CPP在不同的dir到相应的add_library / add_executable命令有点脆弱.如果你可以避免这样做,你可能应该.