cmake-language(7)
Организация
Файлы входных данных CMake написаны на языке «CMake Language» в исходных файлах, имеющих имя 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, и ) аргументов).
Вышеприведенное производство "unquoted_legacy" представляет такие аргументы. Мы не рекомендуем использовать устаревшие необработанные аргументы в новом коде. Вместо этого используйте Аргумент в кавычках или Аргумент в скобках для представления содержимого.
Последовательности экранирования
Последовательность экранирования — это \ , за которым следует один символ:
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()Модуль
ExternalProjectопцияLIST_SEPARATORявляется примером интерфейса, созданного с помощью этого подхода. - В списках
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/v3.27/manual/cmake-language.7.html