当前位置 : 主页 > 大数据 > 区块链 >

CMake和FindProtobuf

来源:互联网 收集:自由互联 发布时间:2021-06-22
我正在项目中使用FindProtobuf模块,其中协议缓冲区文件位于子目录中.我想要该子目录中的CMakeLists.txt文件调用protoc来生成CPP文件.我的项目文件夹结构是这样的: cammy/CMakeLists.txt # Root CM
我正在项目中使用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来生成Source文件,即使我将生成的资源与可执行文件相关联,从而创建一个依赖关系.

当我将protofiles文件夹中的CMakeLists.txt的所有内容移动到根CMakeLists.txt根目录下时,会编译原始文件.

谁能帮我这个?我想要所有的协议缓冲区构建的东西去在protofiles文件夹中创建的CMakeLists.txt文件.

我也注意到内部CMakeLists.txt(如PROTO_SRC)中生成的变量在打印时在内部文件中定义(即我得到正确生成的CPP文件名),但是当我在根文件中打印相同的变量时,它是空的.它几乎就像我需要“导出”(如果有一个方法在cmake)变量到根文件夹.

任何帮助将不胜感激.

谢谢
卡尔蒂克

我认为 FindProtobuf不是真的意思是用这种方式.从其文档:

NOTE: The PROTOBUF_GENERATE_CPP macro & add_executable() or add_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命令有点脆弱.如果你可以避免这样做,你可能应该.

网友评论