Was ist der Unterschied zwischen include_directories und target_include_directories in CMake?

134

Ich habe eine Verzeichnisstruktur für meinen C ++ - Code, die folgendermaßen aussieht:

|
|->include
|->src

Ich schreibe eine CMakeLists.txt-Datei für meinen Code. Ich möchte den Unterschied zwischen include_directoriesund target_include_directoriesin verstehen CMake.

Was ist der Unterschied zwischen ihrer Verwendung und dem Pfad, den ich verwenden soll, um meinen Include-Dateipfad hinzuzufügen?

Ujjwal Aryan
quelle
4
Haben Sie die Dokumentation für include_directoriesund gelesen target_include_directories? Was verstehen Sie nicht über den Unterschied zwischen ihnen?
Einige Programmierer Typ
73
Es gibt keine Klarheit in der Dokumentation. Ich habe es gelesen und vermutet, was Angew in seiner Antwort geschrieben hat, aber es gibt keine Beschreibungen, keine Beispiele und für ein System, das für die Projektbildung gedacht ist, gibt es keine projektbasierten Beispiele in der CMake-Dokumentation. Hätte es eine gute und umfassende Dokumentation von CMake gegeben, hätte ich die Community nicht mit diesen Fragen belastet.
Ujjwal Aryan
Konzepte von cmake sind schlecht dokumentiert. Besonders zielgerichtet und „nicht zielgerichtet“.
John Greene

Antworten:

147

include_directories(x/y)wirkt sich auf den Verzeichnisbereich aus. Allen Zielen in dieser CMakeList sowie denen in allen Unterverzeichnissen, die nach dem Zeitpunkt des Aufrufs x/yhinzugefügt wurden , wird der Pfad zu ihrem Include-Pfad hinzugefügt.

target_include_directories(t x/y)hat Zielbereich - fügt x/yden Einschlusspfad für das Ziel hinzu t.

Sie möchten das erstere, wenn alle Ihre Ziele die betreffenden Include-Verzeichnisse verwenden. Sie möchten letzteres, wenn der Pfad zielspezifisch ist oder wenn Sie die Sichtbarkeit des Pfads genauer steuern möchten. Letzteres kommt von der Tatsache , dass target_include_directories()die Stützen PRIVATE, PUBLICund INTERFACEQualifizierer.

Angew ist nicht mehr stolz auf SO
quelle
35
Ich denke, letzteres sollte generell bevorzugt werden (solange man cmake 3 verwendet). Es hat den zusätzlichen Vorteil, dass x/yder Include-Pfad aller abhängigen Ziele, die tin ihren target_link_librariesBefehlen verwendet werden, eingegeben wird. Natürlich gibt es einen Platz für Ersteres, aber ich glaube, Letzteres ist im Allgemeinen besser.
Phil
2
In der ursprünglichen Antwort wurde angegeben, dass nur nachträglich hinzugefügte Ziele und Unterverzeichnisse include_directoriesbetroffen sind. Ich bearbeite die Antwort: In der Dokumentation wird eindeutig angegeben, dass alle Ziele in den aktuellen CMakeLists betroffen sind. Die Dokumentation erwähnt nicht, aber nur Unterverzeichnisse nach dem Anruf sind betroffen (wie in der ursprünglichen Antwort korrekt angegeben)
tamas.kenez
@Phil, target_include_directorieswurde in CMake 2.8.11 (Mai 2013) eingeführt
tamas.kenez
@ tamas.kenez Danke, dass du mich darauf aufmerksam gemacht hast, behoben. Ich war ziemlich überzeugt, dass es eine "von nun an" Sache war.
Angew ist nicht mehr stolz auf SO
40

Neben der richtigen Antwort von Angew besteht ein weiterer sehr wichtiger Unterschied zwischen include_directoriesund target_include_directoriesdarin, dass letztere bei Verwendung mit PUBLICoder INTERFACEdie INTERFACE_INCLUDE_DIRECTORIESEigenschaft des Ziels füllen. Diese Eigenschaft ist nützlich, wenn ein anderes Ziel target_link_librarieszum Verknüpfen mit dem ursprünglichen Ziel verwendet wird, da dem Verknüpfungsziel automatisch die Include-Verzeichnisse hinzugefügt werden. Siehe Beispiel .

Diese wichtige Funktion ist in der Dokumentation ziemlich gut versteckt: target_include_directories erwähnen das AuffüllenINTERFACE_INCLUDE_DIRECTORIES , dessen Dokumentation lautet:

Wenn Zielabhängigkeiten mit target_link_libraries () angegeben werden, liest CMake diese Eigenschaft aus allen Zielabhängigkeiten , um die Build-Eigenschaften des Verbrauchers zu bestimmen.

Antonio
quelle
Dies ist das erste Mal, dass ich eine verständliche Erklärung der PUBLICusw. Eigenschaften lese ! Danke: D
RL-S
1

Wie @Angew sagte, ist der Unterschied:

1, include_directories () ist für alle Dateien im Quellbaum zugänglich. 2, target_include_directories () ist beim Kompilieren nur für ein bestimmtes Ziel zugänglich.

Nick.Rhan
quelle