Ответ 1
Два принципа CMake, которые вы должны иметь в виду:
- CMake - это script язык и аргументы оцениваются после расширения переменных
- CMake различает обычные строки и переменные списка (строки с разделителями с запятой)
<сильные > Примеры
-
set(_my_text "A B C")
сmessage("${_my_text}")
дастA B C
-
set(_my_list A B C)
сmessage("${_my_list}")
дастA;B;C
-
set(_my_list "A" "B" "C")
сmessage("${_my_list}")
дастA;B;C
-
set(_my_list "A" "B" "C")
сmessage(${_my_list})
дастABC
Некоторые правила большого пальца
Есть несколько правил, которые вы должны рассмотреть:
-
a) Когда ваша переменная содержит текст - особенно тот, который может содержать точки с запятой, вы должны добавить кавычки.
Рассуждение: точка с запятой является разделителем для элементов списка в CMake. Поэтому помещайте кавычки вокруг текста, который должен быть одним (он работает повсюду и для меня лично выглядит лучше с подсветкой синтаксиса CMake)
EDIT: Спасибо за подсказку @schieferstapel
b) Точнее: переменное содержимое с пробелами, у которых уже есть кавычки, сохраняет эти кавычки (представьте, что они становятся частью содержимого переменной). Это работает везде также без кавычек (обычные или пользовательские параметры функции) с заметным исключением вызовов
if()
, где CMake повторно интерпретирует содержимое некотируемых переменных после расширения переменной (см. Также правило № 3 и политика CMP0054: интерпретировать аргументыif()
как переменные или ключевые слова при некотировании)Примеры:
-
set(_my_text "A B C")
сmessage(${_my_text})
также дастA B C
-
set(_my_text "A;B;C")
сif (${_my_text} STREQUAL "A;B;C")
дастif given arguments: "A" "B" "C" "STREQUAL" "A;B;C" Unknown arguments specified
-
-
Если ваша переменная содержит список, вы обычно не добавляете кавычки.
Рассуждение: если вы передаете что-то вроде списка файлов команде CMake, то обычно ожидают список строк, а не одну строку, содержащую список. Разницу, которую вы можете видеть, например, в команде
Операторыforeach()
, принимающейITEMS
илиLISTS
. -
if()
- это особый случай, когда вы обычно не кладете фигурные скобки.Рассуждение: строка может - после расширения - снова оценивать имя переменной. Чтобы предотвратить это, рекомендуется просто указать переменную, содержимое которой вы хотите сравнить (например,
if (_my_text STREQUAL "A B C")
).
COMMAND
Примеры
-
set(_my_text "A B C")
сCOMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}"
будет- вызов
cmake.exe -E echo "A B C"
в VS/Windows - вызов
cmake -E echo A\ B\ C
в GCC/Ubuntu - дать
A B C
- вызов
-
set(_my_text "A B C")
сCOMMAND "${CMAKE_COMMAND}" -E echo "${_my_text}" VERBATIM
будет- вызов
cmake.exe -E echo "A B C"
в VS/Windows - вызов
cmake -E echo "A B C"
в GCC/Ubuntu - дать
A B C
- вызов
-
set(_my_list A B C)
сCOMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}"
будет- вызов
cmake.exe -E echo A;B;C
- введите
A
,B: command not found
,C: command not found
- вызов
-
set(_my_list A B C)
сCOMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
будет- вызов
cmake.exe -E echo "A;B;C"
- дать
A;B;C
- вызов
-
set(_my_list "A" "B" "C")
сCOMMAND "${CMAKE_COMMAND}" -E echo "${_my_list}" VERBATIM
будет- вызов
cmake.exe -E echo "A;B;C"
- дать
A;B;C
- вызов
-
set(_my_list "A" "B" "C")
сCOMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
будет- вызов
cmake.exe -E echo A B C
- дать
A B C
- вызов
-
set(_my_list "A + B" "=" "C")
сCOMMAND "${CMAKE_COMMAND}" -E echo ${_my_list} VERBATIM
будет- вызов
cmake.exe -E echo "A + B" = C
- дать
A + B = C
- вызов
Некоторые правила большого пальца с add_custom_target()
/add_custom_command()
/execute_process()
Есть несколько важных правил, которые следует учитывать при использовании переменных в вызовах COMMAND
:
-
a) Используйте кавычки для аргументов, содержащих пути к файлам (например, первый аргумент, содержащий сам исполняемый файл).
Рассуждение: оно может содержать пробелы и может быть переинтерпретировано как отдельные аргументы для вызова
COMMAND
b) См. выше, работает также, если переменная
set()
включила кавычки. -
Использовать кавычки только в том случае, если вы хотите объединить что-то в один параметр, который будет передан исполняемому, который вызывается.
Рассуждение: переменная может содержать список параметров, которые - при использовании кавычек - не будут правильно извлечены (точки с запятой вместо пробелов)
-
Всегда добавляйте параметр
VERBATIM
с помощьюadd_custom_target()
/add_custom_command()
Рассуждение: В противном случае кросс-платформенное поведение undefined, и вы можете получить сюрпризы с вашими кавычками.
Ссылки