trap tag reggaeton preguntas novio las canciones build cmake modularity

build - preguntas - tag del reggaeton



CMake: ¿cuál es la mejor manera de crear múltiples subproyectos(opcionales)? (6)

Imagina un proyecto global con varios componentes:

  • BASIC
  • io
  • web
  • app-a
  • app-b
  • app-c

Ahora, digamos que web depende de io que depende de Basic, y todas esas cosas están en un solo repositorio y tienen un CMakeLists.txt para construirlas como bibliotecas compartidas.

¿Cómo debo configurar las cosas para poder construir las tres aplicaciones, si cada una de ellas es opcional y puede que no esté presente en el momento de la compilación?

Una idea es tener un directorio de "aplicaciones" vacío en el repositorio principal y podemos clonar cualquier repositorio de aplicaciones que queramos. Nuestro archivo principal CMakeLists.txt puede usar GLOB para encontrar todos los directorios de aplicaciones y compilarlos (sin saber de antemano cuántos habrá). Los problemas con este enfoque incluyen:

  • Al parecer, CMake no vuelve a aparecer cuando solo dices make , así que si agregas una nueva aplicación, debes ejecutar cmake nuevamente.
  • Impone una estructura específica a la persona que realiza la construcción.
  • No es obvio cómo se podrían hacer dos clones de una sola aplicación y compilarlos por separado contra la misma compilación de la biblioteca.

El concepto general es como un proyecto tradicional de CMake recursivo, pero donde los módulos de nivel inferior no necesariamente saben de antemano qué módulos de nivel superior los usarán. Sin embargo, no quiero que el usuario instale las bibliotecas de nivel inferior en una ubicación fija (por ejemplo, /usr/local/lib ). Sin embargo, sí quiero una sola invocación de make para notar las dependencias cambiadas en todo el proyecto, de modo que si estoy creando una aplicación pero he cambiado una de las bibliotecas de bajo nivel, todo se volverá a compilar adecuadamente.


La herramienta CMake BASIS proporciona utilidades en las que puede crear módulos independientes de un proyecto y habilitarlos e inhabilitarlos selectivamente con el comando ccmake.

Revelación completa: soy un desarrollador para el proyecto.


Mi primer pensamiento fue utilizar la función de destino de importación / exportación CMake.

Tenga un CMakeLists.txt para basic , io y web y un CMakeLists.txt que haga referencia a esos. Luego, podría usar la función de exportación de CMake para exportar esos objetivos y los proyectos de la aplicación podrían importar los objetivos de CMake.

Cuando construye el proyecto de la biblioteca primero, los proyectos de la aplicación deben poder encontrar las bibliotecas compiladas automáticamente (sin que las bibliotecas tengan que instalarse en /usr/local/lib ) de lo contrario, siempre se puede configurar la variable CMake adecuada para indicar el directorio correcto .

Al hacerlo de esta manera, una make en el proyecto de la aplicación no hará una make en el proyecto de la biblioteca, tendría que encargarse de esto usted mismo.



Tener múltiples CMakeLists.txt.

Muchos proyectos de código abierto toman este enfoque (LibOpenJPEG, LibPNG, poppler & etc). Echa un vistazo a su CMakeLists.txt para descubrir cómo lo han hecho.

Básicamente, lo que le permite simplemente alternar las características según sea necesario.


Terminé haciendo lo que describí en mi pregunta, que es registrar un directorio vacío (que contiene un archivo .gitignore que ignora todo) y decirle a CMake a GLOB cualquier directorio (que el usuario coloca allí). Entonces solo puedo decir cmake myrootdir y encuentra todos los componentes. Esto funciona más o menos bien. Sin embargo, tiene algunos inconvenientes secundarios, como el hecho de que algunas herramientas de terceros como BuildBot esperan una estructura de proyecto más tradicional que hace que la integración de otras herramientas con este tipo de arreglo sea un poco más de trabajo.


Veo dos enfoques adicionales. Uno es simplemente tener los submódulos básicos, io y web de cada aplicación. Sí, hay duplicación de código y espacio de disco desperdiciado, pero es muy simple de implementar y garantiza que las diferentes configuraciones del compilador para cada aplicación no interfieran entre sí en las bibliotecas compartidas. Supongo que esto hace que las bibliotecas no se compartan más, pero tal vez eso no tenga que ser un gran problema en 2011. La memoria RAM y el disco se han abaratado, pero el tiempo de ingeniería no lo es, y compartir la fuente es posiblemente más portátil que compartir binarios

Otro enfoque es tener el diseño especificado en la pregunta y tener archivos CMakeLists.txt en cada subdirectorio. Los archivos CMakeLists.txt en basic, io y web generan bibliotecas compartidas independientes. Los archivos CMakeLists.txt en cada directorio de aplicaciones se extraen de cada biblioteca compartida con el comando add_subdirectory (). Luego, puede desplegar todos los directorios de la biblioteca y las aplicaciones que desee e iniciar la compilación desde cada directorio de aplicaciones.