CMake: разница между ${} и "${}"
Какая разница в cmake между чем-то вроде:
set(any_new_var ${old_var})
а также
set(any_new_var "${old_var}")
Есть ли важное отличие? Когда я должен использовать ту или иную форму?
Например, я пытаюсь с помощью следующего мини-теста
# test.cmake
# Variable 'a' isn't defined.
set(hola "${a}")
# message(${hola})
message("${hola}")
Вывод этого мини-теста (cmake -P test.cmake) представляет собой пустую строку (потому что "a" не определено). Если я раскомментирую первое сообщение, cmake выдаст сообщение об ошибке:
CMake Error at prueba.cmake:6 (message):
message called with incorrect number of arguments
Почему во втором случае это не бросок и ошибка, а пустая строка?
1 ответ
В CMake строки можно интерпретировать как списки. Правило простое: для формирования списка разбейте строку на точку с запятой. Например, строковое значение one;two;three
можно рассматривать как список из трех элементов: one
, two
, а также three
,
Чтобы вызвать команду, вы пишете имя команды и несколько слов в скобках. Однако эти слова не соответствуют аргументам, которые команда получает в формате один к одному. Каждое слово становится нулем или более аргументов, и все аргументы объединяются вместе. Если слово не заключено в кавычки, оно рассматривается как список и расширяется до нескольких аргументов. Процитированное слово всегда становится единственным аргументом.
Например, предположим, что X
связан с one;two;three
, Y
привязан к пустой строке, и Z
связан с foo
, В следующем вызове команды есть три слова, но команда получает четыре аргумента:
some_command(${X} ${Y} ${Z})
# The command receives four arguments:
# 1. one
# 2. two
# 3. three
# 4. foo
Если бы мы цитировали слова, команда получила бы три аргумента:
some_command("${X}" "${Y}" "${Z}")
# The command receives three arguments:
# 1. one;two;three
# 2. (the empty list)
# 3. foo
Вернемся к исходному вопросу: message
Команда может получить различное количество аргументов. Он принимает все свои аргументы, объединяет их в одну строку и затем печатает эту строку. Однако по неизвестной причине он не принимает нулевые аргументы.
Поведение message
Имеет несколько аргументов, не очень полезно, поэтому вы склонны использовать один аргумент в кавычках:
set(SOURCES foo.c hoo.h)
message(${SOURCES}) # prints foo.cfoo.h
message("${SOURCES}") # prints foo.c;foo.h
Кроме того, когда set
Получив несколько аргументов, он строит строку аргументов, разделенных точкой с запятой. Переменная затем устанавливается на эту строку.