【问题标题】:CMake with Google Protocol Buffers使用 Google 协议缓冲区的 CMake
【发布时间】:2014-01-16 10:23:17
【问题描述】:

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

有一个根目录,其中包含许多子目录以及许多库和可执行文件。我的第一个想法是将我的 .proto 文件放在子目录中,但是当我阅读 this answer 时,我用它创建了一个库。但是当我尝试在我的可执行文件中包含消息头时,它找不到它。

错误信息:

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

我通过在其中创建一个目录“build”然后“cmake .. && make”来运行它。 我看过了,似乎生成的文件被放入了 build/messages,所以我可以做 include_directories(build/messages) 但这似乎不合适。有没有用protobuf做这件事的正确方法?我希望将消息文件放在它们自己的文件夹中的原因是它们将被用于许多不同的小型可执行文件中。

对于改进我的 CMake 结构的任何其他一般提示也表示赞赏:)

目录:

root
   messages
   core
   server

根目录/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()

消息/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})

核心/CMakeLists.txt:

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

服务器/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})

服务器/main.cpp:

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

【问题讨论】:

    标签: c++ cmake protocol-buffers


    【解决方案1】:

    我认为这里的问题是 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) 或:

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

    然后在顶层 CMakeLists.txt 中,你可以这样做:

    include_directories(${ProtobufIncludePath})
    

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

    说了这么多,如果你可以指定 CMake v2.8.12 为最低,你可以使用target_include_directories 命令代替。

    add_library 调用之后的messages/CMakeLists.txt 中,您只需这样做:

    target_include_directories(messages PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
    

    那么任何其他依赖于messages 的目标都会自动将相应的“消息”包括添加到自己的目录中——您根本不需要显式调用include_directories

    【讨论】:

    • 看来 ubuntu stable 运行的是 2.8.11,所以我选择了稍长的版本。
    • 我还应该提到:应该不需要 link_directories 调用(它自己的文档不鼓励使用它),并且您可能知道,add_definitions(-std=c++11) 应该只在以下情况下应用我猜编译器是 GCC 或 Clang。除此之外,结构对我来说都很好。
    • 啊,我会尝试删除 link_directories 调用。我在这个小项目中使用 gcc,所以定义很好,但还是谢谢你提到它:)
    猜你喜欢
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 2011-04-23
    • 2012-05-03
    • 1970-01-01
    • 2011-10-18
    相关资源
    最近更新 更多