Quelle est la différence entre include_directories et target_include_directories dans CMake?

134

J'ai une structure de répertoires pour mon code C ++ qui va comme ceci:

|
|->include
|->src

J'écris un fichier CMakeLists.txt pour mon code. Je veux comprendre la différence entre include_directorieset target_include_directoriesdans CMake.

Quelle est la différence entre leur utilisation et pour ajouter mon chemin de fichier d'inclusion, lequel dois-je utiliser?

Ujjwal Aryen
la source
4
Avez-vous lu la documentation pour include_directorieset target_include_directories? Qu'est-ce que vous ne comprenez pas à la différence entre eux?
Un mec programmeur du
74
Il n'y a pas de clarté dans la documentation. Je l'ai lu et j'ai supposé ce qu'Angew a écrit dans sa réponse, mais il n'y a pas de descriptions, pas d'exemples et pour un système destiné à la construction de projets, il n'y a pas d'exemples basés sur des projets dans la documentation de CMake. S'il y avait eu une bonne documentation exhaustive de CMake, je n'aurais pas alourdi la communauté avec ces questions.
Ujjwal Aryan
Les concepts de cmake sont mal documentés. Particulièrement ciblé et «non ciblé».
John Greene

Réponses:

148

include_directories(x/y)affecte la portée du répertoire. Toutes les cibles de cette CMakeList, ainsi que celles de tous les sous-répertoires ajoutés après le point de son appel, auront le chemin x/yajouté à leur chemin d'inclusion.

target_include_directories(t x/y)a une portée cible - il ajoute x/yau chemin d'inclusion de la cible t.

Vous voulez l'ancien si toutes vos cibles utilisent les répertoires d'inclusion en question. Vous voulez ce dernier si le chemin est spécifique à une cible, ou si vous voulez un contrôle plus fin de la visibilité du chemin. Ce dernier provient du fait que target_include_directories()soutient les PRIVATE, PUBLICet INTERFACEqualificatifs.

Angew n'est plus fier de SO
la source
35
Je pense que ce dernier devrait généralement être préféré (tant que l'on utilise cmake 3). Il a l'avantage supplémentaire de mettre x/ydans le chemin d'inclusion de toutes les cibles dépendantes qui utilisent tdans leurs target_link_librariescommandes. Bien sûr, il y a une place pour le premier, mais je pense que le second est généralement meilleur.
Phil
2
La réponse originale indiquait que seuls les cibles et sous-répertoires ajoutés après include_directoriesseront affectés. Je modifie la réponse: la documentation indique clairement que toutes les cibles des CMakeLists actuelles sont affectées. La documentation ne mentionne pas mais seuls les sous-répertoires après l'appel sont affectés (comme cela a été correctement indiqué dans la réponse d'origine)
tamas.kenez
@Phil, target_include_directoriesa été introduit dans CMake 2.8.11 (mai 2013)
tamas.kenez
@ tamas.kenez Merci d'avoir porté ceci à mon attention, corrigé. J'étais assez convaincu que c'était une chose "à partir de maintenant".
Angew n'est plus fier de SO
40

Outre ce que dit correctement la réponse d'Angew , une autre différence très importante entre include_directorieset target_include_directoriesest que, lorsqu'il est utilisé avec PUBLICou INTERFACE, ce dernier remplit la INTERFACE_INCLUDE_DIRECTORIESpropriété de la cible. Cette propriété est utile lorsqu'une autre cible utilise target_link_librariespour se lier à la cible d'origine, car la cible de liaison aura automatiquement ces répertoires d'inclusion ajoutés. Voir exemple .

Cette fonctionnalité importante est assez bien cachée dans la documentation: target_include_directories mentionne le remplissageINTERFACE_INCLUDE_DIRECTORIES , dont la documentation dit:

Lorsque les dépendances cibles sont spécifiées à l'aide de target_link_libraries () , CMake lira cette propriété à partir de toutes les dépendances cibles pour déterminer les propriétés de construction du consommateur.

Antonio
la source
C'est la première fois que je lis une explication compréhensible des PUBLICpropriétés, etc. Merci: D
RL-S
2

Comme l'a dit @Angew, la différence même est:

1, include_directories () est accessible pour tous les fichiers de l'arborescence des sources 2, target_include_directories () n'est accessible que pour une cible spécifique lors de la compilation.

Nick.Rhan
la source