c++ cmake header-only

c++ - CMake: target_include_directories() imprime un error cuando intento agregar el directorio de origen o uno de sus subdirectorios



header-only (1)

Estoy escribiendo una biblioteca de C ++ (solo encabezado) y estoy usando CMake para generar mis archivos de proyecto y solución (Visual Studio). También estoy escribiendo una suite de prueba, que es parte del mismo proyecto CMake.

Mi problema ocurre cuando llamo a target_include_directories () en el destino que representa mi biblioteca de solo encabezado, de modo que los consumidores de mi biblioteca puedan encontrar sus archivos de encabezado. Recibo el siguiente mensaje de error (aunque la generación NO se ha cancelado).

CMake Error in CMakeLists.txt: Target "Fonts" INTERFACE_INCLUDE_DIRECTORIES property contains path: "D:/Projects/GPC/fonts/include" which is prefixed in the source directory.

(D: / Projects / GPC / Fonts es el directorio de nivel superior de mi proyecto de biblioteca. Por cierto, el problema sigue siendo si muevo mis archivos de encabezado al directorio superior.)

La línea ofensiva en mi CMakeLists.txt es esta (adaptada para simplificar):

target_include_directories(Fonts INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")

No entiendo lo que estoy haciendo mal. Sin target_include_directories (), el código de los proyectos de los consumidores simplemente no puede incluir mis archivos de encabezado (a menos que estén instalados, pero aún no he llegado a eso, y en cualquier caso quiero poder usar mi biblioteca desde su árbol de compilación) , sin instalación.)

Siento que me estoy perdiendo algo básico aquí; Sin embargo, he buscado durante horas sin encontrar una solución o explicación.


El origen del problema no es el comando target_include_directories , sino el intento de install un destino que tiene un directorio público o de interfaz incluido en la ruta de origen.

Si bien es perfectamente correcto y deseable usar rutas absolutas al crear la biblioteca desde cero, una biblioteca de terceros que obtenga una versión precompilada de esa biblioteca probablemente querrá usar una ruta de inclusión diferente. Después de todo, no desea que todos sus usuarios reflejen la estructura de directorios de su máquina de compilación, solo para terminar en la ruta de inclusión de la derecha.

El mecanismo de empaquetado de CMake proporciona soporte para estos dos casos de uso: puede extraer una biblioteca directamente desde el árbol de compilación (es decir, verificar el origen, compilarlo y apuntar find_package() al directorio), o desde un directorio de instalación (ejecute make INSTALL para copiar elementos incorporados al directorio de instalación y apunte find_package() a ese directorio). El último enfoque debe ser reubicable (es decir, yo construyo e instalo en mi máquina, le envío el directorio resultante y usted podrá usarlo en su máquina desde una estructura de directorio diferente), mientras que el primero no lo es.

Esta es una característica muy buena, pero debe tenerla en cuenta al configurar los directorios de inclusión. Citando el manual para target_include_directories :

Los requisitos de uso de los directorios de inclusión suelen diferir entre el árbol de compilación y el árbol de instalación. Las expresiones del generador BUILD_INTERFACE e INSTALL_INTERFACE se pueden usar para describir los requisitos de uso por separado según la ubicación de uso. Las rutas relativas se permiten dentro de la expresión INSTALL_INTERFACE y se interpretan en relación con el prefijo de instalación. Por ejemplo:

target_include_directories(mylib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib> $<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib )

Las expresiones del generador BUILD_INTERFACE e INSTALL_INTERFACE hacen toda la magia:

$<INSTALL_INTERFACE:...>

Contenido de ... cuando la propiedad se exporta utilizando install(EXPORT) , y de lo contrario se vacía.

$<BUILD_INTERFACE:...>

Contenido de ... cuando la propiedad se exporta mediante export() , o cuando el destino es usado por otro objetivo en el mismo sistema de compilación. Expande a la cadena vacía de lo contrario.