Imagine el siguiente escenario: el Proyecto A es una biblioteca compartida que tiene varias dependencias (LibA, LibB y LibC). El proyecto B es un ejecutable que depende del proyecto A y, por lo tanto, también requiere todas las dependencias del proyecto A para poder construir.
Además, ambos proyectos se construyen usando CMake, y el Proyecto A no debería necesitar ser instalado (a través del destino 'instalar') para que el Proyecto B lo use, ya que esto puede convertirse en una molestia para los desarrolladores.
¿Cuál es la mejor manera de resolver estas dependencias usando CMake? La solución ideal sería lo más simple posible (aunque no más simple) y requeriría un mantenimiento mínimo.
Respuestas:
Fácil. Aquí está el ejemplo de la parte superior de mi cabeza:
El nivel superior
CMakeLists.txt
:CMakeLists.txt
encomponents/B
:CMakeLists.txt
encomponents/C
:CMakeLists.txt
encomponents/A
:CMakeLists.txt
encomponents/Executable
:Para que quede claro, aquí está la estructura de árbol de origen correspondiente:
Hay muchos puntos en los que esto podría ajustarse / personalizarse o cambiarse para satisfacer ciertas necesidades, pero esto al menos debería ayudarlo a comenzar.
NOTA: He empleado con éxito esta estructura en varios proyectos de tamaño mediano y grande.
fuente
set(...INCLUDE_DIRS
y una vez parainclude_directories()
), que encuentro difícil de mantener (siempre recordando agregar una nueva dependencia de inclusión en dos lugares). Podrías interrogarlos conget_property(...PROPERTY INCLUDE_DIRECTORIES)
.Alexander Shukaev tuvo un gran comienzo, pero hay varias cosas que podrían hacerse mejor:
target_include_directories
. Sin embargo, probablemente ni siquiera necesite hacer eso si usa los destinos importados.Utilice los objetivos importados. Ejemplo de impulso:
Esto se encarga de los directorios de inclusión, bibliotecas, etc. Si usó Boost en sus encabezados en B, entonces en lugar de PRIVATE, use PUBLIC, y estas dependencias se agregarán transitivamente a lo que dependa de B.
No utilice el archivo globular (a menos que utilice 3.12). Hasta hace muy poco, el almacenamiento global de archivos solo funcionaba durante el tiempo de configuración, por lo que si agrega archivos y compila, no podrá detectar los cambios hasta que regenere explícitamente el proyecto. Sin embargo, si enumera los archivos directamente e intenta compilar, debería reconocer que la configuración está desactualizada y regenerarse automáticamente en el paso de compilación.
Hay una buena charla aquí (YouTube): C ++ Now 2017: Daniel Pfeifer "Effective CMake"
Lo que cubre una idea de administrador de paquetes que permite que su CMake de nivel raíz funcione con
find_package
ORsubdirectory
, sin embargo, he estado tratando de adoptar la ideología de esto y estoy teniendo grandes problemasfind_package
para usarlo para todo y tener una estructura de directorio como la suya.fuente
Esto también se puede hacer usando el
Cache
mecanismo CMake para lograr lo mismo (es decir, compartir variables específicas del proyecto):Consulte la pregunta de Stack Overflow Cómo compartir variables entre diferentes archivos CMake .
fuente