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().
Составные условия вычисляются в следующем порядке приоритета:
- Круглые скобки.
- Унарные проверки, например:
- Проверки существования
COMMAND,DEFINED,DIAGNOSTIC,EXISTS,POLICY,TARGETиTEST. - Файловые операции
IS_READABLE,IS_WRITABLE,IS_EXECUTABLE,IS_DIRECTORY,IS_SYMLINKиIS_ABSOLUTE.
- Бинарные проверки, описанные в разделах Сравнения, Сравнение версий и Сравнение путей, а также
IN_LISTиIS_NEWER_THAN. - Унарный логический оператор
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() -
Ложь, если аргументы не указаны.
Логические операторы
-
if(NOT <condition>) -
Истина, если условие не является истинным.
-
if(<cond1> AND <cond2>) -
Истина, если оба условия по отдельности считались бы истинными.
-
if(<cond1> OR <cond2>) -
Истина, если любое из условий по отдельности считалось бы истинным.
-
if((condition) AND (condition OR (condition))) -
Сначала вычисляются условия в скобках, затем — оставшееся условие, как и в других примерах. Если скобки вложены, внутренние скобки вычисляются в рамках вычисления содержащего их условия.
Проверки существования
-
if(COMMAND <command-name>) -
Истина, если указанное имя является вызываемой командой, макросом или функцией.
-
if(DIAGNOSTIC <category>) -
Добавлено в версии 4.4.
Истина, если указанное имя является существующей категорией диагностики.
-
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>) -
Истина, если указанная строка или значение переменной соответствует заданному регулярному выражению. Формат регулярных выражений см. в разделе Спецификация регулярных выражений. Группы
()сохраняются в переменныхCMAKE_MATCH_<n>.
-
if(<variable|string> LESS <variable|string>) -
Истина, если указанная строка или значение переменной интерпретируется как вещественное число (например, число типа
doubleв C) и меньше значения справа.
-
if(<variable|string> GREATER <variable|string>) -
Истина, если указанная строка или значение переменной интерпретируется как вещественное число (например, число типа
doubleв C) и больше значения справа.
-
if(<variable|string> EQUAL <variable|string>) -
Истина, если указанная строка или значение переменной интерпретируется как вещественное число (например, число типа
doubleв C) и равно значению справа.
-
if(<variable|string> LESS_EQUAL <variable|string>) -
Добавлено в версии 3.7.
Истина, если указанная строка или значение переменной интерпретируется как вещественное число (например, число типа
doubleв C) и меньше или равно значению справа.
-
if(<variable|string> GREATER_EQUAL <variable|string>) -
Добавлено в версии 3.7.
Истина, если указанная строка или значение переменной интерпретируется как вещественное число (например, число типа
doubleв C) и больше или равно значению справа.
-
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.
Лексикографически сравнивает два пути CMake покомпонентно, не обращаясь к файловой системе. Пути считаются равными, только если совпадают все их компоненты. Несколько разделителей пути фактически сводятся к одному, однако обратные косые черты не преобразуются в прямые. Другая нормализация пути не выполняется. Завершающие косые черты сохраняются, поэтому
/a/bи/a/b/не равны.Покомпонентное сравнение лучше сравнения строк, поскольку учитывает несколько разделителей пути. В следующем примере выражение вычисляется как истина при использовании
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отсутствует, возвращается ложь без ошибки. - Левый и правый аргументы
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независимо проверяются на то, являются ли они определёнными переменными. Если да, используются их заданные значения, иначе используются исходные значения. - Левый аргумент
IN_LISTпроверяется на то, является ли он определённой переменной. Если да, используется значение переменной, иначе используется исходное значение. - Правый аргумент
NOTпроверяется на то, является ли он логической константой. Если да, используется это значение, иначе предполагается, что это переменная, и она разыменовывается. - Левый и правый аргументы
ANDиORнезависимо проверяются на то, являются ли они логическими константами. Если да, они используются как есть, иначе предполагается, что это переменные, и они разыменовываются.
Изменено в версии 3.1: Чтобы избежать неоднозначности, потенциальные имена переменных или ключевых слов можно указывать как аргумент в кавычках или аргумент в скобках. Переменная или ключевое слово в кавычках либо скобках интерпретируется как строка и не разыменовывается и не интерпретируется. См. политику CMP0054.
Автоматическое вычисление для переменных среды или кэша не выполняется. Их значения необходимо указывать как ссылки на переменные $ENV{<name>} или $CACHE{<name>} везде, где описанный выше синтаксис условия допускает <variable|string>.
См. также
© 2000–2026 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/latest/command/if.html