Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Система построения проектов CMake. Учебник.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
2.12. Поддержка нескольких конфигураций построения
от системы участки кода в один или несколько заголо­вочных файлов. Для каждого интерфейса прикладных про­грамм существует своя версия заголовочных файлов. Раз­ные версии называются одинаково, но расположены в раз­ных подкаталогах (рис. 2.15).
hкаталог проектаi
include
posix
feature1.h
...
Windows
feature1.h
...
...
Рис. 2.15. Часть структуры каталога проекта с разными
версиями заголовочных файлов
Теперь для правильной сборки приложения достаточно
обеспечить передачу компилятору нужного каталога для поиска заголовочных файлов, чтобы в исходном коде ди­рективы вида:
#include "feature1.h"
подключали нужную версию файла. Выражение генерато­ров $<PLATFORM_ID> заменяется на имя операционной си­стемы, его можно использовать при определении катало­гов поиска:
target_include_directories(
prog
241
2. Основы языка CMake
PRIVATE
"${CMAKE_SOURCE_DIR}/include/$<PLATFORM_ID>")
Тогда в каталоге проекта include нужно создать подката-
логи с именами операционных систем, для которых дол­жен быть собран проект. Однако такой подход приведёт к ненужному дублированию заголовочных файлов, так как целый ряд операционных систем поддерживают интер­фейс POSIX. Чтобы избежать использования символиче­ских ссылок в каталоге проекта, можно усложнить исполь­зуемое выражение генераторов следующим образом:
set(
POSIX_SYSTEMS
Darwin FreeBSD Linux NetBSD OpenBSD)
set(EXPRESSION "")
foreach(SYSTEM IN LISTS POSIX_SYSTEMS)
set(TEST $<PLATFORM_ID:${SYSTEM}>)
if(EXPRESSION)
set(EXPRESSION ${EXPRESSION},${TEST})
else()
set(EXPRESSION ${TEST})
endif()
242
endforeach()
set(EXPRESSION $<OR:${EXPRESSION}>)
set(INC_DIR "${CMAKE_SOURCE_DIR}/include/")
2.12. Поддержка нескольких конфигураций построения
target_include_directories(
prog
PRIVATE
$<${EXPRESSION}:${INC_DIR}posix>
$<$<NOT:${EXPRESSION}>:${INC_DIR}$<PLATFORM_ID>>)
Здесь для удобства сложное выражение формируется на ос­нове списка в переменной POSIX_SYSTEMS. Цикл foreach() генерирует в переменной EXPRESSION выражение, прове­ряющее принадлежность имени системы заданному спис­ку:
$<OR:$<PLATFORM_ID:Darwin>,$<PLATFORM_ID:FreeBSD>,
...>
Дальше это выражение используется в двух условных вы­ражениях:
$<${EXPRESSION}:hкаталог1i>
$<$<NOT:${EXPRESSION}>:hкаталог2i>
Первое выражение после вычисления заменяется на стро­ку hкаталог1i, если выражение в EXPRESSION окажется ис­тинным, и на пустую строку иначе. Второе выражение, на­оборот, заменится на hкаталог2i, если условие будет лож­ным. При этом первый путь будет указывать на подкаталог
«posix», а второй — на подкаталог с именем целевой систе-
мы. ∗
243
2. Основы языка CMake
Замечание: здесь команде target_include_directories() пе- редаются абсолютные пути. Если ей передать относительные пути, инструмент CMake выведет сообщение об ошибке. При­чиной её будет использование выражений генераторов в пу­тях. Так как относительные пути преобразуются в абсолют­ные на этапе исполнения команд CMake, инструмент не может знать, во что преобразуются выражения генераторов на более позднем этапе, и не сможет выполнить корректное преобразо­вание путей в абсолютные.
N
ПРИМЕР В замечании к примеру на с. 188 утверждалось, что использо­вание команды target_include_directories() (п. 2.6.2) для библиотеки, устанавливаемой командой install(EXPORT ...) (п. 2.10.3), осложнено тем, что каталог проекта библиотеки и ка­талог её установки не совпадают. При сборке подключающих библиотеку целей, определённых в том же проекте верхнего уровня, что и сама библиотека, нужно использовать один ката­лог поиска, а при сборке целей из других проектов — другой.
Рассмотрим решение этой проблемы с помощью выраже­ний генераторов. Пусть структура каталогов проекта и уста­новки библиотеки должна быть такой, как она изображена на рис. 2.16 (пусть для сборки библиотеки используется компи­лятор gcc или подобный).
Файл CMakeLists.txt проекта библиотеки:
cmake_minimum_required(VERSION 2.8)
244
2.12. Поддержка нескольких конфигураций построения
hкаталог проектаi
include
my_lib.h
my_lib.cpp
CMakeLists.txt
Рис. 2.16. Структура каталогов проекта и установки
project(my_lib)
add_library(
hкаталог установкиi
include
my_lib.h
lib
libmy_lib.a
share
my_lib.cmake
my_lib-noconfig.cmake
библиотеки
my_lib STATIC
my_lib.cpp include/my_lib.h)
set(DIR "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(
my_lib
PUBLIC
$<BUILD_INTERFACE:${DIR}/include>
$<INSTALL_INTERFACE:include>)
install(
TARGETS my_lib
EXPORT my_lib
RUNTIME
245
2. Основы языка CMake
DESTINATION bin
LIBRARY
DESTINATION lib
ARCHIVE
DESTINATION lib)
install(
FILES include/my_lib.h
DESTINATION include)
install(
EXPORT my_lib
DESTINATION share)
Здесь цель установки определена при помощи трёх команд install() аналогично примеру на с. 182. Основ­ным отличием этого примера является использование ко­манды target_include_directories() с аргументами, со­держащими рассмотренные ранее выражения генераторов $<BUILD_INTERFACE:...> и $<INSTALL_INTERFACE:...>. Пер­вое из них при вычислении заменяется на свой аргумент при подключении библиотеки к цели того же проекта, и на пу­стую строку — при подключении установленной библиотеки из внешнего проекта (при помощи сгенерированного целью установки сценария share/my_lib.cmake). Второе выражение действует противоположным образом. ∗
246
2.12. Поддержка нескольких конфигураций построения
Замечание: как и в предыдущем примере, аргумент выра- жения генераторов $<BUILD_INTERFACE:...>, которое пе­редаётся команде target_include_directories(), должен быть полным путём. Однако путь в аргументе выражения $<INSTALL_INTERFACE:...> уже должен указываться относи­тельно каталога установки. Это необходимо для того, чтобы команда цели установки смогла корректно сгенерировать код сценария для подключения библиотеки. Также допустимо указание абсолютных путей с использованием ранее рассмот­ренного выражения $<INSTALL_PREFIX>.
N

