if
Условно выполняет группу команд.
Синтаксис
if(<condition>) <commands> elseif(<condition>) # optional block, can be repeated <commands> else() # optional block <commands> endif()
Оценивает аргумент condition в предложении if в соответствии с синтаксисом синтаксиса условия, описанным ниже. Если результат — истина, то commands в блоке if выполняются. В противном случае обрабатываются опциональные блоки elseif. Наконец, если ни одно condition не является истинным, commands в опциональном блоке else выполняются.
В соответствии со старой практикой, команды else() и endif() допускают опциональный аргумент <condition>. Если он используется, он должен быть точной копией аргумента открывающей команды if.
Синтаксис условия
Следующий синтаксис применяется к аргументу condition предложений if, elseif и while().
Составные условия вычисляются в следующем порядке приоритетов:
- Скобки.
- Унарные тесты, такие как EXISTS, COMMAND и DEFINED.
- Бинарные тесты, такие как EQUAL, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL, STREQUAL, STRLESS, STRLESS_EQUAL, STRGREATER, STRGREATER_EQUAL, VERSION_EQUAL, VERSION_LESS, VERSION_LESS_EQUAL, VERSION_GREATER, VERSION_GREATER_EQUAL, PATH_EQUAL и MATCHES.
- Унарный логический оператор NOT.
- Бинарные логические операторы AND и OR слева направо без короткого замыкания.
Базовые выражения
-
if(<constant>) -
Истина, если константа —
1,ON,YES,TRUE,Y, или ненулевое число (включая числа с плавающей точкой). Ложь, если константа —0,OFF,NO,FALSE,N,IGNORE,NOTFOUND, пустая строка или оканчивается на суффикс-NOTFOUND. Имена булевых констант нечувствительны к регистру. Если аргумент не является одной из этих специфических констант, он обрабатывается как переменная или строка (см. Расширение переменных ниже).
-
if(<variable>) -
Истина, если задана переменная, определённая значением, которое не является ложной константой. Ложь в противном случае, в том числе если переменная не определена. Обратите внимание, что аргументы макросов не являются переменными. Переменные среды также нельзя тестировать таким образом, например,
if(ENV{some_var})всегда вычисляется как ложь.
-
if(<string>) -
Строка в кавычках всегда вычисляется как ложь, за исключением следующих случаев:
Логические операторы
-
if(NOT <condition>) -
Истина, если условие не истинно.
-
if(<cond1> AND <cond2>) -
Истина, если оба условия индивидуально считаются истинными.
-
if(<cond1> OR <cond2>) -
Истина, если хотя бы одно из условий индивидуально считается истинным.
-
if((condition) AND (condition OR (condition))) -
Условия в скобках сначала оцениваются, а затем остальное условие оценивается, как в других примерах. Если есть вложенные скобки, то самые внутренние оцениваются как часть условия, которое их содержит.
Проверки существования
-
if(COMMAND <command-name>) -
Истина, если данное имя — команда, макрос или функция, которые можно вызвать.
-
if(POLICY <policy-id>) -
Истина, если данное имя — существующая политика (в формате
CMP<NNNN>).
-
if(TARGET <target-name>) -
Истина, если данное имя — существующее логическое имя целевого объекта, созданное вызовом команды
add_executable(),add_library()илиadd_custom_target()(в любом каталоге).
-
if(TEST <test-name>) -
Добавлен в версии 3.3.
Истина, если данное имя — существующее имя теста, созданное командой
add_test().
-
if(DEFINED <name>|CACHE{<name>}|ENV{<name>}) -
Истина, если переменная, переменная кэша или переменная среды с заданным именем
<name>определена. Значение переменной не имеет значения. Обратите внимание на следующие замечания:- Аргументы макросов не являются переменными.
- Невозможно напрямую проверить, является ли
<name>переменной не из кэша. Выражениеif(DEFINED someName)вычисляется как истина, если существует либо переменная из кэша, либо переменная не из кэшаsomeName. В сравнении, выражениеif(DEFINED CACHE{someName})вычисляется как истина только если существует переменная из кэшаsomeName. Оба выражения нужно проверить, если нужно узнать, существует ли переменная не из кэша:if(DEFINED someName AND NOT DEFINED CACHE{someName}).
Добавлен в версии 3.14: Поддержка переменных
CACHE{<name>}.
-
if(<variable|string> IN_LIST <variable>) -
Добавлен в версии 3.3.
Истина, если данный элемент содержится в переменной списка с заданным именем.
Операции с файлами
-
if(EXISTS <path-to-file-or-directory>) -
Истина, если указанный файл или каталог существует и доступен для чтения. Поведение определено только для полных явных путей (начальный
~/не расширяется как домашний каталог и рассматривается как относительный путь). Разрешает символические ссылки, т.е. если указанный файл или каталог является символической ссылкой, возвращает истину, если целевой объект символической ссылки существует.Ложь, если заданный путь — пустая строка.
Примечание
Предпочтительнее использовать
if(IS_READABLE)для проверки доступности файла для чтения.if(EXISTS)может быть изменено в будущем на проверку только существования файла.
-
if(IS_READABLE <path-to-file-or-directory>) -
Добавлен в версии 3.29.
Истина, если указанный файл или каталог доступен для чтения. Поведение определено только для полных явных путей (начальный
~/не расширяется как домашний каталог и рассматривается как относительный путь). Разрешает символические ссылки, т.е. если указанный файл или каталог является символической ссылкой, возвращает истину, если целевой объект символической ссылки доступен для чтения.Ложь, если заданный путь — пустая строка.
-
if(IS_WRITABLE <path-to-file-or-directory>) -
Добавлен в версии 3.29.
Истина, если указанный файл или каталог доступен для записи. Поведение определено только для полных явных путей (начальный
~/не расширяется как домашний каталог и рассматривается как относительный путь). Разрешает символические ссылки, т.е. если указанный файл или каталог является символической ссылкой, возвращает истину, если целевой объект символической ссылки доступен для записи.Ложь, если заданный путь — пустая строка.
-
if(IS_EXECUTABLE <path-to-file-or-directory>) -
Новое в версии 3.29.
Истинно, если указанный файл или директория исполняемый. Поведение определено только для полных путей (ведущий
~/не расширяется как домашний каталог и рассматривается как относительный путь). Разрешает символические ссылки, т.е. если указанный файл или директория является символической ссылкой, возвращает истинно, если целевой объект символической ссылки исполняемый.Ложно, если заданный путь является пустой строкой.
-
if(<file1> IS_NEWER_THAN <file2>) -
Истинно, если
file1новее, чемfile2или если один из двух файлов не существует. Поведение определено только для полных путей. Если метки времени файлов совпадают, операция сравненияIS_NEWER_THANвозвращает истинно, чтобы любые зависимые операции построения выполнялись в случае ничьей. Это включает случай, когда для file1 и file2 передаётся одно и то же имя файла.
-
if(IS_DIRECTORY <path>) -
Истинно, если
pathявляется каталогом. Поведение определено только для полных путей.Ложно, если заданный путь является пустой строкой.
-
if(IS_SYMLINK <path>) -
Истинно, если заданный путь является символической ссылкой. Поведение определено только для полных путей.
-
if(IS_ABSOLUTE <path>) -
Истинно, если заданный путь является абсолютным путём. Обратите внимание на следующие особые случаи:
- Пустой
pathоценивается как ложно. - На Windows-хостах любой
path, начинающийся с буквы диска и двоеточия (например,C:), обратной или прямой косой черты, оценивается как истинно. Это означает, что путь, подобныйC:no\base\dir, будет оцениваться как истинно, даже если относительная часть пути не является частью диска. - На не-Windows-хостах любой
path, начинающийся с тильды (~), оценивается как истинно.
- Пустой
Сравнения
-
if(<variable|string> MATCHES <regex>) -
Истинно, если заданная строка или значение переменной соответствует заданному регулярному выражению. См. Спецификацию регулярных выражений для формата регулярных выражений.
Новое в версии 3.9:
()группы захватываются вCMAKE_MATCH_<n>переменных.
-
if(<variable|string> LESS <variable|string>) -
Истинно, если заданная строка или значение переменной может быть интерпретировано как вещественное число (как в C
double) и меньше, чем значение справа.
-
if(<variable|string> GREATER <variable|string>) -
Истинно, если заданная строка или значение переменной может быть интерпретировано как вещественное число (как в C
double) и больше, чем значение справа.
-
if(<variable|string> EQUAL <variable|string>) -
Истинно, если заданная строка или значение переменной может быть интерпретировано как вещественное число (как в C
double) и равно значению справа.
-
if(<variable|string> LESS_EQUAL <variable|string>) -
Новое в версии 3.7.
Истинно, если заданная строка или значение переменной может быть интерпретировано как вещественное число (как в C
double) и меньше или равно значению справа.
-
if(<variable|string> GREATER_EQUAL <variable|string>) -
Новое в версии 3.7.
Истинно, если заданная строка или значение переменной может быть интерпретировано как вещественное число (как в C
double) и больше или равно значению справа.
-
if(<variable|string> STRLESS <variable|string>) -
Истинно, если заданная строка или значение переменной лексикографически меньше, чем строка или значение справа.
-
if(<variable|string> STRGREATER <variable|string>) -
Истинно, если заданная строка или значение переменной лексикографически больше, чем строка или значение справа.
-
if(<variable|string> STREQUAL <variable|string>) -
Истинно, если заданная строка или значение переменной лексикографически равно строке или значению справа.
-
if(<variable|string> STRLESS_EQUAL <variable|string>) -
Новое в версии 3.7.
Истинно, если заданная строка или значение переменной лексикографически меньше или равно строке или значению справа.
-
if(<variable|string> STRGREATER_EQUAL <variable|string>) -
Новое в версии 3.7.
Истинно, если заданная строка или значение переменной лексикографически больше или равно строке или значению справа.
Сравнения версий
-
if(<variable|string> VERSION_LESS <variable|string>) -
Компонентное целочисленное сравнение версий (формат версии
major[.minor[.patch[.tweak]]], пропущенные компоненты рассматриваются как ноль). Любой нецелочисленный компонент версии или нецелочисленная конечная часть компонента версии эффективно обрезает строку в этом месте.
-
if(<variable|string> VERSION_GREATER <variable|string>) -
Компонентное целочисленное сравнение версий (формат версии
major[.minor[.patch[.tweak]]], пропущенные компоненты рассматриваются как ноль). Любой нецелочисленный компонент версии или нецелочисленная конечная часть компонента версии эффективно обрезает строку в этом месте.
-
if(<variable|string> VERSION_EQUAL <variable|string>) -
Компонентное целочисленное сравнение версий (формат версии
major[.minor[.patch[.tweak]]], пропущенные компоненты рассматриваются как ноль). Любой нецелочисленный компонент версии или нецелочисленная конечная часть компонента версии эффективно обрезает строку в этом месте.
-
if(<variable|string> VERSION_LESS_EQUAL <variable|string>) -
Новое в версии 3.7.
Компонентное целочисленное сравнение версий (формат версии
major[.minor[.patch[.tweak]]], пропущенные компоненты рассматриваются как ноль). Любой нецелочисленный компонент версии или нецелочисленная конечная часть компонента версии эффективно обрезает строку в этом месте.
-
if(<variable|string> VERSION_GREATER_EQUAL <variable|string>) -
Новое в версии 3.7.
Компонентное целочисленное сравнение версий (формат версии
major[.minor[.patch[.tweak]]], пропущенные компоненты рассматриваются как ноль). Любой нецелочисленный компонент версии или нецелочисленная конечная часть компонента версии эффективно обрезает строку в этом месте.
Сравнения путей
-
if(<variable|string> PATH_EQUAL <variable|string>) -
Новое в версии 3.24.
Сравнивает два пути компонент за компонентом. Только если каждый компонент обоих путей совпадает, пути сравниваются как равные. Несколько разделителей путей эффективно сводятся к одному разделителю, но обратите внимание, что обратные слэши не преобразуются в прямые. Другие нормализации путей не выполняются.
Компонентное сравнение превосходит сравнение на основе строк благодаря обработке нескольких разделителей путей. В следующем примере выражение оценивается как истинно с использованием
PATH_EQUAL, но ложно сSTREQUAL.# comparison is TRUE if ("/a//b/c" PATH_EQUAL "/a/b/c") ... endif() # comparison is FALSE if ("/a//b/c" STREQUAL "/a/b/c") ... endif()См. cmake_path(COMPARE) для получения дополнительной информации.
Расширение переменных
Команда if была написана очень рано в истории CMake, до появления синтаксиса оценки переменных ${}, и для удобства оценивает переменные, имена которых указаны в её аргументах, как показано в вышеуказанных сигнатурах. Обратите внимание, что обычная оценка переменных с ${} применяется до того, как команда if даже получит аргументы. Поэтому код, подобный
set(var1 OFF)
set(var2 "var1")
if(${var2})
выглядит для команды if как
if(var1)
и оценивается в соответствии с if(<variable>) случаем, описанным выше. Результат — OFF, что ложно. Однако, если мы удалим ${} из примера, то команда видит
if(var2)
что истинно, поскольку var2 определено как var1, что не является ложным константой.
Автоматическая оценка применяется в других случаях, когда указанный выше синтаксис условия принимает <variable|string>.
- Левый аргумент в операторе MATCHES проверяется на определение как переменной. Если переменная определена, используется её значение, в противном случае используется исходное значение.
- Если левого аргумента оператора MATCHES нет, возвращается false без ошибок.
- Левый и правый аргументы операторов LESS, GREATER, EQUAL, LESS_EQUAL и GREATER_EQUAL проверяются на определение как переменных. Если переменные определены, используются их значения, иначе используются исходные значения.
- Левый и правый аргументы операторов STRLESS, STRGREATER, STREQUAL, STRLESS_EQUAL и STRGREATER_EQUAL проверяются на определение как переменных. Если переменные определены, используются их значения, иначе используются исходные значения.
- Левый и правый аргументы операторов VERSION_LESS, VERSION_GREATER, VERSION_EQUAL, VERSION_LESS_EQUAL и VERSION_GREATER_EQUAL проверяются на определение как переменных. Если переменные определены, используются их значения, иначе используются исходные значения.
- Правый аргумент оператора NOT проверяется на то, является ли он булевым константой. Если это так, используется его значение; в противном случае предполагается, что это переменная, и она разыменовывается.
- Левый и правый аргументы операторов AND и OR проверяются на то, являются ли они булевыми константами. Если это так, они используются как константы; в противном случае предполагается, что это переменные, и они разыменовываются.
Изменено в версии 3.1: Для предотвращения неоднозначности, потенциальные имена переменных или ключевых слов могут быть указаны в Цитата Аргумента или Аргумента в скобках. Цитата или скобки переменной или ключевого слова будут интерпретированы как строка и не будут разыменовываться или интерпретироваться. См. политику CMP0054.
Автоматической оценки для переменных среды или кэша Ссылок на переменные нет. Их значения должны быть указаны как $ENV{<name>} или $CACHE{<name>} всякий раз, когда синтаксис условия, описанный выше, принимает <variable|string>.
См. также
© 2000–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.30/command/if.html