CMake和查找协议缓冲区

6mw9ycah  于 2022-11-11  发布在  其他
关注(0)|答案(1)|浏览(155)

我在一个项目中使用FindProtobuf模块,其中协议缓冲区文件位于子目录中。我希望该子目录中的CMakeLists.txt文件调用protoc来生成CPP文件。我的项目文件夹结构如下:

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来生成源文件,即使我明确地将生成的源文件绑定到可执行文件,从而创建了依赖关系。
当我将protofiles文件夹中的CMakeLists.txt的所有内容移动到根目录CMakeLists.txt中时,原文件就被编译了。
有人能帮我吗?我想把所有的协议缓冲区构建的东西放在protofiles文件夹中创建的CMakeLists.txt文件中。
我还注意到,在内部CMakeLists.txt中生成的变量(如PROTO_SRC)在打印时在内部文件中定义(即我获得了正确生成的CPP文件名),但当我在根文件中打印相同的变量时,它是空的。这几乎就像我需要“导出”(如果cmake中有方法的话)变量到根文件夹。
任何帮助都将不胜感激。
谢谢你,卡蒂克

46qrfjad

46qrfjad1#

我认为[FindProtobuf][0]并不适合这样使用。从它的文档中可以看到:
注意:PROTOBUF_GENERATE_CPP宏与add_executable()add_library()调用只能在同一目录中正常工作.
您尝试在子目录中使用PROTOBUF_GENERATE_CPP宏,尽管CMake文档并没有明确说明,但子目录引入了一个新的变量作用域。这意味着在subdir作用域中设置或修改的任何变量都不会影响父作用域中名称相似的变量。因此,PROTO_SRC在protofiles目录中可用,而在父作用域中不可用。
将变量向上传递到作用域的方法是使用[set(... PARENT_SCOPE)][1],因此在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][2]来实现这一点。自定义命令指定. pb.h和.pb.cc文件作为输出,并且只有在构建了依赖于这些文件的后续目标时才会调用自定义命令(即执行protoc)。
因此,在配置时(当CMake执行时)这些文件并不存在。如果你试图将它们作为源代码添加到add_libraryadd_executable命令中,这将是一个问题-- CMake需要被告知这些文件在它运行时并不存在,但它们 * 将 * 在构建时存在。
方法是将这些文件的[GENERATED][3]属性设置为TRUEPROTOBUF_GENERATE_CPP宏会自动执行此操作,但与变量一样,该属性不会填充到父作用域中。因此,在顶级CMakeLists.txt中,还需要添加:

set_source_files_properties(${PROTO_SRC} ${PROTO_HEADER} PROPERTIES
                            GENERATED TRUE)

正如您所看到的,在不同的目录中使用PROTOBUF_GENERATE_CPP和相应的add_library/add_executable命令有点脆弱。如果您 * 可以 * 避免这样做,您可能应该这样做。
[0]:https://cmake.org/cmake/help/latest/module/FindProtobuf.html“CMake“查找协议缓冲区”模块的最新文档”[1]:https://cmake.org/cmake/help/latest/command/set.html“CMake“set”命令的最新文档”[2]:https://cmake.org/cmake/help/latest/command/add_custom_command.html“CMake“添加自定义命令”的最新文档”[3]:https://cmake.org/cmake/help/latest/prop_sf/GENERATED.html“CMake“GENERATED”源文件属性的最新文档”

相关问题