cmake-language(7)
Организация
Файлы ввода CMake написаны на языке CMake в файлах исходного кода, имена которых заканчиваются на CMakeLists.txt или имеют расширение .cmake.
Файлы исходного кода CMake в проекте организованы следующим образом:
-
Директории (
CMakeLists.txt), -
Сценарии (
<script>.cmake), и -
Модули (
<module>.cmake).
Директории
При обработке CMake проекта исходный код начинается с файла CMakeLists.txt в корневой директории. Этот файл может содержать полную спецификацию сборки или использовать команду add_subdirectory() для добавления поддиректорий в сборку. Каждая поддиректория, добавленная с помощью этой команды, также должна содержать файл CMakeLists.txt в качестве точки входа в эту директорию. Для каждой исходной директории, файл CMakeLists.txt которой обрабатывается, CMake генерирует соответствующую директорию в дереве сборки, которая служит рабочей и выходной директорией по умолчанию.
Сценарии
Индивидуальный файл исходного кода <script>.cmake может быть обработан в режиме сценария с помощью командной строки cmake(1) с параметром -P. Режим сценария просто выполняет команды в указанном файле исходного кода CMake и не генерирует систему сборки. Он не позволяет использовать команды CMake, которые определяют цели сборки или действия.
Модули
Код языка CMake в директориях или сценариях может использовать команду include() для загрузки файла исходного кода <module>.cmake в контексте включающего кода. См. руководство cmake-modules(7) для документации модулей, включенных в дистрибутив CMake. Деревья исходного кода проекта также могут предоставлять свои собственные модули и указывать их расположение в переменной CMAKE_MODULE_PATH.
Синтаксис
Кодировка
Файл исходного кода языка CMake может быть записан в 7-битном ASCII для максимальной портативности на всех поддерживаемых платформах. Переводы строк могут быть закодированы как \n или \r\n, но будут преобразованы в \n при чтении файлов.
Обратите внимание, что реализация является 8-битной, поэтому файлы исходного кода могут быть закодированы как UTF-8 на платформах с API, поддерживающими эту кодировку. Кроме того, CMake 3.2 и выше поддерживают файлы исходного кода, закодированные в UTF-8 на Windows (используя UTF-16 для вызова системных API). Более того, CMake 3.0 и выше позволяют использовать префикс UTF-8 Byte-Order Mark в файлах исходного кода.
Файлы исходного кода
Файл исходного кода языка CMake состоит из нуля или более вызовов команд, разделенных переводами строк и необязательно пробелами и комментариями:
file ::= file_element*
file_element ::= command_invocation line_ending |
(bracket_comment|space)* line_ending
line_ending ::= line_comment? newline
space ::= <match '[ \t]+'>
newline ::= <match '\n'>
Обратите внимание, что любая строка исходного файла, не находящаяся внутри аргументов команд или комментария в квадратных скобках, может заканчиваться комментарием в строке.
Вызовы команд
Вызов команды — это имя, за которым следуют заключенные в скобки аргументы, разделенные пробелами:
command_invocation ::= space* identifier space* '(' arguments ')'
identifier ::= <match '[A-Za-z_][A-Za-z0-9_]*'>
arguments ::= argument? separated_arguments*
separated_arguments ::= separation+ argument? |
separation* '(' arguments ')'
separation ::= space | line_ending
Например:
add_executable(hello world.c)
Имена команд нечувствительны к регистру. Вложенные необработанные скобки в аргументах должны быть сбалансированы. Каждый ( или ) передаётся вызову команды как литерльный необработанный аргумент. Это может использоваться в вызовах команды if() для заключения условий. Например:
if(FALSE AND (FALSE OR TRUE)) # evaluates to FALSE
Примечание
Версии CMake до 3.0 требуют, чтобы идентификаторы имён команд содержали не менее 2 символов.
Версии CMake до 2.8.12 молча принимают необработанный аргумент или аргумент в кавычках непосредственно после аргумента в кавычках и не разделенного пробелами. Для совместимости CMake 2.8.12 и выше принимают такой код, но выдают предупреждение.
Аргументы команд
Существует три типа аргументов внутри вызовов команд:
argument ::= bracket_argument | quoted_argument | unquoted_argument
Аргумент в квадратных скобках
Аргумент в квадратных скобках, вдохновлённый синтаксисом длинных скобок Lua, заключает содержимое между открывающей и закрывающей "скобками" одинаковой длины:
bracket_argument ::= bracket_open bracket_content bracket_close
bracket_open ::= '[' '='* '['
bracket_content ::= <any text not containing a bracket_close with
the same number of '=' as the bracket_open>
bracket_close ::= ']' '='* ']'
Открывающая скобка записывается как [ за которым следуют ноль или более = и [. Соответствующая закрывающая скобка записывается как ] за которым следуют то же количество = и ]. Скобки не вложены. Всегда можно выбрать уникальную длину для открывающей и закрывающей скобок для размещения закрывающих скобок других длин.
Содержимое аргумента в квадратных скобках состоит из всего текста между открывающей и закрывающей скобками, за исключением того, что один перевод строки непосредственно после открывающей скобки, если есть, игнорируется. Не выполняется никакая обработка заключённого содержимого, например, последовательности экранирования или ссылок на переменные. Аргумент в квадратных скобках всегда передаётся вызову команды как ровно один аргумент.
Например:
message([=[
This is the first line in a bracket argument with bracket length 1.
No \-escape sequences or ${variable} references are evaluated.
This is always one argument even though it contains a ; character.
The text does not end on a closing bracket of length 0 like ]].
It does end in a closing bracket of length 1.
]=])
Примечание
Версии CMake до 3.0 не поддерживают аргументы в квадратных скобках. Они интерпретируют открывающую скобку как начало необработанного аргумента.
Аргумент в кавычках
Аргумент в кавычках заключает содержимое между открывающей и закрывающей двойными кавычками:
quoted_argument ::= '"' quoted_element* '"'
quoted_element ::= <any character except '\' or '"'> |
escape_sequence |
quoted_continuation
quoted_continuation ::= '\' newline
Содержимое аргумента в кавычках состоит из всего текста между открывающими и закрывающими кавычками. Оба экранирования и ссылки на переменные оцениваются. Аргумент в кавычках всегда передаётся вызову команды как ровно один аргумент.
Например:
message("This is a quoted argument containing multiple lines.
This is always one argument even though it contains a ; character.
Both \\-escape sequences and ${variable} references are evaluated.
The text does not end on an escaped double-quote like \".
It does end in an unescaped double quote.
")
Последний \ в любой строке, заканчивающейся нечётным числом обратных слешей, обрабатывается как продолжение строки и игнорируется вместе с последующим символом перевода строки. Например:
message("\
This is the first line of a quoted argument. \
In fact it is the only line but since it is long \
the source code uses line continuation.\
")
Примечание
Версии CMake до 3.0 не поддерживают продолжение с \. Они сообщают об ошибках в аргументах в кавычках, содержащих строки, заканчивающиеся нечётным числом \ символов.
Необработанный аргумент
Необработанный аргумент не заключён в никакой синтаксис цитирования. Он не может содержать пробелы, (, ), #, ", или \ за исключением случаев, когда они экранированы обратным слешем:
unquoted_argument ::= unquoted_element+ | unquoted_legacy
unquoted_element ::= <any character except whitespace or one of '()#"\'> |
escape_sequence
unquoted_legacy ::= <see note in text>
Содержимое необработанного аргумента состоит из всего текста в смежном блоке разрешённых или экранированных символов. Оба экранирования и ссылки на переменные оцениваются. Результирующее значение делится таким же образом, как списки делятся на элементы. Каждый ненулевой элемент передаётся вызову команды в качестве аргумента. Следовательно, необработанный аргумент может передаваться вызову команды в качестве нуля или более аргументов.
Например:
foreach(arg
NoSpace
Escaped\ Space
This;Divides;Into;Five;Arguments
Escaped\;Semicolon
)
message("${arg}")
endforeach()
Примечание
Для поддержки устаревшего кода CMake, необработанные аргументы также могут содержать строки в двойных кавычках ("...", возможно, содержащие горизонтальное пространство), и ссылки на переменные в стиле make ($(MAKEVAR)).
Неэкранированные двойные кавычки должны быть сбалансированы, не могут появляться в начале необработанного аргумента и обрабатываются как часть содержимого. Например, необработанные аргументы -Da="b c", -Da=$(v), и a" "b"c"d каждый интерпретируются буквально. Их можно вместо этого записать как аргументы в кавычках "-Da=\"b c\"", "-Da=$(v)", и "a\" \"b\"c\"d", соответственно.
Ссылки в стиле make обрабатываются буквально как часть содержимого и не подвергаются расширению переменных. Они обрабатываются как часть одного аргумента (а не как отдельные $, (, MAKEVAR, и ) аргументы).
Вышеприведенное «необработанное_устаревшее» производство представляет такие аргументы. Мы не рекомендуем использовать устаревшие необработанные аргументы в новом коде. Вместо этого используйте аргумент в кавычках или аргумент в квадратных скобках для представления содержимого.
Последовательности экранирования
Последовательность экранирования — это \ за которым следует один символ:
escape_sequence ::= escape_identity | escape_encoded | escape_semicolon escape_identity ::= '\' <match '[^A-Za-z0-9;]'> escape_encoded ::= '\t' | '\r' | '\n' escape_semicolon ::= '\;'
\ за которым следует не буквенно-цифровой символ, просто кодирует буквенный символ без интерпретации его как синтаксиса. \t, \r, или \n кодирует символ табуляции, возврата каретки или новой строки, соответственно. \; вне ссылок на переменные кодирует себя, но может использоваться в необработанном аргументе для кодирования ; без разделения значения аргумента на нём. \; внутри ссылок на переменные кодирует буквенный ; символ. (См. также политику CMP0053 документацию для исторических соображений.)
Ссылки на переменные
Ссылка на переменную имеет вид ${<variable>} и оценивается внутри аргумента в кавычках или необработанного аргумента. Ссылка на переменную заменяется значением переменной или пустой строкой, если переменная не задана. Ссылки на переменные могут быть вложены и оцениваются изнутри наружу, например, ${outer_${inner_variable}_variable}.
Буквенные ссылки на переменные могут состоять из буквенно-цифровых символов, символов /_.+-, и последовательностей экранирования. Вложенные ссылки могут использоваться для оценки переменных любого имени. См. также политику CMP0053 документацию для исторических соображений и причин, почему $ также технически разрешено, но не рекомендуется.
Раздел Переменные документирует область имен переменных и то, как устанавливаются их значения.
Ссылка на переменную окружения имеет вид $ENV{<variable>}. См. раздел Переменные окружения для получения дополнительной информации.
Ссылка на переменную кэша имеет вид $CACHE{<variable>}. См. CACHE для получения дополнительной информации.
Команда if() имеет специальный синтаксис условия, который позволяет использовать ссылки на переменные в сокращенной форме <variable> вместо ${<variable>}. Однако, переменные среды и кэша всегда должны ссылаться как $ENV{<variable>} или $CACHE{<variable>}.
Комментарии
Комментарий начинается с символа #, который не находится внутри аргумента в квадратных скобках, аргумента в кавычках или экранирован с \ как часть необработанного аргумента. Существуют два типа комментариев: комментарий в квадратных скобках и строчный комментарий.
Комментарий в квадратных скобках
# сразу за которым следует bracket_open формирует комментарий в квадратных скобках, состоящий из всего содержимого скобок:
bracket_comment ::= '#' bracket_argument
Например:
#[[This is a bracket comment.
It runs until the close bracket.]]
message("First Argument\n" #[[Bracket Comment]] "Second Argument")
Примечание
Версии CMake до 3.0 не поддерживают комментарии в квадратных скобках. Они интерпретируют открывающий # как начало строчного комментария.
Строчный комментарий
# не сразу за которым следует bracket_open формирует строчный комментарий, который продолжается до конца строки:
line_comment ::= '#' <any text not starting in a bracket_open
and not containing a newline>
Например:
# This is a line comment.
message("First Argument\n" # This is a line comment :)
"Second Argument") # This is a line comment.
Структуры управления
Условные блоки
Команды if()/elseif()/else()/endif() разделяют блоки кода, которые должны быть выполнены условно.
Циклы
Команды foreach()/endforeach() и while()/endwhile() разделяют блоки кода, которые должны быть выполнены в цикле. В таких блоках может использоваться команда break() для преждевременного завершения цикла, а команда continue() — для немедленного перехода к следующей итерации.
Определения команд
Команды macro()/endmacro() и function()/endfunction() разделяют блоки кода, которые записываются для последующего вызова в качестве команд.
Переменные
Переменные являются основной единицей хранения в языке CMake. Их значения всегда являются строкового типа, хотя некоторые команды могут интерпретировать строки как значения других типов. Команды set() и unset() явно устанавливают или удаляют переменную, но и другие команды имеют семантику, которая изменяет переменные. Имена переменных чувствительны к регистру и могут состоять практически из любого текста, но мы рекомендуем придерживаться имен, состоящих только из буквенно-цифровых символов, плюс _ и -.
Переменные имеют динамическую область видимости. Каждое «установка» или «удаление» переменной создает привязку в текущей области видимости:
- Область видимости функции
-
Определения команд, созданные командой
function(), создают команды, которые при вызове обрабатывают записанные команды в новой области видимости привязки переменных. Переменная «установка» или «удаление» привязывается в этой области видимости и видна для текущей функции и любых вложенных вызовов в ней, но не после возвращения функции. - Область видимости директории
-
Каждая из директорий в дереве исходных файлов имеет свои привязки переменных. Перед обработкой файла
CMakeLists.txtдля директории CMake копирует все привязки переменных, которые в данный момент определены в родительской директории, если таковые имеются, для инициализации новой области видимости директории. Скрипты CMake, при обработке сcmake -P, привязывают переменные в одной области видимости «директории».Переменная «установка» или «удаление», не находящаяся внутри вызова функции, привязывается к текущей области видимости директории.
- Постоянный кэш
-
CMake хранит отдельный набор «переменных кэша», или «записей кэша», значения которых сохраняются во время нескольких запусков в дереве сборки проекта. У записей кэша есть изолированная область видимости привязки, изменяемая только по явным запросам, таким как опция
CACHEкомандset()иunset().
При оценке ссылок на переменные, CMake сначала ищет привязку в стеке вызовов функций, если таковой имеется, а затем переходит к привязке в области видимости текущего каталога, если таковая имеется. Если найдена привязка «set», используется её значение. Если найдена привязка «unset» или привязка не найдена, CMake ищет запись в кэше. Если запись в кэше найдена, используется её значение. В противном случае ссылка на переменную оценивается как пустая строка. Синтаксис $CACHE{VAR} может использоваться для непосредственного поиска записей в кэше.
В руководстве cmake-variables(7) описываются многочисленные переменные, предоставляемые CMake или имеющие значение для CMake, когда они заданы кодом проекта.
Примечание
CMake резервирует идентификаторы, которые:
- начинаются с
CMAKE_(заглавные, строчные или смешанные регистры), или - начинаются с
_CMAKE_(заглавные, строчные или смешанные регистры), или - начинаются с
_, за которым следует имя любойCMake Command.
Переменные среды
Переменные среды похожи на обычные переменные, с следующими отличиями:
- Область видимости
-
Переменные среды имеют глобальную область видимости в процессе CMake. Они никогда не кэшируются.
- Ссылки
-
Ссылки на переменные имеют вид
$ENV{<variable>}. - Инициализация
-
Начальные значения переменных среды CMake — это значения вызывающего процесса. Значения можно изменить с помощью команд
set()иunset(). Эти команды влияют только на выполняемый процесс CMake, а не на системную среду в целом. Изменённые значения не записываются обратно в вызывающий процесс и не видны последующим процессам сборки или тестирования.
В руководстве cmake-env-variables(7) описаны переменные среды, имеющие специальное значение для CMake.
Списки
Хотя все значения в CMake хранятся как строки, строка может обрабатываться как список в определенных контекстах, например, при оценке неуказанного аргумента. В таких контекстах строка делится на элементы списка путём разбиения по символам ; не следующих за неравным количеством [ и ] символов и не предшествующих непосредственно символу \. Последовательность \; не разделяет значение, а заменяется на ; в результирующем элементе.
Список элементов представляется как строка путём конкатенации элементов, разделённых ;. Например, команда set() сохраняет несколько значений в целевую переменную в виде списка:
set(srcs a.c b.c c.c) # sets "srcs" to "a.c;b.c;c.c"
Списки предназначены для простых случаев использования, таких как список исходных файлов, и не должны использоваться для сложных задач обработки данных. Большинство команд, которые строят списки, не экранируют символы ; в элементах списка, тем самым уплощая вложенные списки:
set(x a "b;c") # sets "x" to "a;b;c", not "a;b\;c"
© 2000–2021 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.20/manual/cmake-language.7.html