2013-10-13 5 views
11

Ich verwende das FindProtobuf-Modul in einem Projekt, in dem sich die Protokollpufferdateien in einem Unterverzeichnis befinden. Ich möchte die Datei CMakeLists.txt in diesem Unterverzeichnis aufrufen, um die CPP-Dateien zu generieren. Mein Projekt Ordnerstruktur ist wie folgt:CMake und FindProtobuf

cammy/CMakeLists.txt # Root CMakeLists.txt 
cammy/protofiles/test.proto # protofile 
cammy/protofiles/CMakeLists.txt 

Ich habe die umfassen (FindProtobuf), der find_package Aufruf und der Aufruf von PROTOBUF_GENERATE_CPP in der CMakeLists.txt Datei in protobuf Ordner.

Der ausführbare Build-Schritt befindet sich in der Root CMakeLists.txt-Datei, und ich füge die generierten Dateien der ausführbaren Zieldatei in dieser Datei IEEE hinzu.

add_executable(${EXEC} ${SRCS} ${PROTO_SRC} ${PROTO_HEADER}) 
target_link_libraries(${EXEC} ${PROTOBUF_LIBRARIES}) 

sind beide in der Wurzel definiert CMakeLists.txt

Wenn ich Cmake laufen, ist es nicht Protoc laufen die Quelle zu generieren Dateien, obwohl ich expilicitly auf die ausführbare Datei erzeugt Quellen binden, wodurch eine Abhängigkeit zu schaffen.

Wenn ich den gesamten Inhalt von CMakeLists.txt im Protofiles-Ordner in den Stamm CMakeLists.txt verschiebe, werden die Proto-Dateien kompiliert.

Kann mir jemand dabei helfen? Ich möchte, dass alle Sachen, die den Protokollpuffer aufbauen, in die Datei CMakeLists.txt gehen, die im Ordner protofiles erstellt wurde.

Ich habe auch festgestellt, dass Variablen in der inneren CMakeLists.txt (wie PROTO_SRC) in der inneren Datei beim Drucken (dh ich bekomme den korrekten CPP-Dateinamen erzeugt) definiert, aber wenn ich die gleiche Variable in der Root-Datei drucken. . es ist leer. Es ist fast so, als ob ich die Variablen in den Wurzelordner "exportieren" müsste (wenn es einen Weg in cmake gäbe).

Jede Hilfe würde sehr geschätzt werden.

Dank Kartik

Antwort

19

denke ich FindProtobuf nicht wirklich auf diese Weise verwendet werden soll gemeint ist. Von seiner docs:

HINWEIS: Die PROTOBUF_GENERATE_CPP Makro & add_executable() oder add_library() Anrufe funktionieren nur richtig im gleichen Verzeichnis.

Sie versuchen, die PROTOBUF_GENERATE_CPP Makro in einem Unterverzeichnis zu verwenden, und obwohl die CMake docs es klar, nicht wirklich machen, stellt ein Unterverzeichnis einen neuen Bereich für Variablen. Dies bedeutet, dass alle Variablen, die im Unterverzeichnisbereich festgelegt oder geändert werden, keine gleichnamigen Variablen im übergeordneten Bereich betreffen. Daher ist der Grund für PROTO_SRC in Ihrem Protofiles-Verzeichnis verfügbar, aber nicht im übergeordneten Element.

Die Art und Weise Variablen einen Bereich zu verzichten ist set(... PARENT_SCOPE) zu verwenden, also in protofiles/CMakeLists.txt Sie tun können:

PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER test.proto) 

set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE) 
set(PROTOBUF_LIBRARIES ${PROTOBUF_LIBRARIES} PARENT_SCOPE) 
set(PROTO_SRC ${PROTO_SRC} PARENT_SCOPE) 
set(PROTO_HEADER ${PROTO_HEADER} PARENT_SCOPE) 

Dies schließt jedoch immer noch nicht, uns den ganzen Weg!

CMake ruft nicht den Protoc-Compiler auf, um die .pb.h- und .pb.cc-Dateien zu generieren - hierfür wird add_custom_command verwendet. Der benutzerdefinierte Befehl gibt die Datei .pb.h und .pb an.cc-Dateien als Ausgaben, und der benutzerdefinierte Befehl wird nur aufgerufen (d. h. protokolliert), wenn ein nachfolgendes Ziel, das von diesen Dateien abhängt, erstellt wird.

Zum Zeitpunkt der Konfiguration (wenn CMake ausgeführt wird) sind diese Dateien nicht vorhanden. Dies ist ein Problem, wenn Sie versuchen, sie als Quellen zu einem add_library oder add_executable Befehl hinzufügen - CMake muss gesagt werden, dass diese Dateien nicht existieren, wenn es ausgeführt wird, aber dass sie zur Build-Zeit existieren.

Der Weg dies zu tun, ist die GENERATED Eigenschaft auf TRUE für diese Dateien zu setzen. Das Makro PROTOBUF_GENERATE_CPP erledigt das automatisch, aber wie bei den Variablen wird die Eigenschaft nicht in den übergeordneten Bereich eingefügt. Also in Ihrem Top-Level-CMakeLists.txt, müssen Sie auch hinzufügen:

set_source_files_properties(${PROTO_SRC} ${PROTO_HEADER} PROPERTIES 
          GENERATED TRUE) 

Wie Sie sehen können, mit PROTOBUF_GENERATE_CPP in einem anderen Verzeichnis zu den entsprechenden add_library/add_executable Befehlen ein bisschen zerbrechlich sind. Wenn Sie können vermeiden, es zu tun, sollten Sie wahrscheinlich.

+0

Danke für die Klärung der Dinge. Zusammenfassend kann ich sagen, dass der Grund, warum das verschachtelte Proto-Kompilieren nicht funktioniert, darin liegt, dass die generierten Variablen nicht im Bereich des Turms liegen? Ist es auch möglich, das GENERATED-Flag zu markieren, wenn wir die Variablen für den übergeordneten Bereich von den lokalen Variablen aus setzen, anstatt es in der Root-Datei zu tun? Schließlich wäre es ein alternativer Ansatz, den protobuf stuff als eine Bibliothek zu erstellen und einfach mit der ausführbaren root-Datei zu verknüpfen. –

+0

@KartikAiyer Nicht sicher, was "nicht im Bereich des Turmes" bedeutet, aber wenn es "nicht im Bereich der Top-Level CMakeLists.txt" ist, dann ja. Für Q2, nein - meines Wissens gibt es keine Möglichkeit, Eigenschaften für Dateien festzulegen, die im übergeordneten Bereich definiert sind. Für Q3, ja - ich denke, das wäre ein guter Ansatz. – Fraser

+0

@Fraser danke für Ihre Antwort, ich habe eine ähnliche Frage, ich das Projekt anpassen und immer noch nicht arbeiten, ist es möglich, dass mir mehr Anregung geben? ref: http://stackoverflow.com/questions/29720410/no-member-found-when-use-cmake-construct-proto, Beispielprojekt: https://github.com/yuikns/cmake-proto –