Функции и макросы в CMake
Проекты использующие CMake по мере разработки, со временем обрастают всё большим числом настроек. К тому же код CMake, используемый в одном проекте, как правило начинает использоваться в других проектах.
В CMake как правило код разбивают на части и помещают в отдельные файлы и уже в файле CMakeLists.txt включают эти файлы в определённом порядке.
Если же один и тот же код предполагается использовать, например, для обработки разных файлов, имеет смысл объявить отдельную функцию, которая будет содержать данный код.
Сегодня мы рассмотрим использование функций и макросов в CMake.
Настройка проекта
Начнем мы с шаблона проекта Qt6 размещенного в git-репозитории.
Если папка:
c:\projects\qt6_funcsуже существует, переместите или удалите её:
cd c:\projects
rmdir /q/s qt6_funcsМы будем использовать проект из git-репозитория:
cd c:\projects
rmdir /q/s qt6-project-templategit
git clone https://gitflic.ru/project/vasiliyaltunin/qt6-project-templategit.git --depth 1Скопируем папку с проектом:
xcopy /y/e .\qt6-project-templategit\ .\qt6_funcs\Проверим:
cd c:\projects\qt6_funcs
cmake –S . –B build
cmake —-build build
.\build\qt6tpl.exeHello world!
Debug: Clicked (qrc:/qt/qml/altuninvv/qmlmain/qml/Main.qml:24, expression for onClicked)Всё работает.
Объявление функции
Добавим папку для функций:
mkdir cmake\functionsСоздадим файл для функции:
type nul > cmake\functions\myfunc.cmake.inОткроем наш проект
cd c:\projects\qt6_funcs
code .В файл cmake\functions\myfunc.cmake.in добавим код:
# Объявление функции - myfunction
function(myfunction)
message("Helloo this is MyFunction!")
endfunction()Откроем файл CMakeLists.txt добавим в конце:
# Добавляем функцию в проект
include(${PROJECT_SOURCE_DIR}/cmake/functions/myfunc.cmake.in)
# Вызываем функцию myfunction
myfunction()Запустим:
cmake -S . -B buildРезультат:
Helloo this is MyFunction!
-- Configuring done (1.0s)
-- Generating done (0.1s)
-- Build files have been written to: C:/Projects/qt6_funcs/buildПараметры функции
Откроем файл CMakeLists.txt изменим код после:
# Вызываем функцию myfunctionЗаменим на:
set(MY_FUNCTION_PARAM "123")
myfunction(MY_FUNCTION_PARAM)Изменим код в файле cmake\functions\myfunc.cmake:
# - Функция myfunction
# Предназначена для вычисления зависимостей от сторонних разделяемых библиотек.
#
# Использование:
#
# myfunction(
# [param1]
# )
#
# [param1] - первый параметр функции
function(myfunction param1)
message("Helloo this is MyFunction!")
message("All params: ${ARGV}")
message("Params count: ${ARGC}")
message("Params names: ${ARGN}")
message("----")
message("Param #1: ${param1}")
message("Param #1: ${ARGV0}")
endfunction()Здесь мы сразу добавили комментарий с описанием функции.
Доступ к параметрам может осуществляться по имени параметра и использованием переменных.
Всего функция имеет три переменных, позволяющих получить доступ к параметрам:
${ARGV} – список всех параметров
${ARGС} – количество параметров
${ARGN} – имена параметров не указанных при объявлении функции
Получить параметры по порядку можно добавлением цифр к параметру ${ARGV}.
Обратите внимание! Нумерация начинается с нуля!
${ARGV0}
${ARGV1}
и.т.д.Запустим:
cmake -S . -B buildHelloo this is MyFunction!
All params: MY_FUNCTION_PARAM
Params count: 1
Params names:
----
Param #1: MY_FUNCTION_PARAM
Param #1: MY_FUNCTION_PARAMДобавим еще параметров в вызов нашей функции в файле CMakeLists.txt:
myfunction(MY_FUNCTION_PARAM ${PROJECT_SOURCE_DIR} "123456")Запустим:
cmake -S . -B buildHelloo this is MyFunction!
All params: MY_FUNCTION_PARAM;C:/Projects/qt6_pre_package;123456
Params count: 3
Params names: C:/Projects/qt6_pre_package;123456
----
Param #1: MY_FUNCTION_PARAM
Param #1: MY_FUNCTION_PARAMОбратите внимание! Необязательные параметры появились в:
Params names: C:/Projects/qt6_pre_package;123456Разыменование параметров в функции
Изменим нашу функцию:
function(myfunction param1)
message("Helloo this is MyFunction!")
message("All params: ${ARGV}")
message("Params count: ${ARGC}")
message("Params names: ${ARGN}")
message("----")
message("Param #1: ${param1}")
message("${ARGV0}: ${${ARGV0}}")
endfunction()Запустим:
cmake -S . -B buildHelloo this is MyFunction!
All params: MY_FUNCTION_PARAM;C:/Projects/qt6_pre_package;123456
Params count: 3
Params names: C:/Projects/qt6_pre_package;123456
----
Param #1: MY_FUNCTION_PARAM
MY_FUNCTION_PARAM: 123Здесь мы провели двойное разыменование:
${${ARGV0}}Для получения значения первой переменной функции.
Видимость переменных в функциях
Любые переменные устанавливаемые в функции будут удалены при выходе из функции.
Изменим нашу функцию:
function(myfunction param1)
message("Helloo this is MyFunction!")
message("All params: ${ARGV}")
message("Params count: ${ARGC}")
message("Params names: ${ARGN}")
message("----")
message("Param #1: ${param1}")
message("${ARGV0}: ${${ARGV0}}")
set(MY_FUNCTION_PARAM "456")
endfunction()Изменим вызов нашей функции добавив еще один вызов в CMakeLists.txt:
myfunction(MY_FUNCTION_PARAM ${PROJECT_SOURCE_DIR} "123456")
myfunction(MY_FUNCTION_PARAM ${PROJECT_SOURCE_DIR} "123456")Запустим:
cmake -S . -B buildHelloo this is MyFunction!
All params: MY_FUNCTION_PARAM;C:/Projects/qt6_pre_package;123456
Params count: 3
Params names: C:/Projects/qt6_pre_package;123456
----
Param #1: MY_FUNCTION_PARAM
MY_FUNCTION_PARAM: 123
Helloo this is MyFunction!
All params: MY_FUNCTION_PARAM;C:/Projects/qt6_pre_package;123456
Params count: 3
Params names: C:/Projects/qt6_pre_package;123456
----
Param #1: MY_FUNCTION_PARAM
MY_FUNCTION_PARAM: 123Несмотря на то, что мы меняем значение переменной MY_FUNCTION_PARAM её значение: не сохраняется при выходе из функции.
Макросы в CMake
Макросы аналогичны функциям, за исключением того, что любые изменения глобальных параметров будут сохранены после выхода из макроса.
Изменим нашу функцию, превратив её в макрос:
macro(myfunction param1)
message("Helloo this is MyFunction!")
message("All params: ${ARGV}")
message("Params count: ${ARGC}")
message("Params names: ${ARGN}")
message("----")
message("Param #1: ${param1}")
message("${ARGV0}: ${${ARGV0}}")
set(MY_FUNCTION_PARAM "456")
endmacro()Запустим:
cmake -S . -B buildHelloo this is MyFunction!
All params: MY_FUNCTION_PARAM;C:/Projects/qt6_pre_package;123456
Params count: 3
Params names: C:/Projects/qt6_pre_package;123456
----
Param #1: MY_FUNCTION_PARAM
MY_FUNCTION_PARAM: 123
Helloo this is MyFunction!
All params: MY_FUNCTION_PARAM;C:/Projects/qt6_pre_package;123456
Params count: 3
Params names: C:/Projects/qt6_pre_package;123456
----
Param #1: MY_FUNCTION_PARAM
MY_FUNCTION_PARAM: 456На этот раз, при втором вызове, значение переменной MY_FUNCTION_PARAM поменялось:
Param #1: MY_FUNCTION_PARAM = 456Обратите внимание! Всегда используйте только функции при работе с CMake, макросы используются в особых случаях, так как их использование может привести к необъяснимому поведению в процессе сборки проекта.
Заключение
Сегодня мы рассмотрели использование функций и макросов в CMake:
Рассмотрели объявление функции;
Рассмотрели объявление параметров;
Рассмотрели разыменование параметров функции;
Рассмотрели особенности применения макросов в CMake.
Добавить комментарий