Подтвердить что ты не робот

CMake с буферами протокола Google

Я пытаюсь использовать cmake для создания моего маленького проекта с использованием буферов протокола.

Там есть корневой каталог с несколькими подкаталогами с рядом библиотек и исполняемых файлов. Моя первая мысль заключалась в том, чтобы мои .proto файлы в подкаталоге, но когда я читал этот ответ, я сделал из него библиотеку. Но когда я пытаюсь включить заголовок сообщения в свой исполняемый файл, он не может его найти.

Сообщение об ошибке:

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

Я запускаю его, создавая dir "build", а затем "cmake.. && make" изнутри. Я посмотрел, и кажется, что сгенерированные файлы вставляются в сборку/сообщения, поэтому я могу делать include_directories (сборка/сообщения), но это не кажется... правильным. Есть ли правильный способ сделать это с 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;
}
4b9b3361

Ответ 1

Я думаю, проблема в том, что функция PROTOBUF_GENERATE_CPP устанавливает файлы .pb.h и .pb.cc для существования в дереве сборки, а не в исходном дереве.

Это хорошая практика (не загрязняя исходное дерево), но это означает, что ваш вызов include_directories(../messages) добавляет неправильное значение в пути поиска. Это добавляет исходный каталог "root/messages", тогда как вы хотите "[build root]/messages".

Вы могли бы просто заменить эту строку:

include_directories(${CMAKE_BINARY_DIR}/messages)

Однако более надежным, удобным для обслуживания способом может быть установка необходимого пути include внутри сообщений /CMakeLists.txt. Чтобы выставить это значение в родительскую область, это должно было бы либо использовать set(... PARENT_SCOPE), либо:

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

Затем в CMakeLists.txt верхнего уровня вы можете сделать:

include_directories(${ProtobufIncludePath})

Если ваша библиотека messages сама должна # включать в себя сгенерированные файлы protobuf (это было бы нормально), то она тоже должна иметь похожий вызов include_directories.

Сказав все это, если вы можете указать CMake v2.8.12 как минимум, вы можете использовать команду target_include_directories.

В сообщениях /CMakeLists.txt после вызова add_library вы просто выполните:

target_include_directories(messages PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

Тогда любая другая цель, которая зависит от messages автоматически, имеет соответствующие "сообщения", включающие в себя dirs, добавленные в ее собственные, - вам не нужно явно вызывать include_directories вообще.