CMake和FindProtobuf

Kar*_*yer 13 cmake protocol-buffers

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

cammy/CMakeLists.txt   # Root CMakeLists.txt
cammy/protofiles/test.proto # protofile
cammy/protofiles/CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

我有include(FindProtobuf),find_package调用和protobuf文件夹中CMakeLists.txt文件中对PROTOBUF_GENERATE_CPP的调用.

可执行构建步骤位于Root CMakeLists.txt文件中,我将生成的文件添加到此文件中的目标可执行文件中,即.

add_executable( ${EXEC} ${SRCS} ${PROTO_SRC} ${PROTO_HEADER} )
target_link_libraries( ${EXEC} ${PROTOBUF_LIBRARIES} )
Run Code Online (Sandbox Code Playgroud)

都在根CMakeLists.txt中定义

当我运行cmake时,它不会运行protoc来生成源文件,即使我将生成的源与可执行文件捆绑在一起从而创建依赖项.

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

谁能帮我这个?我希望所有协议缓冲区构建内容都包含在protofiles文件夹中创建的CMakeLists.txt文件中.

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

任何帮助将非常感激.

谢谢Kartik

Fra*_*ser 22

我认为FindProtobuf这并不是真的意味着以这种方式使用.从它的文档:

注意:PROTOBUF_GENERATE_CPP宏和/ add_executable()add_library() 调用仅在同一目录中正常工作.

您正在尝试PROTOBUF_GENERATE_CPP在子目录中使用宏,虽然CMake文档并没有真正说清楚,但子目录引入了变量的新范围.这意味着在子范围中设置或修改的任何变量都不会影响父范围中类似命名的变量.因此PROTO_SRC,你的protofiles目录中可用的原因,但不是在父.

将变量传递到作用域的方法是使用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)
Run Code Online (Sandbox Code Playgroud)

但是,这仍然没有让我们一路走来!

CMake实际上并没有调用protoc编译器来生成.pb.h和.pb.cc文件 - 它add_custom_command用来执行此操作.custom命令将.pb.h和.pb.cc文件指定为输出,并且仅在构建依赖于这些文件的后续目标时才调用自定义命令(即执行protoc).

因此,在配置时(CMake执行时),这些文件不存在.如果您尝试将它们作为源添加到add_libraryadd_executable命令,则会出现问题- 需要告知CMake运行时这些文件不存在,但它们在构建时存在.

这样做的方法是为这些文件设置GENERATED属性TRUE.该PROTOBUF_GENERATE_CPP宏做自动,但与变量,属性未填充成父范围.因此,在您的顶级CMakeLists.txt中,您还需要添加:

set_source_files_properties(${PROTO_SRC} ${PROTO_HEADER} PROPERTIES
                            GENERATED TRUE)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,PROTOBUF_GENERATE_CPP在不同的目录中使用相应的add_library/ add_executable命令有点脆弱.如果你避免这样做,你应该.