Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Система построения проектов CMake. Учебник.pdf
X
- •Введение
- •Модульное программирование
- •Автоматизация построения проектов
- •Обзор инструментов построения проектов
- •qmake
- •Генераторы
- •Входные файлы
- •Пути
- •Синтаксис
- •Команды
- •Упражнения
- •Тест рубежного контроля
- •Проектное задание
- •Основные концепции
- •Строки
- •Свойства
- •Примеры простых проектов
- •Команды общего назначения
- •cmake_minimum_required()
- •project()
- •include()
- •message()
- •Команды описания целей
- •add_executable()
- •add_library()
- •add_subdirectory()
- •Команды настроек целей
- •include_directories()
- •target_include_directories()
- •add_definitions(), add_compile_options()
- •target_compile_definitions()
- •target_compile_options()
- •target_compile_features()
- •target_link_libraries()
- •add_dependencies()
- •Команды обработки данных
- •math()
- •list()
- •Команды управляющих конструкций
- •foreach(), endforeach()
- •Команды работы с файлами
- •get_filename_component()
- •Команды добавления специальных целей
- •configure_file()
- •add_test(), enable_testing()
- •install()
- •add_custom_target()
- •Прочие команды
- •find_package()
- •get_property(), set_property()
- •Виды конфигураций
- •Выражения генераторов
- •Информационные выражения
- •Логические выражения
- •Преобразующие выражения
- •Вспомогательные выражения
- •Упражнения
- •Тест рубежного контроля
- •Проектное задание
- •Интерфейс подключения библиотек
- •Подключение заголовочной библиотеки
- •Частичная подмена стандартной библиотеки
- •Интерфейс подключения библиотек
- •Локализация приложения
- •Установка приложения
- •Инструменты разработки
- •Управление версиями
- •Генерирование документации
- •Упражнения
- •Тест рубежного контроля
- •Проектное задание
- •Заключение
- •Библиография
- •Ответы на тесты

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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
