c++ - guia - estructura preferida del proyecto cmake
qgis manual (1)
Me gustaría tener la siguiente estructura A -> B -> C
, donde:
-
C
es un código repetitivo, envoltorios para bibliotecas de terceros, código muy básico, etc. -
B
es las clases comunes, las funciones y las estructuras de datos específicas del dominio del proyecto. -
A
es el proyecto en sí.
Me gustaría facilitar el reutilizar C
o B(+C)
en el futuro en mis otros proyectos. Además, tengo los siguientes requisitos:
- Como los tres proyectos están en progreso, me gustaría tener la capacidad de construir
C
,C+B
yC+B+A
en una sola toma. - Preferiría la vinculación estática sobre la dinámica, de modo que
C
yC+B
serían bibliotecas estáticas, yC+B+A
sería el ejecutable - Me gustaría mantener las listas de cmake y los archivos de configuración simples y limpios. Los ejemplos que encontré en la wiki oficial y en Internet son bastante grandes y monstruosos.
- Sería genial si no fuera necesario cambiar más de un par de líneas si cambiara las ubicaciones de
A
,B
oC
en el sistema de archivos. - Todos estos tres componentes están usando google-test, pero no estoy seguro de si es importante para el diseño del proyecto.
Soy bastante nuevo para cmake y ni siquiera entiendo es mejor escribir XXXConfig.cmake
o FindXXX.cmake
archivos. Además, no estoy seguro, ¿cómo debo pasar las rutas relativas del subcomponente al componente padre usando X_INCLUDE_DIRS
?
Primero debo admitir que estoy de acuerdo con @Tsyvarev. Su entorno CMake debe ajustarse a sus procesos / flujo de trabajo y debe tener en cuenta el tamaño del proyecto y la estructura del equipo. O hablando en general, el entorno en el que se utilizará CMake. Y esto tiende a ser, de manera positiva, muy vivo.
Entonces, esta parte de su pregunta es difícil de responder y me concentraré en la parte técnica:
- CMake debe conocer la ubicación de las dependencias, relativa o absoluta, mediante
- tener un árbol fuente monolítico (el que ya no quieres)
- una ubicación de directorio común para includes / libraries / binaries
- obtener las rutas a través de archivos de configuración / definiciones de variables
- utilizando el registro o la instalación desde una base de datos proporcionada en el host
- Para mantener sus archivos CMake lo más simple posible, le recomiendo agrupar su código CMake en archivos dedicados separados:
- Prefiere los archivos de la cadena de herramientas sobre las declaraciones
if(SomeCompiler)
- Mueva partes de código comunes / repetitivas como cuerpos de
function()
en un archivo de inclusión de CMake compartido - Mueva partes de código específicas no específicas de destino a sus propios archivos de script (CMake)
- Prefiere los archivos de la cadena de herramientas sobre las declaraciones
Código de ejemplo
Como ha solicitado específicamente la variante find_package()
, utilice las bibliotecas Usar CMake en su proyecto CMake y las cosas enumeradas anteriormente:
MyCommonCode.cmake
cmake_policy(SET CMP0022 NEW)
function(my_export_target _target _include_dir)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Config.cmake"
"
include(/"/$/{CMAKE_CURRENT_LIST_DIR/}/${_target}Targets.cmake/")
set_property(
TARGET ${_target}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES /"${_include_dir}/"
)
"
)
export(
TARGETS ${_target}
FILE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Targets.cmake"
EXPORT_LINK_INTERFACE_LIBRARIES
)
export(PACKAGE ${_target})
endfunction(my_export_target)
C / CMakeLists.txt
include(MyCommonCode.cmake)
...
my_export_target(C "${CMAKE_CURRENT_SOURCE_DIR}/include")
B / CMakeLists.txt
include(MyCommonCode.cmake)
find_package(C REQUIRED)
...
target_link_libraries(B C)
my_export_target(B "${CMAKE_CURRENT_SOURCE_DIR}/include")
A / CMakeLists.txt
include(MyCommonCode.cmake)
find_package(B REQUIRED)
...
target_link_libraries(A B)
Esto mantiene separados los 3 entornos de compilación, solo compartiendo el archivo MyCommonCode.cmake
relativamente estático. Por lo tanto, en este enfoque hasta ahora no he cubierto su primer punto, pero recomendaría el uso de un script externo para encadenar / activar sus pasos de compilación para A / B / C.