Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Система построения проектов CMake. Учебник.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
2.8. Команды управляющих конструкций
но, выполняются все команды до соответствующей команды
endwhile().
Команда break() досрочно прерывает выполнение ближайшего охватывающего цикла while() или foreach() (п. 2.8.3).
Команда continue(), которая появилась в CMake 3.2, до­срочно переходит к следующей итерации ближайшего цикла.

2.8.3. foreach(), endforeach()

foreach(hимя_переменнойi hзначение1i ... hзначениеni)
hкомандыi
endforeach()
foreach(
hимя_переменнойi IN
f
g g
LISTSfhсписок1i ... hсписокni
f
ITEMSfhзначение1i ... hзначениеni
g g
)
foreach(hимя_переменнойi RANGE hмаксимумi)
foreach(hимя_переменнойi RANGE hстартi hстопifhшагig)
Первая форма команды foreach() выполняет все коман­ды до соответствующей команды endforeach() в количестве раз, равном количеству передаваемых ей значений. При этом на каждой итерации цикла переменная с заданным именем бу-
141
2. Основы языка CMake
дет последовательно принимать значения со второго по послед­ний аргумент команды foreach().
Вторая форма команды foreach() аналогична первой, но удобнее неё в определённых случаях. В ней можно указывать имена переменных-списков, значения которых будут обходить­ся в цикле (после необязательного аргумента LISTS), а также са­ми значения непосредственно (после необязательного аргумен­та ITEMS). Пустые списки рассматриваются как списки без эле­ментов.
Третья форма команды foreach() выполняет тело цик­ла с целочисленными значениями переменной от 0 до за­данного максимума. Таким образом, тело цикла выполняется
«hмаксимумi + 1» раз.
Наконец, последняя форма команды foreach() выполняет тело цикла с целочисленными значениями переменной в задан­ном отрезке с заданным шагом (1 по умолчанию). Тело цикла выполняется, пока значение переменной не превышает значе­ния hстопi. Таким образом, тело цикла будет выполнено всего
«hстопi − hстартi + 1÷ hшагi» раз (здесь используется деление на-
цело с недостатком).
ПРИМЕР Пусть проект верхнего уровня должен состоять из несколь­ких независимых подпроектов. Требуется организовать схему, предусматривающую возможность исключения каждого под­проекта из общего построения в целях экономии времени раз­работчиков, которым для работы не нужно собирать все компо­ненты системы. Компонент выбирается для построения, если де-
142
2.8. Команды управляющих конструкций
рево его исходных файлов загружается из отдельного репозита­рия кода в каталог корневого проекта. В каждом таком проек­те есть его описание в файле CMakeLists.txt. Кроме этого, раз­работчик может исключить проект из построения при помощи флага настройки из кэша CMake.
Файл CMakeLists.txt корневого проекта может быть реа-
лизован следующим образом:
cmake_minimum_required(VERSION 2.8)
project(complex_project)
set(
SUBPROJECTS
program1 program2 super_program
)
include(build.cmake)
Здесь для удобства разработчиков все детали реализации перенесены во вспомогательный файл build.cmake, который подключается командой include() (п. 2.4.3). Таким образом, корневой CMakeLists.txt, который, скорее всего, придётся ре­дактировать чаще, имеет небольшой размер. Список компонент присваивается переменной SUBPROJECTS при помощи команды set() (п. 2.7.1).
Файл build.cmake может иметь следующее содержимое:
foreach(PROJ ${SUBPROJECTS})
143
2. Основы языка CMake
set(
MY_BUILD_${PROJ} TRUE
CACHE BOOL "Build the ${PROJ} subproject")
if(MY_BUILD_${PROJ} AND
EXISTS
"${CMAKE_SOURCE_DIR}/${PROJ}/CMakeLists.txt")
message(
STATUS
"The project ${PROJ} will be included")
add_subdirectory(${PROJ})
else()
message(
STATUS
"The project ${PROJ} will NOT be included")
endif()
endforeach()
Здесь команда foreach() организует перебор значений списка из переменной SUBPROJECTS, присваивая каждое из них последовательно переменной PROJ. В теле цикла при помощи команды set() создаётся логическая переменная в кэше (ес­ли на текущий момент её там ещё нет), значение которой определяет включение подпроекта в построение. Имя перемен­ной получается конкатенацией строки «MY_BUILD_» и имени подпроекта. Далее команда if() (п. 2.8.1) проверяет условие, при котором подпроект будет включён в построение. Для это­го необходимо, чтобы значение соответствующей переменной
144
2.8. Команды управляющих конструкций
было истинным и чтобы исходные файлы подпроекта были загружены в дерево корневого проекта. Последнее проверяет­ся существованием файла CMakeLists.txt в каталоге с име­нем подпроекта, который должен находиться в каталоге кор­невого проекта. Путь к нему содержится в специальной пере­менной CMAKE_SOURCE_DIR. Подпроект подключается командой add_subdirectory() (п. 2.5.3).
Команда foreach() может быть также записана в следую-
щем виде:
foreach(PROJ IN LISTS SUBPROJECTS)
После первой обработки проекта системой CMake будет создан файл кэша в каталоге построения с переменными MY_BUILD_program1 и т. д. Дальше включение отдельных ком­понент в построение можно настроить, например, при помощи утилиты CMake с графическим интерфейсом (рис. 2.9). ∗
145
2. Основы языка CMake
Рис. 2.9. Редактирование переменных кэша в утилите CMake
с графическим интерфейсом пользователя
2.8.4. function(), endfunction(), return()
function(hимя_функцииifhпараметр1i ... hпараметрnig)
hкомандыi
endfunction()
return()
Команда function() запоминает все команды, следующие после неё до соответствующей команды endfunction(), без их исполнения. Кроме этого, создаётся новая команда с именем hимя_функцииi. При её вызове сохранённые ранее команды ис­полняются. При этом все ссылки на формальные параметры вида ${hпараметр1i} заменяются значениями фактических аргу- ментов, переданных команде.
146
2.8. Команды управляющих конструкций
Любую команду, определённую при помощи function(), можно вызывать с переменным количеством аргументов. Для доступа к ним можно использовать специальные переменные, приведённые в табл. 2.11.
Таблица 2.11
Специальные переменные CMake для доступа
к аргументам функций
Перменная Значение
ARGC Общее количество аргументов
ARGV0, ARGV1,
. ..
Первый, второй и т. д. фактические аргумен­ты
ARGV Список всех аргументов
ARGN Список дополнительных аргументов, пере-
данных в дополнение к объявленным
ПРИМЕР В следующем фрагменте кода:
function(dump_vars)
message(STATUS ==============)
message(STATUS "Dumping ${ARGC} variables:")
foreach(VAR_NAME ${ARGN})
message(
STATUS " ${VAR_NAME} == \"${${VAR_NAME}}\"")
endforeach()
message(STATUS ==============)
147
2. Основы языка CMake
endfunction()
dump_vars(DATA GREETING VALUES)
создаётся команда с именем dump_vars, которая выполняет отладочную печать значений всех переменных, имена кото­рых передаются ей в качестве аргументов. Список аргумен­тов ${ARGN} обрабатывается при помощи команды foreach() (п. 2.8.3). Команда message() (п. 2.4.4) в теле цикла печа­тает имя очередной переменной, которое хранится в пере­менной VAR_NAME (подстановка ${VAR_NAME}), и её значение
(${${VAR_NAME}}).
Вызов команды dump_vars() в последней строке приводит
к выводу на печать следующей информации:
-- ==============
-- Dumping 3 variables:
-- DATA == "message(Hello)"
-- GREETING == "Hello"
-- VALUES == "a;b;c\;d"
-- ==============
Замечания:
∗
— При помощи языковых конструкций вида «${hаргументi}»
и «${${hаргументi}}» можно организовать передачу в функ­ции переменных по ссылке.
148
2.8. Команды управляющих конструкций
— Функциональностью, аналогичной команде dump_vars()
из приведённого выше примера, обладает команда
cmake_print_variables() из стандартного модуля CMake
CMakePrintHelpers.
— В стандартном модуле CMakeParseArguments определена
команда cmake_parse_arguments(), которая предназначе-
на для облегчения синтаксического разбора списков аргу-
ментов функций. С её помощью можно определять тре-
бования для аргументов функций, аналогичные стандарт-
ным командам CMake.
ПРИМЕР
function(quote VAR_NAME)
set(${VAR_NAME} "\"${${VAR_NAME}}\"" PARENT_SCOPE)
endfunction()
set(STR "some string")
message(${STR})
quote(STR)
message(${STR})
N
Здесь создаётся пользовательская команда quote(), кото­рой передаётся имя переменной. Команда добавляет в начало и конец значения этой переменной символы двойных кавы­чек. Изменение переменной осуществляется командой set() (п. 2.7.1) с аргументом PARENT_SCOPE, так как переменная нахо-
149
2. Основы языка CMake
дится во внешней по отношению к функции quote() области действия (п. 2.2.3).
В результате исполнения последних четырёх строк кода
на печать будет выведена следующая информация:
some string
"some string"
Команда return(), как и в других языках программирова-
ния, позволяет досрочно прервать выполнение пользователь-
∗
ской команды и передать управление следующей за ней ко­манде. Также команда return() способна прервать выполне­ние текущего модуля CMake и обработку подпроекта. Таким образом, этой командой можно досрочно прервать исполне­ние команд include() (п. 2.4.3), add_subdirectory() (п. 2.5.3) и find_package() (п. 2.11.1). Наконец, командой return() мож­но прервать обработку описания проекта верхнего уровня.

2.9. Команды работы с файлами

2.9.1. get_filename_component()

get_filename_component(
hимя_переменнойi hпуть_к_файлуi hкомпонентi
f
CACHEg)
get_filename_component(
150
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]