Spec-Zone.ru › CMake 3.29

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 маркер порядка байтов в файлах исходного кода.

Файлы исходного кода

Файл исходного кода 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() явно устанавливают или сбрасывают переменную, но и другие команды имеют семантику, которая изменяет переменные. Имена переменных регистрозависимые и могут состоять практически из любого текста, но мы рекомендуем придерживаться имён, состоящих только из буквенно-цифровых символов плюс _ и -.

Переменные имеют динамический охват. Каждая переменная "set" или "unset" создает привязку в текущем объеме:

Область действия блока

Команда block() может создать новую область действия для привязок переменных.

Область действия функции

Определения команд, созданные командой function(), создают команды, которые при вызове обрабатывают записанные команды в новой области действия привязок переменных. Переменная "set" или "unset" связывается в этой области и видна для текущей функции и любых вложенных вызовов внутри неё, но не после возврата из функции.

Область действия директории

Каждая из Директорий в дереве исходных кодов имеет свои привязки переменных. Перед обработкой файла CMakeLists.txt для директории CMake копирует все привязки переменных, которые в данный момент определены в родительской директории, если таковые имеются, для инициализации новой области действия директории. CMake Скрипты, при обработке с cmake -P, привязывают переменные в одной области действия "директории".

Переменная "set" или "unset", не находящаяся внутри вызова функции, привязывается к текущей области действия директории.

Постоянный кэш

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/v3.29/manual/cmake-language.7.html

Spec-Zone.ru

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