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>}.
Комментарии
Комментарий начинается с символа #, который не находится внутри Аргумента в скобках, Аргумента в кавычках или не экранирован с помощью \ как часть Необработанного аргумента. Существует два типа комментариев: Комментарий в скобках и Комментарий в строке.
Комментарий в скобках
# непосредственно после 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–2023 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.26/manual/cmake-language.7.html