web-dev-qa-db-fra.com

CMake avec tampons de protocole Google

J'essaie d'utiliser cmake pour construire mon petit projet en utilisant des tampons de protocole.

Il y a un répertoire racine avec un certain nombre de sous-répertoires avec un certain nombre de bibliothèques et d'exécutables. Ma première pensée a été d'avoir mes fichiers .proto dans un sous-répertoire, mais quand j'ai lu cette réponse j'en ai fait une bibliothèque à la place. Mais lorsque j'essaie d'inclure un en-tête de message dans mon exécutable, il ne le trouve pas.

Message d'erreur:

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

Je l'exécute en créant un répertoire "build" puis "cmake .. && make" à l'intérieur. J'ai regardé et il semble que les fichiers générés soient placés dans build/messages, donc je pourrais faire include_directories (build/messages) mais cela ne semble pas ... approprié. Existe-t-il un moyen approprié de le faire avec protobuf? La raison pour laquelle je veux le fichier de messages dans leur propre dossier, c'est qu'ils seront utilisés dans de nombreux petits exécutables différents.

Tout autre conseil général pour améliorer ma structure CMake est également apprécié :)

Répertoires:

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})

serveur/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})

serveur/main.cpp:

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

Je pense que le problème ici est que la fonction PROTOBUF_GENERATE_CPP configure les fichiers .pb.h et .pb.cc pour exister dans l'arborescence de construction, pas dans l'arborescence source.

C'est une bonne pratique (sans polluer l'arborescence source), mais cela signifie que votre appel include_directories(../messages) ajoute la mauvaise valeur aux chemins de recherche. Ceci ajoute le répertoire source "root/messages", alors que vous voulez "[build root]/messages".

Vous pouvez probablement remplacer cette ligne par:

include_directories(${CMAKE_BINARY_DIR}/messages)

Cependant, un moyen plus robuste et maintenable pourrait être de définir le chemin d'inclusion requis dans les messages/CMakeLists.txt. Pour exposer cette valeur à la portée parent, cela devrait soit utiliser set(... PARENT_SCOPE) ou:

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

Ensuite, dans le CMakeLists.txt de niveau supérieur, vous pouvez faire:

include_directories(${ProtobufIncludePath})

Si votre bibliothèque messages elle-même doit #inclure les fichiers protobuf générés (ce serait normal), elle devrait également avoir un appel include_directories Similaire.

Cela dit, si vous pouvez spécifier CMake v2.8.12 au minimum, vous pouvez utiliser la commande target_include_directories à la place.

Dans messages/CMakeLists.txt après l'appel add_library, Vous feriez simplement:

target_include_directories(messages PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

Ensuite, toute autre cible qui dépend de messages a automatiquement les "messages" appropriés contenant les répertoires ajoutés à la sienne - vous n'avez pas besoin d'appeler explicitement include_directories.

23
Fraser