CMake和FindProtobuf [英] CMake and FindProtobuf

查看:1993
本文介绍了CMake和FindProtobuf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中使用FindProtobuf模块,其中协议缓冲区文件位于子目录中。我想要该子目录中的CMakeLists.txt文件调用protoc生成CPP文件。我的项目文件夹结构是这样的:

  cammy / CMakeLists.txt#root CMakeLists.txt 
cammy / protofiles / test.proto#protofile
cammy / protofiles / CMakeLists.txt

FindProtobuf),find_package调用和对protobuf文件夹中CMakeLists.txt文件中的PROTOBUF_GENERATE_CPP的调用。



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

  add_executable($ {EXEC} $ {SRCS} $ {PROTO_SRC} $ {PROTO_HEADER})
target_link_libraries在根CMakeLists.txt中定义了{EXEC} $ {PROTOBUF_LIBRARIES})

当我运行cmake时,它不会运行protoc生成源文件,即使我明确地将生成的源绑定到可执行文件,从而创建依赖。



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



任何人都可以帮我吗?我想要所有的协议缓冲区建设的东西进入在protofiles文件夹中创建的CMakeLists.txt文件。



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



任何帮助将非常感激。 / p>

感谢
Kartik

解决方案

=http://www.cmake.org/cmake/help/v2.8.12/cmake.html#module%3aFindProtobuf> FindProtobuf 不是真的意味着要用这种方式。从其文档:


注意: PROTOBUF_GENERATE_CPP 宏& add_executable() add_library()
调用只能在同一目录中正常工作。


您尝试在子目录中使用 PROTOBUF_GENERATE_CPP 宏,虽然CMake文档不要真的清楚,一个子目录引入了一个新的变量范围。这意味着在subdir范围中设置或修改的任何变量不会影响父范围中类似命名的变量。因此, PROTO_SRC 在您的原始文件目录中可用,而不在父文件夹中。



变量范围是使用 set(...) PARENT_SCOPE) ,因此在原始档/ 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 。 custom命令指定.pb.h和.pb.cc文件作为输出,如果创建了依赖于这些文件的后续目标,则只调用自定义命令(即原始执行)。



所以,在配置时(当CMake执行时)这些文件不存在。如果您尝试将它们作为源添加到 add_library add_executable 命令 - CMake需要被告知,这些文件在运行时不存在,但在构建时它们会存在



这样做的方法是设置 GENERATED 属性为 TRUE PROTOBUF_GENERATE_CPP 宏会自动执行,但与变量一样,属性不会填充到父作用域中。因此在您的顶层CMakeLists.txt中,您还需要添加:

  set_source_files_properties($ {PROTO_SRC} $ {PROTO_HEADER}属性
GENERATED TRUE)

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


I'm using the FindProtobuf module in a project where the protocol buffer files are in a sub-directory. I want the CMakeLists.txt file in that sub-directory to invoke protoc to generate the CPP Files. My project folder structure is like this:

cammy/CMakeLists.txt   # Root CMakeLists.txt
cammy/protofiles/test.proto # protofile
cammy/protofiles/CMakeLists.txt

I have the include(FindProtobuf), the find_package invocation and the call to PROTOBUF_GENERATE_CPP in the CMakeLists.txt file in protobuf folder.

The executable build step is in the Root CMakeLists.txt file and I add the generated files to the target executable in this file ie.

add_executable( ${EXEC} ${SRCS} ${PROTO_SRC} ${PROTO_HEADER} )
target_link_libraries( ${EXEC} ${PROTOBUF_LIBRARIES} )

are both defined in the root CMakeLists.txt

When I run cmake, it does not run protoc to generate the Source files even though I expilicitly tie generated sources to the executable thereby creating a dependency.

When I move all the contents of CMakeLists.txt in the protofiles folder into the root CMakeLists.txt, the proto files are compiled.

Can anyone help me with this? I want all the protocol buffer building stuff to go in the CMakeLists.txt file created in the protofiles folder.

I also noticed that variables generated in the inner CMakeLists.txt ( like PROTO_SRC ) are defined in the inner file when printed ( ie I get the correct generated CPP filename ) but when I print the same variable in the root file.. it is empty. Its almost as though I need to "export" (if there were a way in cmake ) the variables out to the root folder.

Any help would be much appreciated.

Thanks Kartik

解决方案

I think FindProtobuf isn't really meant to be used this way. From its docs:

NOTE: The PROTOBUF_GENERATE_CPP macro & add_executable() or add_library() calls only work properly within the same directory.

You're trying to use the PROTOBUF_GENERATE_CPP macro in a subdirectory, and although the CMake docs don't really make it clear, a subdirectory introduces a new scope for variables. This means that any variables set or modified in the subdir scope don't affect similarly-named variables in the parent scope. Hence the reason for PROTO_SRC being available in your protofiles dir, but not in the parent.

The way to pass variables up a scope is to use set(... PARENT_SCOPE), so in protofiles/CMakeLists.txt you could do:

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)

However, this still doesn't get us all the way!

CMake doesn't actually invoke the protoc compiler to generate the .pb.h and .pb.cc files - it uses add_custom_command to do this. The custom command specifies the .pb.h and .pb.cc files as outputs, and the custom command is only invoked (i.e. protoc executed) if a subsequent target which depends on these files is built.

So, at configure time (when CMake executes) these files don't exist. This is a problem if you try to add them as sources to an add_library or add_executable command - CMake needs to be told that these files don't exist when it runs, but that they will exist at build time.

The way to do that is to set the GENERATED property to TRUE for these files. The PROTOBUF_GENERATE_CPP macro does that automatically, but as with the variables, the property isn't populated up into the parent scope. So in your top-level CMakeLists.txt, you also need to add:

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

As you can see, using PROTOBUF_GENERATE_CPP in a different dir to the corresponding add_library/add_executable commands is a bit fragile. If you can avoid doing it, you probably should.

这篇关于CMake和FindProtobuf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