macro
Начать запись макроса для последующего вызова в качестве команды
macro(<name> [<arg1> ...]) <commands> endmacro()
Определяет макрос с именем <name>, принимающий аргументы с именами <arg1>, ... Команды, указанные после макроса, но перед соответствующей командой endmacro(), не будут выполнены до вызова макроса.
Согласно старой версии, команда endmacro() допускает необязательный <name> аргумент. Если он используется, он должен быть точной копией аргумента открывающей команды macro.
См. документацию команды cmake_policy() для поведения политик внутри макросов.
См. раздел Макрос против функции ниже для отличий между макросами CMake и functions.
Вызов
Вызов макроса нечувствителен к регистру. Макрос, определенный как
macro(foo) <commands> endmacro()
можно вызвать с помощью любого из
foo() Foo() FOO() cmake_language(CALL foo)
и так далее. Однако настоятельно рекомендуется придерживаться регистра, выбранного при определении макроса. Обычно для макросов используются имена с маленькими буквами.
Новое в версии 3.18: Команда cmake_language(CALL ...) также может использоваться для вызова макроса.
Аргументы
При вызове макроса команды, записанные в макросе, сначала модифицируются заменой формальных параметров (${arg1}, ...) на переданные аргументы, а затем вызываются как обычные команды.
В дополнение к обращению к формальным параметрам можно обратиться к значениям ${ARGC}, которое будет установлено в количестве переданных аргументов макросу, а также к ${ARGV0}, ${ARGV1}, ${ARGV2}, ... которые будут содержать фактические значения переданных аргументов. Это способствует созданию макросов с необязательными аргументами.
Кроме того, ${ARGV} содержит список всех аргументов, переданных макросу, а ${ARGN} — список аргументов, следующих за последним ожидаемым аргументом. Обращение к аргументам ${ARGV#} за пределами ${ARGC} имеет неопределенное поведение. Проверка того, что ${ARGC} больше #, является единственным способом гарантировать, что ${ARGV#} был передан функции в качестве дополнительного аргумента.
Макрос против функции
Команда macro очень похожа на команду function(). Тем не менее, есть несколько важных отличий.
В функции ARGN, ARGC, ARGV и ARGV0, ARGV1, ... являются истинными переменными в обычном смысле CMake. В макросе они таковыми не являются, они являются строковыми заменами, аналогично тому, как это делает препроцессор C с макросом. Это влечёт за собой ряд последствий, как описано в разделе Примечания к аргументам ниже.
Другое различие между макросами и функциями — это поток управления. Функция выполняется путём передачи управления от вызывающей инструкции к телу функции. Макрос выполняется так, как будто тело макроса было вставлено вместо вызывающей инструкции. Это означает, что команда return() в теле макроса не просто завершает выполнение макроса; вместо этого управление возвращается из области вызова макроса. Для избежания путаницы рекомендуется полностью избегать использования return() в макросах.
В отличие от функции, переменные CMAKE_CURRENT_FUNCTION, CMAKE_CURRENT_FUNCTION_LIST_DIR, CMAKE_CURRENT_FUNCTION_LIST_FILE, CMAKE_CURRENT_FUNCTION_LIST_LINE не устанавливаются для макроса.
Примечания к аргументам
Поскольку ARGN, ARGC, ARGV, ARGV0 и т. д. не являются переменными, вы НЕ сможете использовать такие команды, как
if(ARGV1) # ARGV1 is not a variable if(DEFINED ARGV2) # ARGV2 is not a variable if(ARGC GREATER 2) # ARGC is not a variable foreach(loop_var IN LISTS ARGN) # ARGN is not a variable
В первом случае можно использовать if(${ARGV1}). Во втором и третьем случае правильный способ проверить, был ли передан необязательный аргумент макросу, — использовать if(${ARGC} GREATER 2). В последнем случае можно использовать foreach(loop_var ${ARGN}), но это пропустит пустые аргументы. Если вам нужно их включить, можно использовать
set(list_var "${ARGN}")
foreach(loop_var IN LISTS list_var)
Обратите внимание, что если у вас есть переменная с таким же именем в области, из которой вызывается макрос, использование неинициализированных имен будет использовать существующую переменную вместо аргументов. Например:
macro(bar)
foreach(arg IN LISTS ARGN)
<commands>
endforeach()
endmacro()
function(foo)
bar(x y z)
endfunction()
foo(a b c)
Будет перебирать a;b;c а не x;y;z, как можно было ожидать. Если вам нужны настоящие переменные CMake и/или лучший контроль над областью видимости CMake, следует использовать команду function.
См. также
© 2000–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.30/command/macro.html