Я спрашиваю это как напоминание себе в следующий раз, когда я использую CMake. Он никогда не прилипает, и результаты Google не очень хороши.
Какой синтаксис для установки и использования переменных в CMake?
При написании сценариев CMake нужно много знать о синтаксисе и о том, как использовать переменные в CMake.
Строки, использующие set()
:
set(MyString "Some Text")
set(MyStringWithVar "Some other Text: ${MyString}")
set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")
Или с string()
:
string(APPEND MyStringWithContent " ${MyString}")
Списки, использующие set()
:
set(MyList "a" "b" "c")
set(MyList ${MyList} "d")
Или лучше с list()
:
list(APPEND MyList "a" "b" "c")
list(APPEND MyList "d")
Списки имен файлов:
set(MySourcesList "File.name" "File with Space.name")
list(APPEND MySourcesList "File.name" "File with Space.name")
add_excutable(MyExeTarget ${MySourcesList})
set()
Commandstring()
Commandlist()
CommandСначала есть «Нормальные переменные» и вещи, которые вы должны знать об их области действия:
CMakeLists.txt
они установлены в и все , называется оттуда ( add_subdirectory()
, include()
, macro()
и function()
).add_subdirectory()
И function()
команды являются особенными, потому что они открывают, свои собственные рамки.
set(...)
там видны только там, и они копируют все нормальные переменные уровня области действия, из которого они вызываются (называемые родительской областью действия).set(... PARENT_SCOPE)
function(xyz _resultVar)
установкаset(${_resultVar} 1 PARENT_SCOPE)
include()
или macro()
скрипты, изменяет переменные непосредственно в области, откуда они вызываются.Во-вторых, это «Кэш глобальных переменных». Что нужно знать о кеше:
CMakeCache.txt
файле в вашем каталоге двоичного вывода.Значения в Cache могут быть изменены в приложении с графическим интерфейсом CMake перед их генерацией. Поэтому они - по сравнению с обычными переменными - имеют a type
и a docstring
. Я обычно не использую графический интерфейс, поэтому я использую set(... CACHE INTERNAL "")
для установки своих глобальных и постоянных значений.
Обратите внимание, что INTERNAL
тип переменной кеша подразумеваетFORCE
В сценарии CMake вы можете изменять существующие записи в кэше, только если используете set(... CACHE ... FORCE)
синтаксис. Это поведение используется, например, самим CMake, потому что обычно оно не заставляет сами записи Cache, и поэтому вы можете предварительно определить его с другим значением.
cmake -D var:type=value
, просто cmake -D var=value
или с помощью cmake -C CMakeInitialCache.cmake
.unset(... CACHE)
.Кэш является глобальным, и вы можете установить его практически в любом месте ваших сценариев CMake. Но я бы порекомендовал вам дважды подумать о том, где использовать переменные Cache (они глобальные и постоянные). Я обычно предпочитаю set_property(GLOBAL PROPERTY ...)
и set_property(GLOBAL APPEND PROPERTY ...)
синтаксис , чтобы определить свои собственные , не стойкие к глобальным переменным.
Чтобы избежать ошибок, вы должны знать следующее о переменных:
find_...
команды - в случае успеха - напишете свои результаты в виде кэшированных переменных « так что ни один звонок не будет снова искать»set(MyVar a b c)
есть "a;b;c"
и set(MyVar "a b c")
есть"a b c"
list()
команду для обработки списковfunctions()
вместо, macros()
потому что вы не хотите, чтобы ваши локальные переменные отображались в родительской области видимости.project()
и enable_language()
вызовами. Поэтому может быть важно установить некоторые переменные перед использованием этих команд.Иногда помогают только отладочные переменные. Следующее может помочь вам:
printf
стиль отладки с помощью message()
команды. Есть также некоторые готовые к использованию модули, поставляемые с самим CMake: CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmakeCMakeCache.txt
файл в вашей директории двоичного вывода. Этот файл создается даже в случае сбоя фактической генерации вашей среды создания.cmake --trace ...
чтобы увидеть полный процесс разбора CMake. Это своего рода последний резерв, потому что он генерирует много продукции.$ENV{...}
и записывать set(ENV{...} ...)
переменные окружения$<...>
оцениваются только тогда, когда генератор CMake записывает среду make (это сравнение с обычными переменными, которые заменяются парсером "на месте")${${...}}
вы можете дать имена переменных в переменной и ссылаться на ее содержимое.if()
Команду)
if(MyVariable)
вы можете напрямую проверить переменную на true / false (здесь нет необходимости для включения ${...}
)1
, ON
, YES
, TRUE
, Y
, или ненулевое число.0
, OFF
, NO
, FALSE
, N
, IGNORE
, NOTFOUND
, пустая строка, или заканчивается в суффиксе -NOTFOUND
.if(MSVC)
, но он может сбивать с толку тех, кто не знает этого ярлыка синтаксиса.set(CMAKE_${lang}_COMPILER ...)
if()
командах. Вот пример, где CMAKE_CXX_COMPILER_ID
есть "MSVC"
и MSVC
есть "1"
:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
верно, потому что это оценивает if("1" STREQUAL "1")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
ложно, потому что это оценивает if("MSVC" STREQUAL "1")
if(MSVC)
cmake_policy(SET CMP0054 NEW)
«интерпретировать if()
аргументы как переменные или ключевые слова без кавычек».option()
команда
ON
или, OFF
и они допускают некоторую специальную обработку, например, зависимостиoption
виду , не путайте с set
командой. Присвоенное значение на option
самом деле является только «начальным значением» (переданным один раз в кэш на первом этапе настройки) и впоследствии должно быть изменено пользователем через графический интерфейс CMake .
if ("${MyString}" ...)
я вижу предупреждение:Policy CMP0054 is not set: Only interpret if() arguments as variables or keywords when unquoted
. См. Например, Build 367 . Любые идеи?${MyString}
приводит к куче ошибок для «если даны аргументы ...», таких как ошибка CMake рядом с if: «если даны аргументы», за которыми следуют паратезы, «НЕ», «РАВНЫЕ» и тому подобное .MyString
оно содержит имя переменной, которая затем будет разыменована . Я считаю, что никто не хочет такогоOLD
поведения. Таким образом , с моей точки зрения его абсолютно безопасным и обратную совместимость просто установить политику ,CMP0054
чтобыNEW
(см обсуждение здесь ).if (MyString ...)
(если ваш код дает предупреждение).${MyString}
и заменили егоMyString
(или я думаю, что мы удалили их все). До сих пор нет радости: Сборка 372 . Дерьмо даже не исходит из нашего кода. Похоже, что идет от CMake. Строка 283 естьif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
.Вот пара основных примеров, чтобы начать быстро и грязно.
Одна переменная элемента
Установить переменную:
Используйте переменную:
Многоэлементная переменная (т.е. список)
Установить переменную:
Используйте переменную:
CMake документы по переменным
источник
$ENV{FOO}
для использования, гдеFOO
выбирается из переменной среды. в противном случае используйте as${FOO}
, гдеFOO
находится некоторая другая переменная. Для настройкиSET(FOO "foo")
будет использоваться в CMake.источник