library - create cmakelists txt
¿Cuál es la sintaxis de CMake para establecer y usar variables? (3)
Al escribir scripts de CMake, hay mucho que necesita saber sobre la sintaxis y cómo usar variables en CMake.
La sintaxis
Cadenas usando
set()
:
-
set(MyString "Some Text")
-
set(MyStringWithVar "Some other Text: ${MyString}")
-
set(MyStringWithQuot "Some quote: /"${MyStringWithVar}/"")
O con una
string()
:
-
string(APPEND MyStringWithContent " ${MyString}")
Listas que usan
set()
:
-
set(MyList "a" "b" "c")
-
set(MyList ${MyList} "d")
O mejor con
list()
:
-
list(APPEND MyList "a" "b" "c")
-
list(APPEND MyList "d")
Listas de nombres de archivo:
-
set(MySourcesList "File.name" "File with Space.name")
-
list(APPEND MySourcesList "File.name" "File with Space.name")
-
add_excutable(MyExeTarget ${MySourcesList})
La documentación
- CMake / Sintaxis del lenguaje
- CMake: cadenas de listas de variables
- CMake: variables útiles
-
Comando CMake
set()
-
Comando CMake
string()
-
Comando CMake
list()
- Cmake: expresiones del generador
El alcance o "¿Qué valor tiene mi variable?"
Primero están las "Variables normales" y las cosas que necesita saber sobre su alcance:
-
Las variables normales son visibles para el
CMakeLists.txt
que se establecen y todo lo que se llama desde allí (add_subdirectory()
,include()
,macro()
yfunction()
). -
Los
add_subdirectory()
yfunction()
son especiales, porque abren su propio ámbito.-
Las variables de significado
set(...)
solo son visibles allí y hacen una copia de todas las variables normales del nivel de alcance desde el que se llaman (llamado alcance primario). -
Entonces, si está en un subdirectorio o una función, puede modificar una variable ya existente en el ámbito primario con
set(... PARENT_SCOPE)
-
Puede utilizar esto, por ejemplo, en funciones pasando el nombre de la variable como un parámetro de función.
Un ejemplo sería la
function(xyz _resultVar)
es setset(${_resultVar} 1 PARENT_SCOPE)
-
Las variables de significado
-
Por otro lado, todo lo que establezca en los scripts
include()
omacro()
modificará las variables directamente en el ámbito de donde se llaman.
En segundo lugar está el "Caché de variables globales". Cosas que debes saber sobre el caché:
- Si no se define una variable normal con el nombre dado en el ámbito actual, CMake buscará una entrada de caché coincidente.
-
Los valores de caché se almacenan en el archivo
CMakeCache.txt
en su directorio de salida binario. -
Los valores en la caché se pueden modificar en la aplicación GUI de CMake antes de que se generen. Por lo tanto, en comparación con las variables normales, tienen un
type
y unadocstring
. Normalmente no uso la GUI, así que usoset(... CACHE INTERNAL "")
para establecer mis valores globales y persistentes.Tenga en cuenta que el tipo de variable de caché
INTERNAL
implicaFORCE
-
En un script CMake, solo puede cambiar las entradas de caché existentes si utiliza la sintaxis
set(... CACHE ... FORCE)
. Este comportamiento es utilizado, por ejemplo, por CMake mismo, porque normalmente no fuerza las entradas de caché y, por lo tanto, puede predefinirlo con otro valor. -
Puede usar la línea de comando para establecer entradas en la caché con la sintaxis
cmake -D var:type=value
, solocmake -D var=value
o concmake -C CMakeInitialCache.cmake
. -
Puede
unset
entradas en la caché con
unset(... CACHE)
.
La memoria caché es global y puede configurarlos prácticamente en cualquier lugar en sus scripts CMake.
Pero le recomendaría que lo piense dos veces antes de utilizar las variables de caché (son globales y persistentes).
Normalmente prefiero la
set_property(GLOBAL PROPERTY ...)
y
set_property(GLOBAL APPEND PROPERTY ...)
para definir mis propias variables globales no persistentes.
Errores variables y "¿Cómo depurar cambios variables?"
Para evitar dificultades, debe saber lo siguiente acerca de las variables:
- Las variables locales ocultan las variables en caché si ambas tienen el mismo nombre
-
Los comandos
find_...
, si tienen éxito, escriben sus resultados como variables en caché "para que ninguna llamada vuelva a buscar" -
Las listas en CMake son solo cadenas con delimitadores de punto
y
coma
y, por lo tanto, las comillas son importantes
-
set(MyVar abc)
es"a;b;c"
yset(MyVar "abc")
es"abc"
- La recomendación es que siempre use comillas con la única excepción cuando desee dar una lista como lista
-
Generalmente prefiero el comando
list()
para manejar listas
-
-
Todo el problema de alcance descrito anteriormente.
Se recomienda especialmente utilizar
functions()
lugar demacros()
porque no desea que sus variables locales se muestren en el ámbito primario. -
Muchas variables utilizadas por CMake se configuran con las llamadas
project()
yenable_language()
. Por lo tanto, podría ser importante establecer algunas variables antes de usar esos comandos. -
Las variables de entorno pueden diferir de dónde CMake generó el entorno de creación y cuándo se utilizan los archivos de creación.
- Un cambio en una variable de entorno no reactiva el proceso de generación.
- Especialmente un entorno IDE generado puede diferir de su línea de comando, por lo que se recomienda transferir sus variables de entorno a algo que está en caché.
A veces solo ayuda la depuración de variables. Lo siguiente puede ayudarlo:
-
Simplemente use el viejo estilo de depuración
printf
usando el comandomessage()
. También hay algunos módulos listos para usar que se envían con CMake: CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmake -
Busque en el archivo
CMakeCache.txt
en su directorio de salida binario. Este archivo incluso se genera si falla la generación real de su entorno de creación. - Use variable_watch() para ver dónde se leen / escriben / eliminan sus variables.
- Mire las propiedades del directorio CACHE_VARIABLES y CACHE_VARIABLES
-
Llame a
cmake --trace ...
para ver el proceso completo de análisis de CMake. Esa es una especie de última reserva, ya que genera mucha salida.
Sintaxis Especial
-
Variables de entorno
-
Puede leer
$ENV{...}
y escribir variables de entorno delset(ENV{...} ...)
-
Puede leer
-
Expresiones de generador
-
Las expresiones de generador
$<...>
solo se evalúan cuando el generador de CMake escribe el entorno de creación (en comparación con las variables normales que se reemplazan "en el lugar" por el analizador) - Muy útil, por ejemplo, en las líneas de comando del compilador / enlazador y en entornos de configuración múltiple
-
Las expresiones de generador
-
Referencias
-
Con
${${...}}
puede dar nombres de variables en una variable y hacer referencia a su contenido. - A menudo se usa al dar un nombre de variable como parámetro de función / macro.
-
Con
-
Valores constantes (ver comando
if()
)-
Con
if(MyVariable)
puede verificar directamente una variable para verdadero / falso (no es necesario aquí para el adjunto${...}
) -
Verdadero si la constante es
1
,ON
,YES
,TRUE
,Y
o un número distinto de cero. -
Falso si la constante es
0
,OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
, la cadena vacía o termina en el sufijo-NOTFOUND
. -
Esta sintaxis a menudo se usa para algo como
if(MSVC)
, pero puede ser confusa para alguien que no conoce este atajo de sintaxis.
-
Con
-
Sustituciones recursivas
-
Puede construir nombres de variables usando variables.
Después de que CMake haya sustituido las variables, verificará nuevamente si el resultado es una variable en sí misma.
Esta es una característica muy poderosa utilizada en CMake, por ejemplo, como una especie de
set(CMAKE_${lang}_COMPILER ...)
plantillasset(CMAKE_${lang}_COMPILER ...)
-
Pero
tenga en cuenta que
esto puede causarle dolor de cabeza en los comandos
if()
. Aquí hay un ejemplo dondeCMAKE_CXX_COMPILER_ID
es"MSVC"
yMSVC
es"1"
:-
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
es verdadero, porque se evalúa comoif("1" STREQUAL "1")
-
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
es falso, porque se evalúa comoif("MSVC" STREQUAL "1")
-
Entonces, la mejor solución aquí sería, ver arriba, verificar directamente
if(MSVC)
-
-
La buena noticia es que esto se solucionó en CMake 3.1 con la introducción de la
política CMP0054
.
Recomendaría siempre configurar
cmake_policy(SET CMP0054 NEW)
para "interpretar solo los argumentosif()
como variables o palabras clave cuando no están entre comillas".
-
Puede construir nombres de variables usando variables.
Después de que CMake haya sustituido las variables, verificará nuevamente si el resultado es una variable en sí misma.
Esta es una característica muy poderosa utilizada en CMake, por ejemplo, como una especie de
-
El comando
option()
-
Principalmente solo cadenas en caché que solo pueden estar
ON
oOFF
y permiten un manejo especial como, por ejemplo, dependencies -
Pero
tenga en cuenta
, no confunda la
option
con el comandoset
. El valor dado a laoption
es realmente solo el "valor inicial" (transferido una vez al caché durante el primer paso de configuración) y luego debe ser modificado por el usuario a través de la GUI de CMake .
-
Principalmente solo cadenas en caché que solo pueden estar
Referencias
Me lo pido como un recordatorio la próxima vez que use CMake. Nunca se pega, y los resultados de Google no son excelentes.
¿Cuál es la sintaxis para establecer y usar variables en CMake?
Aquí hay un par de ejemplos básicos para comenzar rápido y sucio.
Una variable de elemento
Establecer variable:
SET(INSTALL_ETC_DIR "etc")
Usar variable:
SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
Variable de elementos múltiples (es decir, lista)
Establecer variable:
SET(PROGRAM_SRCS
program.c
program_utils.c
a_lib.c
b_lib.c
config.c
)
Usar variable:
add_executable(program "${PROGRAM_SRCS}")
$ENV{FOO}
para uso, donde
FOO
se está recogiendo de la variable de entorno.
de lo contrario, use como
${FOO}
, donde
FOO
es alguna otra variable.
Para la configuración,
SET(FOO "foo")
se usaría en CMake.