Stellen Sie sich das folgende Szenario vor: Projekt A ist eine gemeinsam genutzte Bibliothek mit mehreren Abhängigkeiten (LibA, LibB und LibC). Projekt B ist eine ausführbare Datei, die von Projekt A abhängig ist und daher zum Erstellen alle Abhängigkeiten von Projekt A benötigt.
Darüber hinaus werden beide Projekte mit CMake erstellt, und Projekt A sollte nicht installiert werden müssen (über das Installationsziel), damit Projekt B es verwenden kann, da dies für Entwickler zu einem Ärgernis werden kann.
Was ist der beste Weg, um diese Abhängigkeiten mit CMake zu lösen? Die ideale Lösung wäre so einfach wie möglich (wenn auch nicht einfacher) und erfordert nur minimale Wartung.
Antworten:
Einfach. Hier ist das Beispiel von oben:
Die oberste Ebene
CMakeLists.txt
:CMakeLists.txt
incomponents/B
:CMakeLists.txt
incomponents/C
:CMakeLists.txt
incomponents/A
:CMakeLists.txt
incomponents/Executable
:Um dies zu verdeutlichen, ist hier die entsprechende Quellbaumstruktur:
Es gibt viele Punkte, an denen dies optimiert / angepasst oder geändert werden kann, um bestimmte Anforderungen zu erfüllen, aber dies sollte Ihnen zumindest den Einstieg erleichtern.
HINWEIS: Ich habe diese Struktur erfolgreich in mehreren mittelgroßen und großen Projekten eingesetzt.
quelle
set(...INCLUDE_DIRS
und einmal fürinclude_directories()
), was ich schwer zu pflegen finde (immer daran denken, an zwei Stellen eine neue Include-Abhängigkeit hinzuzufügen ). Sie könnten sie mit abfragenget_property(...PROPERTY INCLUDE_DIRECTORIES)
.Alexander Shukaev hat einen großartigen Start hingelegt, aber es gibt eine Reihe von Dingen, die besser gemacht werden könnten:
target_include_directories
. Sie müssen dies jedoch wahrscheinlich nicht einmal tun, wenn Sie die importierten Ziele verwenden.Verwenden Sie die importierten Ziele. Beispiel für Boost:
Dies kümmert sich um die Include-Verzeichnisse, Bibliotheken usw. Wenn Sie Boost in Ihren Headern in B verwendet haben, verwenden Sie anstelle von PRIVATE PUBLIC, und diese Abhängigkeiten werden transitiv zu dem hinzugefügt, was von B abhängt.
Verwenden Sie kein Dateiglobing (es sei denn, Sie verwenden 3.12). Bis vor kurzem funktioniert das Globbing von Dateien nur während der Konfigurationszeit. Wenn Sie also Dateien hinzufügen und erstellen, können die Änderungen erst erkannt werden, wenn Sie das Projekt explizit neu generieren. Wenn Sie die Dateien jedoch direkt auflisten und versuchen, sie zu erstellen, sollte sie erkennen, dass die Konfiguration veraltet ist, und im Erstellungsschritt automatisch neu generiert werden.
Hier (YouTube) wird gut geredet: C ++ Now 2017: Daniel Pfeifer „Effective CMake“
Welche einen Paket - Manager Idee deckt , dass Ihr Root - Ebene CMake Arbeit mit ermöglicht
find_package
ORsubdirectory
, aber ich habe versucht , die Ideologie , dies zu übernehmen und große Probleme habe mit der Verwendungfind_package
für alles und eine Verzeichnisstruktur wie das Ihre ist.quelle
Dies kann auch mithilfe des CMake-
Cache
Mechanismus erfolgen, um dasselbe zu erreichen (dh gemeinsame Nutzung projektspezifischer Variablen):Siehe Frage zum Stapelüberlauf . So teilen Sie Variablen zwischen verschiedenen CMake-Dateien .
quelle