CMake target_include_directories signification de la portée

101

Quelle est la signification du mot - clé PUBLIC, PRIVATEet en INTERFACErapport avec CMake de target_include_directories?

Poorna
la source
Étroitement lié: stackoverflow.com/q/26037954/3425536
emlai

Réponses:

121

Ces mots-clés sont utilisés pour indiquer quand la liste des répertoires d'inclusion que vous transmettez à la cible est nécessaire. Par quand , cela signifie que si ces répertoires d'inclusion sont nécessaires:

  • Pour compiler cette cible elle-même.
  • Pour compiler d'autres cibles qui dépendent de cette cible (comme utiliser ses en-têtes publics).
  • Dans les deux situations ci-dessus.

Lorsque CMake compile une cible, il utilise les cibles INCLUDE_DIRECTORIES, COMPILE_DEFINITIONSet les COMPILE_OPTIONSpropriétés. Lorsque vous utilisez le PRIVATEmot - clé in target_include_directories()and alike, vous indiquez à CMake de renseigner ces propriétés cibles.

Lorsque CMake détecte une dépendance entre une cible A et une autre cible B (comme lorsque vous utilisez la target_link_libraries(A B)commande), il propage de manière transitoire B les exigences d'utilisation vers la Acible. Ces exigences d'utilisation de la cible sont les répertoires d'inclusion, les définitions de compilation, etc. que toute cible qui dépend Bdoit satisfaire. Ils sont spécifiés par la INTERFACE_*version des propriétés listées ci-dessus (comme INTERFACE_INCLUDE_DIRECTORIES) et sont renseignés à l'aide du INTERFACEmot - clé lors de l'appel dutarget_*() commandes.

Le PUBLICmot-clé signifie à peu près PRIVATE + INTERFACE.

Par conséquent, supposons que vous créez une bibliothèque Aqui utilise des en-têtes Boost. Vous feriez:

  • target_include_directories(A PRIVATE ${Boost_INCLUDE_DIRS})si vous n'utilisez ces en-têtes Boost que dans vos fichiers source ( .cpp) ou vos fichiers d'en- tête privés ( .h).
  • target_include_directories(A INTERFACE ${Boost_INCLUDE_DIRS})si vous n'utilisez pas ces en-têtes Boost dans vos fichiers source (par conséquent, vous n'avez pas besoin de les compiler A). Je ne peux pas vraiment penser à un exemple réel pour cela.
  • target_include_directories(A PUBLIC ${Boost_INCLUDE_DIRS})si vous utilisez ces en-têtes Boost dans vos fichiers d'en-tête publics, qui sont inclus À LA FOIS dans certains Afichiers source de et peuvent également être inclus dans tout autre client de votre Abibliothèque.

La documentation CMake 3.0 contient plus de détails sur cette spécification de construction et les propriétés des exigences d'utilisation .

TManhente
la source
18
En ce qui concerne un exemple réel de INTERFACE. target_include_directories(libname INTERFACE include PRIVATE include/libname). Cela signifie que dans votre bibliothèque, vous pouvez inclure des fichiers directement, mais en tant qu'utilisateur de la bibliothèque, vous devez d' libname/abord insérer .
KaareZ
2
Cette réponse me semble logique pour la création de bibliothèques. Mais que diriez-vous d'appeler target_include_directories pour une cible qui est un exécutable?
Norman Pellet
1
@NormanPellet: Vous pouvez appeler target_include_directories()une cible exécutable si vous devez définir des répertoires d'inclusion dans lesquels les fichiers d'en-tête utilisés par ces exécutables se trouvent (par exemple: Boost :: Program_options, si vous l'utilisez pour analyser les arguments de votre main()fonction) . Vous utiliseriez probablement le PRIVATEmot - clé dans ce cas, car ces fichiers sont nécessaires pour compiler l'exécutable lui-même. Je ne sais pas s'il y a une utilisation pour INTERFACEou PUBLICsur un exécutable, cependant.
TManhente
13

Les mots clés INTERFACE, PUBLIC et PRIVATE sont nécessaires pour spécifier la portée des arguments suivants. Les éléments PRIVATE et PUBLIC rempliront la propriété INCLUDE_DIRECTORIES de <target>. Les éléments PUBLIC et INTERFACE rempliront la propriété INTERFACE_INCLUDE_DIRECTORIES de <cible>. Les arguments suivants spécifient les répertoires d'inclusion.

Depuis la documentation: http://www.cmake.org/cmake/help/v3.0/command/target_include_directories.html

Pour reformuler la documentation avec mes propres mots:

  • vous voulez ajouter un répertoire à la liste du répertoire d'inclusion pour une cible
  • avec PRIVATE le répertoire est ajouté aux répertoires d'inclusion de la cible
  • avec INTERFACE la cible n'est pas modifiée, mais l'INTERFACE_INCLUDE_DIRECTORIES est étendue par le répertoire. La variable est une liste de répertoires d'inclusion publics pour une bibliothèque.
  • avec PUBLIC, les deux actions de PRIVATE et INTERFACE sont effectuées.
usr1234567
la source
4
J'ai parcouru la documentation de CMAKE, mais je n'ai toujours pas compris ce qu'ils signifient réellement et dans quel contexte (créer des fichiers ou comment ils sont compilés)?
Poorna
@Sirish: J'ai essayé de reformuler la documentation, j'espère que cela aide.
usr1234567