Cuándo citar variables?

Estoy escribiendo macros CMake por primera vez, y me cuesta entender cómo funcionan las variables. Más específicamente, ${a} parece tener un significado diferente a "${a}" .

Por ejemplo aquí: Pasar una lista a una macro cmake

No entiendo cuándo se supone que debo agregar citas, y cuáles son los principios subyacentes más grandes.

Dos principios de CMake debes tener en cuenta:

  1. CMake es un lenguaje de script y los argumentos se evalúan después de que las variables se expanden
  2. CMake diferencia entre cadenas normales y variables de lista (cadenas con delimitadores de punto y coma)

Ejemplos

  • set(_my_text "ABC") con el message("${_my_text}") daría ABC
  • set(_my_list ABC) con el message("${_my_list}") daría A;B;C
  • set(_my_list "A" "B" "C") con el message("${_my_list}") daría A;B;C
  • set(_my_list "A" "B" "C") con message(${_my_list}) daría ABC

Algunas reglas de oro

Hay algunas reglas generales que debe considerar:

  1. a) Cuando su variable contiene texto, especialmente uno que podría contener punto y coma, debe agregar comillas.

    Razonamiento : Un punto y coma es un delimitador para elementos de lista en CMake. Así que ponga citas alrededor de un texto que se supone que es uno (funciona en todas partes y para mí personalmente se ve mejor con el resaltado de syntax CMake)

    EDITAR: Gracias por la pista de @schieferstapel

    b) Para ser más precisos: un contenido variable con espacios que ya tenían comillas mantiene esas comillas (imagínese que forma parte del contenido de la variable). Esto funciona en todas partes también sin comillas (parámetros de función normales o definidos por el usuario) con la excepción prominente de las llamadas if() , donde CMake reinterpreta el contenido de las variables sin comillas después de la expansión de variables (ver regla 3 y política CMP0054: solo interpretar if() argumentos como variables o palabras clave cuando no se incluyen las comillas )

    Ejemplos:

    • set(_my_text "ABC") con el message(${_my_text}) también daría ABC
    • set(_my_text "A;B;C") con if (${_my_text} STREQUAL "A;B;C") daría if given arguments: "A" "B" "C" "STREQUAL" "A;B;C" Unknown arguments specified
  2. Si su variable contiene una lista, normalmente no agrega comillas.

    Razonamiento : si le da algo así como una lista de archivos a un comando CMake, normalmente espera una lista de cadenas y no una cadena que contenga una lista. La diferencia que puede ver, por ejemplo, en el comando foreach() acepta ITEMS o LISTS .

  3. if() declaraciones if() son un caso especial en el que normalmente ni siquiera pones los frenos.

    Razonamiento : una cadena podría – después de la expansión – evaluar de nuevo a un nombre de variable. Para evitar esto, se recomienda simplemente nombrar la variable cuyo contenido desea comparar (por ejemplo, if (_my_text STREQUAL "ABC") ).


Ejemplos de COMMAND

  • set(_my_text "ABC") con COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" haría
    • llame a cmake.exe -E echo "ABC" en VS / Windows
    • llame a cmake -E echo A\ B\ C en GCC / Ubuntu
    • da ABC
  • set(_my_text "ABC") con COMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM
    • llame a cmake.exe -E echo "ABC" en VS / Windows
    • llame a cmake -E echo "ABC" en GCC / Ubuntu
    • da ABC
  • set(_my_list ABC) con COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" haría
    • llame a cmake.exe -E echo A;B;C
    • dar A , B: command not found , C: command not found
  • set(_my_list ABC) con COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
    • llame a cmake.exe -E echo "A;B;C"
    • dar A;B;C
  • set(_my_list "A" "B" "C") con el COMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
    • llame a cmake.exe -E echo "A;B;C"
    • dar A;B;C
  • set(_my_list "A" "B" "C") con COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
    • llame a cmake.exe -E echo ABC
    • da ABC
  • set(_my_list "A + B" "=" "C") con COMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
    • llame a cmake.exe -E echo "A + B" = C
    • dar A + B = C

Algunas reglas prácticas con add_custom_target() / add_custom_command() / execute_process()

Hay algunas reglas generales que debe considerar cuando utiliza variables en las llamadas a COMMAND :

  1. a) Use comillas para los argumentos que contienen rutas de archivos (como el primer argumento que contiene el ejecutable).

    Razonamiento : podría contener espacios y podría ser reinterpretado como argumentos separados para la llamada COMMAND

    b) Ver arriba, también funciona si la variable set() incluía comillas.

  2. Use comillas solo si desea concatenar algo en un solo parámetro para pasarlo al ejecutable al que se llama.

    Razonamiento : una variable podría contener una lista de parámetros que, al usar comillas, no se extraerán correctamente (punto y coma en lugar de espacios)

  3. Siempre agregue la opción VERBATIM con add_custom_target() / add_custom_command()

    Razonamiento : de lo contrario, el comportamiento multiplataforma no está definido y podría obtener sorpresas con las cadenas entrecomilladas.

Referencias

  • CMake: diferencia entre $ {} y “$ {}”
  • ¿Cuál es la syntax de CMake para establecer y usar variables?
  • Bucle sobre una lista de cuerdas
  • CMake se compara con la cadena vacía con STREQUAL failed