C++ 使用 Google 协议缓冲区的 CMake

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20824194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:20:19  来源:igfitidea点击:

CMake with Google Protocol Buffers

c++cmakeprotocol-buffers

提问by dutt

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

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

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 answerI made a library out of it instead. But when I try to include a messages header in my executable it can't find it.

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

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.

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

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

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

Directories:

目录:

root
   messages
   core
   server

root/CMakeLists.txt:

根/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:

消息/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:

核心/CMakeLists.txt:

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

server/CMakeLists.txt:

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

服务器/main.cpp:

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

回答by Fraser

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

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

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".

这是一个很好的做法(不污染源树),但这意味着您的调用include_directories(../messages)向搜索路径添加了错误的值。这是添加源目录“root/messages”,而您想要“[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:

但是,更健壮、可维护的方法可能是在消息/CMakeLists.txt 中设置所需的包含路径。要将这个值暴露给父作用域,这需要使用set(... PARENT_SCOPE)或:

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

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

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

include_directories(${ProtobufIncludePath})

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

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

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

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

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

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

target_include_directories(messages PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

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

然后任何其他messages自动依赖的目标都有适当的“消息”包括添加到它自己的目录 - 你根本不需要显式调用include_directories