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 маркер порядка байтов в файлах исходного кода.
Файлы исходного кода
Файл исходного кода языка 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>}.
Комментарии
Комментарий начинается с символа #, который не находится внутри Аргумента в скобках, Цитируемого аргумента или экранирован с \ в качестве части Нецитируемого аргумента. Существует два типа комментариев: Комментарий в скобках и Строчный комментарий.
Комментарий в скобках
# сразу за которым следует 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() явно устанавливают или сбрасывают переменную, но и другие команды имеют семантику, которая изменяет переменные. Имена переменных чувствительны к регистру и могут состоять практически из любого текста, но мы рекомендуем придерживаться имён, состоящих только из буквенно-цифровых символов плюс _ и -.
Переменные имеют динамическую область действия. Каждое «установление» или «сброс» переменной создает привязку в текущей области действия:
- Область действия блока
-
Команда
block()может создать новую область действия для привязок переменных. - Область действия функции
-
Определения команд, созданные командой
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–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/latest/manual/cmake-language.7.html