descarga - cmake vs make
CMake comparar con una cadena vacĂa con STREQUAL fallido (1)
Siempre pienso que si quieres comparar dos cadenas (pero no variables) todo lo que necesitas hacer es citarlo así:
if("${A}" STREQUAL "some string")
pero ahora descubro que este código a veces se imprime, ¡ oops
!
cmake_minimum_required(VERSION 2.8)
if("d" STREQUAL "")
message("oops...")
endif()
¿Puede ser que sea un error (porque se imprime con Xcode , pero no con make )? ¿O hay algunas variables especiales?
- cmake: 2.8.12, 2.8.11.2
- xcode: 4.6.2, 5.0.1
Actualizar
Hay una string comandos sin problemas descritos:
string(COMPARE EQUAL "${A}" "" result)
if(result)
message("...")
endif()
Actualización 2
El comportamiento que esperaba implementado desde CMake 3.1.0 (ver CMP0054 ).
Salida de la test 3.0.2:
CMake version: 3.0.2
Quoted test
Surprise!
Unquoted test
Surprise!
Salida de la test 3.1.0:
CMake version: 3.1.0
Quoted test
OK
Unquoted test
Surprise!
Se encontró con un comportamiento bastante molesto de "no es un error, es una característica" de CMake. Como se explica en la documentación del comando if :
The if command was written very early in CMake''s history, predating the ${}
variable evaluation syntax, and for convenience evaluates variables named
by its arguments as shown in the above signatures.
Bueno, la conveniencia resultó ser un inconveniente. En su ejemplo, la cadena "d"
se trata como una variable llamada d
por el comando if
. Si la variable d
pasa a estar definida en la cadena vacía, la declaración del mensaje imprimirá "oops ...", por ejemplo:
set (d "")
if("d" STREQUAL "")
# this branch will be taken
message("oops...")
else()
message("fine")
endif()
Esto puede dar resultados sorprendentes para afirmaciones como
if("${A}" STREQUAL "some string")
porque puede haber una expansión doble no intencionada del primer argumento si la variable A
pasa a definirse en una cadena que también es el nombre de una variable CMake, por ejemplo:
set (A "d")
set (d "some string")
if("${A}" STREQUAL "some string")
# this branch will be taken
message("oops...")
else()
message("fine")
endif()
Posibles soluciones:
Puede agregar un carácter de sufijo a la cadena después de la expansión ${}
que evita que la sentencia if realice la evaluación automática:
set (A "d")
set (d "some string")
if("${A} " STREQUAL "some string ")
message("oops...")
else()
# this branch will be taken
message("fine")
endif()
No utilice la expansión ${}
:
set (A "d")
set (d "some string")
if(A STREQUAL "some string")
message("oops...")
else()
# this branch will be taken
message("fine")
endif()
Para evitar la evaluación involuntaria en el lado derecho de STREQUAL
use STREQUAL
con una expresión regular CMake :
if(A MATCHES "^value$")
...
endif()
Addendum: CMake 3.1 ya no hace expansiones dobles para los argumentos entre comillas. Ver la nueva política .