2.12.6. Вспомогательные выражения

Вспомогательные выражения генераторов (табл. 2.17) ис­пользуются для обхода ограничений синтаксиса самих выраже­ний генераторов: при помощи них можно вставить в вычисля­емое выражение символы запятой, закрывающей угловой скоб­ки и т. д.
Таблица 2.17
Вспомогательные выражения генераторов
Выражение Результат
ANGLE-R «>» («больше»)
COMMA «,» («запятая»)
SEMICOLON «;» («точка с запятой»)
247
2. Основы языка CMake
Окончание табл. 2.17
Выражение Результат
TARGET_NAME:hстрокаi Отмечает заданную строку как имя
цели
*
Имя цели в выражении может содержать символы запятой
*
и двоеточия, не допустимые в аргументах других выражений генераторов. Однако имя цели здесь должно быть литералом
(не вложенным выражением).

2.13. Упражнения

2.13.1. Тест рубежного контроля

1. При исполнении системой CMake следующего фрагмента ко­да:
set(DATA a b c)
message(${DATA})
будет выведено:
(a) abc; (b) a b c; (c) a;b;c; (d) a\;b\;c.
2. При исполнении системой CMake следующего фрагмента ко­да:
set(DATA a;b;c)
message(${DATA})
248
2.13. Упражнения
будет выведено:
(a) abc; (b) a b c; (c) a;b;c; (d) a\;b\;c.
3. При исполнении системой CMake следующего фрагмента ко­да:
set(DATA a\;b\;c)
message(${DATA})
будет выведено:
(a) abc; (b) a b c; (c) a;b;c; (d) a\;b\;c.
4. При исполнении системой CMake следующего фрагмента ко­да:
set(DATA "a b c")
message(${DATA})
будет выведено:
(a) abc; (b) a b c; (c) a;b;c; (d) a\;b\;c.
5. При исполнении системой CMake следующего фрагмента ко­да:
set(DATA "a;b;c")
message(${DATA})
будет выведено:
(a) abc; (b) a b c; (c) a;b;c; (d) a\;b\;c.
249
2. Основы языка CMake
6. При исполнении системой CMake следующего фрагмента ко­да:
set(DATA "a\;b\;c")
message(${DATA})
будет выведено:
(a) abc; (b) a b c; (c) a;b;c; (d) a\;b\;c.
7. При исполнении системой CMake следующего фрагмента ко­да:
set(DATA a b c)
message("${DATA}")
будет выведено:
(a) abc; (b) a b c; (c) a;b;c; (d) a\;b\;c.
8. Пусть требуется в файле CMakeLists.txt корневого про­екта подключить подпроект, находящийся в подкаталоге library_1. При помощи какой команды это можно сделать?
(a) include(library_1/CMakeLists.txt);
(b) add_subdirectory(library_1);
(c) include_directories(library_1).
9. Пусть файл CMakeLists.txt для библиотеки имеет следую­щее содержимое:
add_library(my_lib file1.cpp file1.h)
Пусть в проекте приложения, подключающем эту библио­теку, требуется настроить путь к заголовочному файлу
250
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]