Estas palabras clave se utilizan para indicar cuándo se necesita la lista de directorios de inclusión que está pasando al destino. Para cuándo , significa si se necesitan directorios de inclusión:
Para compilar ese objetivo en sí mismo.
Para compilar otros destinos que dependen de ese destino (como usar sus encabezados públicos).
En las dos situaciones anteriores.
Cuando CMake está compilando un objetivo, que utiliza los objetivos INCLUDE_DIRECTORIES, COMPILE_DEFINITIONSy COMPILE_OPTIONSpropiedades. Cuando usa la PRIVATEpalabra clave in target_include_directories()y similar, le dice a CMake que complete esas propiedades de destino.
Cuando CMake detecta una dependencia entre un objetivo A y otro objetivo B (como cuando usa el target_link_libraries(A B)comando), propaga de forma transitiva Blos requisitos de uso al Aobjetivo. Los requisitos de uso de destino son los directorios de inclusión, las definiciones de compilación, etc. que Bdebe cumplir cualquier destino que dependa . Se especifican mediante la INTERFACE_*versión de las propiedades enumeradas anteriormente (como INTERFACE_INCLUDE_DIRECTORIES) y se completan utilizando la INTERFACEpalabra clave al llamar a los target_*()comandos.
La PUBLICpalabra clave significa aproximadamente PRIVATE + INTERFACE.
Por lo tanto, suponga que está creando una biblioteca Aque usa algunos encabezados de Boost. Tu harías:
target_include_directories(A PRIVATE ${Boost_INCLUDE_DIRS})si solo usa esos encabezados de Boost dentro de sus archivos de origen ( .cpp) o archivos de encabezado privados ( .h).
target_include_directories(A INTERFACE ${Boost_INCLUDE_DIRS})si no usa esos encabezados de Boost dentro de sus archivos fuente (por lo tanto, no los necesita para compilar A). En realidad, no puedo pensar en un ejemplo del mundo real para esto.
target_include_directories(A PUBLIC ${Boost_INCLUDE_DIRS})si usa esos encabezados de Boost en sus archivos de encabezado públicos, que se incluyen AMBOS en algunos de Alos archivos fuente y también pueden estar incluidos en cualquier otro cliente de su Abiblioteca.
Con respecto a un ejemplo del mundo real de INTERFACE. target_include_directories(libname INTERFACE include PRIVATE include/libname). Esto significa que dentro de su biblioteca puede incluir archivos directamente, pero como usuario de la biblioteca debe insertar libname/primero.
KaareZ
2
Esta respuesta tiene sentido para mí para crear bibliotecas. Pero, ¿qué tal llamar a target_include_directories para un objetivo que es un ejecutable?
Norman Pellet
1
@NormanPellet: puede llamar target_include_directories()a un destino ejecutable si necesita establecer directorios de inclusión donde se encuentran los archivos de encabezado que usan esos ejecutables (por ejemplo: Boost :: Program_options, si lo usa para analizar argumentos en su main()función) . Probablemente usaría la PRIVATEpalabra clave en este caso, ya que estos archivos son necesarios para compilar el ejecutable en sí. Sin embargo, no sé si hay algún uso para INTERFACEo PUBLICen un ejecutable.
TManhente
13
Las palabras clave INTERFACE, PUBLIC y PRIVATE son necesarias para especificar el alcance de los siguientes argumentos. Los elementos PRIVADOS y PÚBLICOS poblarán la propiedad INCLUDE_DIRECTORIES de <target>. Los elementos PUBLIC e INTERFACE completarán la propiedad INTERFACE_INCLUDE_DIRECTORIES de <target>. Los siguientes argumentos especifican directorios de inclusión.
Para reformular la documentación con mis propias palabras:
desea agregar un directorio a la lista de directorios de inclusión para un objetivo
con PRIVATE el directorio se agrega a los directorios de inclusión del objetivo
con INTERFACE no se modifica el destino, pero el directorio amplía INTERFACE_INCLUDE_DIRECTORIES. La variable es una lista de directorios de inclusión públicos para una biblioteca.
con PUBLIC se realizan ambas acciones desde PRIVATE e INTERFACE.
Respuestas:
Estas palabras clave se utilizan para indicar cuándo se necesita la lista de directorios de inclusión que está pasando al destino. Para cuándo , significa si se necesitan directorios de inclusión:
Cuando CMake está compilando un objetivo, que utiliza los objetivos
INCLUDE_DIRECTORIES
,COMPILE_DEFINITIONS
yCOMPILE_OPTIONS
propiedades. Cuando usa laPRIVATE
palabra clave intarget_include_directories()
y similar, le dice a CMake que complete esas propiedades de destino.Cuando CMake detecta una dependencia entre un objetivo A y otro objetivo B (como cuando usa el
target_link_libraries(A B)
comando), propaga de forma transitivaB
los requisitos de uso alA
objetivo. Los requisitos de uso de destino son los directorios de inclusión, las definiciones de compilación, etc. queB
debe cumplir cualquier destino que dependa . Se especifican mediante laINTERFACE_*
versión de las propiedades enumeradas anteriormente (comoINTERFACE_INCLUDE_DIRECTORIES
) y se completan utilizando laINTERFACE
palabra clave al llamar a lostarget_*()
comandos.La
PUBLIC
palabra clave significa aproximadamentePRIVATE + INTERFACE
.Por lo tanto, suponga que está creando una biblioteca
A
que usa algunos encabezados de Boost. Tu harías:target_include_directories(A PRIVATE ${Boost_INCLUDE_DIRS})
si solo usa esos encabezados de Boost dentro de sus archivos de origen (.cpp
) o archivos de encabezado privados (.h
).target_include_directories(A INTERFACE ${Boost_INCLUDE_DIRS})
si no usa esos encabezados de Boost dentro de sus archivos fuente (por lo tanto, no los necesita para compilarA
). En realidad, no puedo pensar en un ejemplo del mundo real para esto.target_include_directories(A PUBLIC ${Boost_INCLUDE_DIRS})
si usa esos encabezados de Boost en sus archivos de encabezado públicos, que se incluyen AMBOS en algunos deA
los archivos fuente y también pueden estar incluidos en cualquier otro cliente de suA
biblioteca.La documentación de CMake 3.0 tiene más detalles sobre esta especificación de compilación y las propiedades de los requisitos de uso .
fuente
INTERFACE
.target_include_directories(libname INTERFACE include PRIVATE include/libname)
. Esto significa que dentro de su biblioteca puede incluir archivos directamente, pero como usuario de la biblioteca debe insertarlibname/
primero.target_include_directories()
a un destino ejecutable si necesita establecer directorios de inclusión donde se encuentran los archivos de encabezado que usan esos ejecutables (por ejemplo: Boost :: Program_options, si lo usa para analizar argumentos en sumain()
función) . Probablemente usaría laPRIVATE
palabra clave en este caso, ya que estos archivos son necesarios para compilar el ejecutable en sí. Sin embargo, no sé si hay algún uso paraINTERFACE
oPUBLIC
en un ejecutable.De la documentación: http://www.cmake.org/cmake/help/v3.0/command/target_include_directories.html
Para reformular la documentación con mis propias palabras:
fuente