Spec-Zone.ru › CMake 3.23

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 сначала ищет привязку в стеке вызовов функций, если таковой имеется, а затем обращается к привязке в текущем глобальном пространстве имен, если она существует. Если найдена привязка типа «установить», используется её значение. Если найдена привязка типа «сбросить» или привязка не найдена, 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"

В общем случае списки не поддерживают элементы, содержащие ; символы. Чтобы избежать проблем, воспользуйтесь следующими рекомендациями:

  • Интерфейсы многих команд 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.23/manual/cmake-language.7.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API