带有Google协议缓冲区的CMake [英] CMake with Google Protocol Buffers

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

问题描述

我正在尝试使用cmake使用协议缓冲区来构建我的小项目。



有一个带有许多子目录的根目录,这些子目录具有许多库和可执行文件。我最初的想法是将.proto文件放在子目录中,但是当我阅读此答案时,我制作了一个库相反。但是,当我尝试在可执行文件中包含message标头时,找不到它。



错误消息:

 致命错误:msgs.pb.h:没有这样的文件或目录
#include msgs.pb.h
^
编译终止。

我正在通过创建目录 build然后 cmake ..&& ;从里面制作。
我看过了,似乎生成的文件放在了build / messages中,所以我可以做include_directories(build / messages),但这似乎不对。是否有使用protobuf执行此操作的正确方法?我想要将消息文件保存在自己的文件夹中的原因是,它们将在许多不同的小型可执行文件中使用。



有关改善CMake的任何其他一般性提示-structure也值得赞赏:)



目录:

  root 
消息
核心
服务器

root / CMakeLists.txt:

  project(lillebror)
cmake_minimum_required(版本2.8)
cmake_policy(SET CMP0015 NEW)

设置(Boost_USE_STATIC_LIBS ON)
设置(Boost_USE_MULTITHREADED ON)
设置(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost组件date_time日志线程系统)
find_package(需要Protobuf)
if(Boost_FOUND)
add_definitions(-std = c ++ 11)
add_subdirectory(消息)
add_subdirectory(核心)
add_subdirectory(服务器)
add_subdirectory (测试服务器)
endif()

messages / CMakeLists.txt:

  file(GLOB原型文件 $ {CMAKE_CURRENT_SOURCE_DIR} / *。proto)
PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders $ {ProtoFiles})
add_library(消息静态$ {ProtoSources} $ {ProtoHeaders})
target_link_libraries(消息$ {Boost_LIBRARIES} $ {PROTOBUF_LIBRARY})

core / CMakeLists.txt:

  aux_source_directory(src SRC_LIST)
add_library (核心静态$ {SRC_LIST})
target_link_libraries(核心消息$ {Boost_LIBRARIES})

服务器/CMakeLists.txt:

  aux_source_directory(src SRC_LIST)
include_directories(../ messages)<- -我以为这样可以解决我的问题
include_directories(../ core / src)
link_directories(../ core / build)
add_executable(服务器$ {SRC_LIST})
target_link_libraries(服务器核心$ {Boost_LIBRARIES})

server / main.cpp:

  #include msgs.pb.h 
int m ain()
{
返回0;
}


解决方案

我认为这里的问题是 PROTOBUF_GENERATE_CPP 函数将.pb.h和.pb.cc文件设置为存在于生成树中,而不存在于源代码树中。



这是一个好习惯(不污染源树),但这意味着您的调用 include_directories(../ messages)给搜索路径添加了错误的值。这是在源目录中添加 root / messages,而您要 [build root] / messages。



您可能只需将该行替换为:

  include_directories($ {CMAKE_BINARY_DIR} / messages)

但是,更健壮,更易维护的方法可能是在messages / CMakeLists.txt中设置所需的包含路径。要将此值公开给父范围,则需要使用 set(... PARENT_SCOPE)或:



< pre class = lang-none prettyprint-override> set(ProtobufIncludePath $ {CMAKE_CURRENT_BINARY_DIR}
CACHE INTERNAL生成protobuf文件的路径。)

然后在顶级CMakeLists.txt中,您可以执行以下操作:

  include_directories($ {ProtobufIncludePath})

如果您的 messages 库本身需要#include生成的protobuf文件(这是正常的),那么它也应该具有类似的 include_directories 调用。



话虽如此,如果您可以将CMake v2.8.12指定为最小值,则可以使用 target_include_directories 命令代替。



消息/ CMake中调用 add_library 后的Lists.txt,您只需执行以下操作:

  target_include_directories(消息PUBLIC $ {CMAKE_CURRENT_BINARY_DIR})

然后根据 messages 会自动添加适当的 messages包括dirs-您根本不需要显式调用 include_directories 。 / p>

I'm trying to use cmake to build my little project using protocol buffers.

There's a root directory with a number of subdirectories with a number of libraries and executables. My first thought was to have my .proto-files in a subdirectory, but when I read this answer I made a library out of it instead. But when I try to include a messages header in my executable it can't find it.

Error message:

fatal error: msgs.pb.h: No such file or directory
 #include "msgs.pb.h"
                     ^
compilation terminated.

I'm running it by creating a dir "build" and then "cmake .. && make" from inside it. I've looked and it seems the generated files get put in build/messages, so I could do include_directories(build/messages) but that doesn't seem...proper. Is there a proper way of doing this with protobuf? The reason I want the messages file in their own folder is they they'll be used in a lot of different small executables.

Any other general tips for improvements to my CMake-structure is also appreciated :)

Directories:

root
   messages
   core
   server

root/CMakeLists.txt:

project(lillebror)
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0015 NEW)

set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost COMPONENTS date_time log thread system)
find_package(Protobuf REQUIRED)
if(Boost_FOUND)
    add_definitions(-std=c++11)
    add_subdirectory(messages)
    add_subdirectory(core)
    add_subdirectory(server)
    add_subdirectory(testserver)
endif()

messages/CMakeLists.txt:

file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles})
add_library(messages STATIC ${ProtoSources} ${ProtoHeaders})
target_link_libraries(messages ${Boost_LIBRARIES} ${PROTOBUF_LIBRARY})

core/CMakeLists.txt:

aux_source_directory(src SRC_LIST)
add_library(core STATIC ${SRC_LIST})
target_link_libraries(core messages ${Boost_LIBRARIES})

server/CMakeLists.txt:

aux_source_directory(src SRC_LIST)
include_directories(../messages) <---- I thought this would sove my problem
include_directories(../core/src)
link_directories(../core/build)
add_executable(server ${SRC_LIST})
target_link_libraries(server core ${Boost_LIBRARIES})

server/main.cpp:

#include "msgs.pb.h"
int main()
{
    return 0;
}

解决方案

I think the problem here is that the PROTOBUF_GENERATE_CPP function sets up the .pb.h and .pb.cc files to exist in the build tree, not in the source tree.

This is good practice (not polluting the source tree), but it means that your call include_directories(../messages) is adding the wrong value to the search paths. This is adding the source directory "root/messages", whereas you want "[build root]/messages".

You could probably just replace that line with:

include_directories(${CMAKE_BINARY_DIR}/messages)

However, a more robust, maintainable way might be to set the required include path inside the messages/CMakeLists.txt. To expose this value to the parent scope, this would need to either use set(... PARENT_SCOPE) or:

set(ProtobufIncludePath ${CMAKE_CURRENT_BINARY_DIR}
    CACHE INTERNAL "Path to generated protobuf files.")

Then in the top-level CMakeLists.txt, you can do:

include_directories(${ProtobufIncludePath})

If your messages library itself needs to #include the generated protobuf files (this would be normal), then it too should have a similar include_directories call.

Having said all that, if you can specify CMake v2.8.12 as the minimum, you can use the target_include_directories command instead.

In messages/CMakeLists.txt after the add_library call, you'd simply do:

target_include_directories(messages PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

Then any other target which depends on messages automatically has the appropriate "messages" include dirs added to its own - you don't need to explicitly call include_directories at all.

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

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