¿Cmake es variable recursivo?

Estoy tratando de modificar los indicadores del comstackdor para todos los directorios debajo de un cierto directorio (es decir, para todos los subdirectorios de directorios actuales y todos sus subdirectorios recursivamente). Así que encontré aquí hay dos formas:

add_directory(dir1) # ... add_directory(dirN) add_compile_options(flag1 flag2 ...) # or for CMake versions < 3.0 to do something more like: set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} flag1 flag2 ...") 

La página man para add_compile_options es muy clara al indicar que el efecto será “directorio actual y abajo” (que es lo que quiero) pero para set(CMAKE_CXX_FLAGS ...) no estoy tan seguro.

¿Cmake es variable recursivo?

La respuesta corta es que cada subdirectorio tiene su propio ámbito de variable inicializado con una copia de los valores de variable actuales en el momento de la llamada add_subdirectory() .

Para obtener una respuesta larga, consulte ¿Cuál es la syntax de CMake para establecer y usar variables?

Directory & Target Properties vs (Global) Variables

Existe una diferencia entre cómo add_compile_options() y CMAKE_CXX_FLAGS :

  • Todo lo que especifique con add_compile_options() se agrega a la propiedad de directorio COMPILE_OPTIONS . A continuación, “esta propiedad se utiliza para inicializar la propiedad de destino COMPILE_OPTIONS cuando se crea un destino” con add_library() o add_executable() .

    Y el estado actual de las propiedades del directorio se usa para inicializar las propiedades del subdirectorio cuando el analizador llega a una llamada add_subdirectory() .

  • CMAKE_CXX_FLAGS es una variable global en caché. Puede extender / sobreescribirlo definiendo una variable con ámbito de directorio local (ocultando el que está en caché global).

    El contexto de esas variables se copia en un ámbito de add_subdirectory() en add_subdirectory() (propagándose a subdirectorios).

    Y CMake busca su valor al final de cada archivo CMakeLists.txt y lo aplica a todos los destinos en el mismo CMakeLists.txt (lo que permite declaraciones tardías, consulte también Fórmula completa y Código de prueba a continuación).

  • Entonces, para las versiones de CMake <3.0, el equivalente a add_compile_options() era add_definitions() . La funcionalidad todavía está allí, pero fue extraño mezclar definiciones con opciones de comstackción. Entonces se inventó add_compile_options() .

La Generador-Fórmula completa para banderas de comstackción

Está en el código de CMake (vea cmCommonTargetGenerator::GetFlags() , cmLocalGenerator::AddCompileOptions() y cmLocalGenerator::AddLanguageFlags() ).

Este ejemplo muestra una biblioteca de configuración de comstackción DEBUG sin exportaciones, sin tener en cuenta las banderas basadas en características o algo así como CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES o CMAKE_QUOTE_INCLUDE_PATHS :

  CMAKE_CXX_FLAGS // as set at the end of target's CMakeLists.txt + CMAKE_CXX_FLAGS_DEBUG + Include Directories // pefixed with CMAKE_INCLUDE_FLAG_CXX/CMAKE_INCLUDE_SYSTEM_FLAG_CXX (CMAKE_INCLUDE_CURRENT_DIR) ? + CMAKE_CURRENT_SOURCE_DIR + CMAKE_CURRENT_BINARY_DIR + CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES + Target[INCLUDE_DIRECTORIES] + DependingTargets[INTERFACE_INCLUDE_DIRECTORIES] + Define Flags // compiler flags given with add_definitions() + Target[COMPILE_FLAGS] // deprecated - Filtered by CMAKE_CXX_FLAG_REGEX + Target[COMPILE_OPTIONS] + DependingTargets[INTERFACE_COMPILE_OPTIONS] 

Código de prueba

Para una mejor comprensión aquí está mi código para probar las opciones del comstackdor y los resultados que obtengo:

Nota : Normalmente usaría add_definitions() y target_compile_definitions() lugar de add_compile_options() y target_compile_options() para establecer las definiciones del comstackdor, pero para demostrar la propagación de las opciones del comstackdor I (mis-) usadas -D flags.

CMakeLists.txt

 cmake_minimum_required(VERSION 3.0) project(CxxFlagsTest) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCXX_FLAG") add_compile_options("-DCOMPILE_OPTION") add_subdirectory(lib) file(WRITE main.cpp "int main() { return 0; }") add_executable(main main.cpp) target_link_libraries(main lib) target_compile_options(main PRIVATE "-DMAIN_COMPILE_OPTION") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLATE_CXX_FLAG") get_target_property(_main_compile_options main COMPILE_OPTIONS) message(STATUS "main COMPILE_OPTIONS: ${_main_compile_options}") get_directory_property(_root_compile_options COMPILE_OPTIONS) message(STATUS "root COMPILE_OPTIONS: ${_root_compile_options}") message(STATUS "root CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") 

lib / CMakeLists.txt

 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSUB_CXX_FLAG") add_compile_options("-DSUB_COMPILE_OPTION") file(WRITE lib.cpp "") add_library(lib lib.cpp) target_compile_options(lib PUBLIC "-DLIB_COMPILE_OPTION") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLATE_SUB_CXX_FLAG") get_target_property(_lib_compile_options lib COMPILE_OPTIONS) message(STATUS "lib COMPILE_OPTIONS: ${_lib_compile_options}") get_directory_property(_sub_compile_options COMPILE_OPTIONS) message(STATUS "sub COMPILE_OPTIONS: ${_sub_compile_options}") message(STATUS "sub CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") 

Daría lugar a los siguientes mensajes:

 -- lib COMPILE_OPTIONS: -DCOMPILE_OPTION;-DSUB_COMPILE_OPTION;-DLIB_COMPILE_OPTION -- sub COMPILE_OPTIONS: -DCOMPILE_OPTION;-DSUB_COMPILE_OPTION -- sub CMAKE_CXX_FLAGS: ... -DCXX_FLAG -DSUB_CXX_FLAG -DLATE_SUB_CXX_FLAG -- main COMPILE_OPTIONS: -DCOMPILE_OPTION;-DMAIN_COMPILE_OPTION -- root COMPILE_OPTIONS: -DCOMPILE_OPTION -- root CMAKE_CXX_FLAGS: ... -DCXX_FLAG -DLATE_CXX_FLAG 

Y se establecen las siguientes definiciones de preprocesador:

lib

 CXX_FLAG SUB_CXX_FLAG LATE_SUB_CXX_FLAG COMPILE_OPTION SUB_COMPILE_OPTION LIB_COMPILE_OPTION 

principal

 CXX_FLAG LATE_CXX_FLAG COMPILE_OPTION MAIN_COMPILE_OPTION LIB_COMPILE_OPTION 

Las partes interesantes aquí son las banderas LATE CXX y la opción de comstackción LIB propagó la biblioteca vinculada.

Referencias

  • cmake – Configuración del indicador del enlazador global (para todos los destinos en el directorio)
  • ¿Cuál es la syntax de CMake para establecer y usar variables?