cmake-language(7)
Организация
Файлы входных данных CMake написаны на языке CMake в файлах исходного кода, имеющих имя CMakeLists.txt или заканчивающиеся расширением .cmake.
Файлы исходного кода CMake Language в проекте организованы следующим образом:
-
Директории (
CMakeLists.txt), -
Скрипты (
<script>.cmake), и -
Модули (
<module>.cmake).
Директории
При обработке исходного дерева проекта CMake, точкой входа является файл исходного кода, называемый CMakeLists.txt в корневой директории исходного кода. Этот файл может содержать полное описание сборки или использовать команду add_subdirectory() для добавления поддиректорий к сборке. Каждая поддиректория, добавленная командой, также должна содержать файл CMakeLists.txt в качестве точки входа в эту директорию. Для каждой исходной директории, чьей файл CMakeLists.txt обрабатывается CMake, генерируется соответствующая директория в дереве сборки, которая служит в качестве рабочей и выходной директории по умолчанию.
Скрипты
Индивидуальный файл исходного кода <script>.cmake может обрабатываться в режиме скрипта с помощью утилиты командной строки cmake(1) с опцией -P. Режим скрипта просто выполняет команды в заданном файле исходного кода CMake Language и не генерирует систему сборки. Он не позволяет использовать команды CMake, определяющие цели сборки или действия.
Модули
Код CMake Language в директориях или скриптах может использовать команду include() для загрузки файла исходного кода <module>.cmake в контексте включающего кода. См. страницу справки cmake-modules(7) для документации модулей, включённых в дистрибутив CMake. Деревья исходного кода проектов также могут предоставлять свои собственные модули и указывать их расположение(я) в переменной CMAKE_MODULE_PATH.
Синтаксис
Кодировка
Файл исходного кода CMake Language может быть написан в 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 Language состоит из нуля или более Вызовов команд, разделённых символами новой строки и необязательно пробелами и Комментариями:
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>}.
Комментарии
Комментарий начинается с символа #, который не находится внутри аргумента в скобках, цитируемого аргумента или экранирован с \ как часть нецитируемого аргумента. Существует два типа комментариев: комментарий в скобках и строковый комментарий.
Комментарий в Скобках
# сразу после 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>}, используя операторENV. - Инициализация
-
Начальные значения переменных окружения CMake — это значения вызывающего процесса. Значения можно изменить с помощью команд
set()иunset(). Эти команды влияют только на выполняемый процесс CMake, а не на системную среду в целом. Измененные значения не записываются обратно в вызывающий процесс и не видны последующим процессам сборки или тестирования.См. команду командной строки cmake -E env для выполнения команды в изменённой среде.
- Проверка
-
См. команду командной строки cmake -E environment для отображения всех текущих переменных окружения.
Руководство 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"
В общем случае списки не поддерживают элементы, содержащие ; символы. Для избежания проблем рекомендуется следующее:
- Интерфейсы многих команд, переменных и свойств CMake принимают списки, разделённые точкой с запятой. Избегайте передачи списков с элементами, содержащими точки с запятой, в эти интерфейсы, если они не документируют либо прямую поддержку, либо какой-либо способ экранирования или кодирования точек с запятой.
-
При создании списка замените
;в элементах на иначе не используемый плейсхолдер. Затем замените;на плейсхолдер при обработке элементов списка. Например, следующий код использует|вместо символов;.set(mylist a "b|c") foreach(entry IN LISTS mylist) string(REPLACE "|" ";" entry "${entry}") # use "${entry}" normally endforeach()Опция
LIST_SEPARATORмодуляExternalProject— это пример интерфейса, созданного с использованием этого подхода. - В списках
generator expressionsиспользуйте выражение генератора$<SEMICOLON>. - В вызовах команд, используйте синтаксис цитируемого аргумента по возможности. Вызываемая команда получит содержимое аргумента с сохранёнными точками с запятой. Нецитируемый аргумент будет разделен на точки с запятой.
-
В реализациях
function()избегайтеARGVиARGN, которые не различают точки с запятой в значениях от разделяющих значения. Вместо этого предпочтительнее использовать именованные позиционные аргументы и переменныеARGCиARGV#. При использованииcmake_parse_arguments()для разбора аргументов, предпочтительнее использовать его подписьPARSE_ARGV, которая использует переменныеARGV#.Обратите внимание, что этот подход не применим к реализациям
macro(), потому что они ссылаются на аргументы, используя плейсхолдеры, а не реальные переменные.
© 2000–2022 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.25/manual/cmake-language.7.html