Добавил:
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.5. Команды описания целей
Окончание табл. 2.4
Режим Описание Обработка Генерация
DEPRECATION Использование
зависит от настроек
устаревшей
возможности
*
При исполнении команды message(DEPRECATION ...) поведение системы CMake зависит от значений специальных переменных CMAKE_ERROR_DEPRECATED и CMAKE_WARN_DEPRECATED.
Если первая из них содержит значение «истина» (см. табл. 2.1),
поведение аналогично режиму FATAL_ERROR, иначе, если вторая содержит значение «истина», — режиму WARNING. Иначе
обработка файла и генерация продолжаются, и сообщение
не выводится. По умолчанию обе переменные содержат зна-
*
чение FALSE.
2.5. Команды описания целей
2.5.1. add_executable()
add_executable(
hлогическое_имя_целиi
f
WIN32
hисходный_модуль1i ... hисходный_модульni)
g f
MACOSX_BUNDLE
g f
EXCLUDE_FROM_ALL
g
81

2. Основы языка CMake
Команда добавляет к проекту цель с заданным логическим
именем, построение которой из указанных исходных модулей
должно привести к созданию исполняемого файла.
Имя исполняемого файла формируется из имени цели
и расширения «.exe» (на платформе Windows). Изменить имя
можно также при помощи установки свойства OUTPUT_NAME цели (см. пример на с. 214).
По умолчанию файл должен создаваться в подкаталоге
построения, соответствующем текущему обрабатываемому подкаталогу проекта. Изменить этот каталог можно при помощи установки соответствующего свойства цели, которое изначально инициализируется значением специальной переменной CMAKE_RUNTIME_OUTPUT_DIRECTORY. Конечные системы построения, которые поддерживают множественные конфигурации (Micsrosoft Visual Studio, XCode и т. д.), могут добавлять к этому пути ещё один вложенный каталог, соответствующий имени
используемой конфигурации (Debug, Release и т. д.).
— Передача команде необязательного аргумента WIN32
приводит к тому, что при построении для платфор-
мы Windows приложение не будет иметь создаваемой
по умолчанию консоли, даже если главной функцией
программы является функция main(), а не WinMain().
Это достигается передачей компоновщику аргумента ко-
82
мандной строки, зависящего от компилятора. Например,
для системы gcc-MinGW компоновщику передаётся ключ
-Wl,--subsystem,windows. Это бывает удобно, в частности, для разработки с использованием библиотек Qt.

2.5. Команды описания целей
При использовании аргумента WIN32 можно обойтись
без функции WinMain(), таким образом, упростить переносимость кода. Для остальных платформ этот аргумент
игнорируется.
— Передача необязательного аргумента MACOSX_BUNDLE сооб-
щит системе CMake, что создаваемый исполняемый файл
должен быть пакетом приложения системы OS X.
— Передача необязательного аргумента EXCLUDE_FROM_ALL
приведёт к тому, что генерируемая цель будет исключена
из цели «all». Таким образом, например, при работе с системой make команда make или make all приведёт к построению данной цели, только если от неё зависимы другие цели, включённые в цель «all».
Замечание: при использовании компилятора Microsoft Visual
C++передачи аргумента WIN32 команде add_executable() недо-
статочно, если требуется использовать функцию main() в качестве точки входа. В этом случае также требуется передача
компоновщику ключа «/ENTRY:mainCRTStartup» (см. пример
на с. 258).
N
2.5.2. add_library()
add_library(
hлогическое_имя_целиi
f
STATIC
f
EXCLUDE_FROM_ALL
hисходный_модуль1i ... hисходный_модульni)
SHARED
MODULE
g
g
83

2. Основы языка CMake
add_library(
hлогическое_имя_целиi
hтип_библиотекиi
IMPORTED)
hтип_библиотекиi F SHARED
Первая форма команды add_library() аналогична коман-
де add_executable() (п. 2.5.1), но создаёт цель для построения
библиотеки.
Имя библиотеки будет сформировано из базового име-
ни (по умолчанию соответствующего имени цели): например,
«hимяi.lib» для компилятора Microsoft Visual C++, «libhимяi.a»
для gcc и т. д.
По умолчанию библиотека будет создана в подкаталоге
построения, соответствующем текущему обрабатываемому подкаталогу проекта. Изменить расположение библиотеки можно
STATIC
MODULE
UNKNOWN
при помощи установки соответствующих свойств цели, которые инициализируются значениями специальных переменных
(табл. 2.5). Как и в случае с командой add_executable(), конечные системы построения могут добавлять к этим путям каталог
с именем используемой конфигурации.
84

2.5. Команды описания целей
Таблица 2.5
Специальные переменные, определяющие выходные
каталоги для библиотек
Переменная Виды библиотек
CMAKE_ARCHIVE_OUTPUT_DIRECTORY статические (+импорта)
CMAKE_RUNTIME_OUTPUT_DIRECTORY DLL
CMAKE_LIBRARY_OUTPUT_DIRECTORY модули, разделяемые
— Тип библиотеки можно задать при помощи необязательно-
го аргумента:
STATIC: статическая;
SHARED: динамическая (разделяемая);
MODULE: разделяемая, предназначенная исключитель-
но для загрузки при помощи функций API (POSIX
dlopen() и т. п.). Такой тип библиотеки используется для реализации загружаемых модулей (plugins).
См. пример определения и использования такой
библиотеки на с. 230.
По умолчанию создаются правила для построения разделяемой библиотеки, если переменная BUILD_SHARED_LIBS содержит истинное значение, и статической, если иначе.
Таблица 2.5 нуждается в пояснении. При построении все
статические библиотеки помещаются в каталог, определяемый переменной CMAKE_ARCHIVE_OUTPUT_DIRECTORY. Аналогично, все загружаемые модули попадают в каталог, путь к кото-
85

2. Основы языка CMake
рому задаётся переменной CMAKE_LIBRARY_OUTPUT_DIRECTORY.
Сложнее обстоит дело с разделяемыми библиотеками. Дело
в том, что в POSIX-совместимых системах разделяемые библиотеки принято помещать в специальные каталоги — туда же,
где находятся и статические библиотеки. При создании процесса динамический загрузчик исполняемого файла будет искать все требуемые для него библиотеки в этих каталогах. Некоторые из этих путей могут быть заданы системой (переменная окружения LD_LIBRARY_PATH и т. д.). Другие из этих путей могут храниться в относительном виде в самом исполняемом файле («rpath»). Если библиотеки будут расположены в другом месте, загрузчик не сможет их найти. Как правило, исполняемые файлы помещаются в каталог с именем bin, а разделяемые библиотеки — в находящийся рядом каталог lib. Таким образом, разделяемые библиотеки помещаются при построении в каталог, путь к которому задаётся переменной
CMAKE_LIBRARY_OUTPUT_DIRECTORY.
В системах, совместимых с Windows, динамические библиотеки ищутся загрузчиком прежде всего в тех же каталогах,
что и исполняемые файлы. Например, динамическая библиотека может находиться в том же каталоге, что и использующая её программа. По этой причине динамические библиотеки создаются при построении проекта в таких системах в том
же каталоге, что и исполняемые модули, т. е. путь к которому находится в переменной CMAKE_RUNTIME_OUTPUT_DIRECTORY.
При этом для облегчения процесса подключения динамической
библиотеки к использующему её приложению при её постро-
86

2.5. Команды описания целей
ении также создаётся небольшая статическая библиотека, содержащая информацию об экспортируемых символах динамической (так называемая библиотека импорта — import library).
Как и другие статические библиотеки, библиотеки импорта помещаются в каталог, путь к которому определяется переменной
CMAKE_ARCHIVE_OUTPUT_DIRECTORY.
ПРИМЕР
Пусть проект включает исполняемый файл и две библиотеки,
которые он использует. Пусть структура каталога проекта соответствует рис. 2.4.
my_project .................................... каталог проекта
my_library_1 .....................подкаталог библиотеки 1
...
CMakeLists.txt .........описание проекта библиотеки 1
my_library_2 .....................подкаталог библиотеки 2
...
CMakeLists.txt .........описание проекта библиотеки 2
my_program ............... подкаталог проекта программы
...
CMakeLists.txt .......... описание проекта приложения
CMakeLists.txt ..........описание проекта верхнего уровня
Рис. 2.4. Структура каталога проекта с исполняемым файлом
и двумя библиотеками
В этом случае для формирования при построении системы выходных каталогов, совместимой с рекомендациями GNU,
можно использовать следующее описание для системы CMake:
project(my_project)
87

2. Основы языка CMake
set(BINARY_DIR "${CMAKE_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BINARY_DIR}/lib")
add_subdirectory(my_library_1)
add_subdirectory(my_library_2)
add_subdirectory(my_program)
Здесь специальная переменная CMAKE_BINARY_DIR хранит
полный путь к каталогу построения проекта верхнего уровня.
Вместо неё в этом примере можно использовать переменную
CMAKE_CURRENT_BINARY_DIR, в которой хранится путь к каталогу построения текущего (под)проекта.
В результате обработки этого примера инструментом
CMake и сборки проекта в системе Windows каталог построения
будет иметь структуру, изображённую на рис. 2.5, а в POSIX-совместимой системе — как на рис. 2.6. Как можно видеть, в системе Windows все выходные файлы будут помещены в один каталог, так что при отладке приложения загрузчик сможет найти
все требуемые ему библиотеки. То же самое будет справедливым и для систем, совместимых с POSIX. ∗
Вторая форма команды add_library() предназначена для
добавления к проекту внешней заранее собранной библиотеки (как правило, сторонней). Как и для предыдущей формы
команды, создаётся цель с заданным логическим именем, которая по умолчанию имеет область видимости текущего ката-
88

2.5. Команды описания целей
build_my_project ..........................каталог построения
bin
my_library_1.dll
my_library_2.dll
my_program.exe
lib
my_library_1.lib ..................библиотеки импорта
my_library_2.lib
my_library_1
...................................промежуточные файлы
my_library_2
...................................промежуточные файлы
my_program
...................................промежуточные файлы
...
Рис. 2.5. Структура каталога построения в системе Windows
лога построения и ниже и которую можно использовать, как
и остальные цели библиотек, для связывания с другими целями проекта при помощи команды target_link_libraries()
(п. 2.6.7). Однако в этом случае не создаётся никаких правил
построения библиотеки. Чтобы указать местоположение файла библиотеки для создаваемой цели, необходимо записать
его в свойство цели IMPORTED_LOCATION, а также в свойства
IMPORTED_LOCATION_DEBUG и т. д. для каждой используемой конфигурации (подробнее о конфигурациях см. п. 2.12.1) при помощи команды set_property() (п. 2.11.2). Для получения пути
к исполняемому файлу библиотеки можно использовать команду find_library() (п. 2.9.2).
Вообще говоря, использовать дополнительную команду
add_library(... IMPORTED) для того, чтобы подключить
89

2. Основы языка CMake
build_my_project ..........................каталог построения
bin
my_program ............................исполняемый файл
lib
libmy_library_1.so ............разделяемые библиотеки
libmy_library_2.so
my_library_1
...................................промежуточные файлы
my_library_2
...................................промежуточные файлы
my_program
...................................промежуточные файлы
...
Рис. 2.6. Структура каталога построения
в POSIX-совместимой системе
внешнюю библиотеку, необязательно, так как команда
target_link_libraries() может получать на вход непосредственно пути к файлам библиотек вместо логических имён
их целей. Однако команда позволяет существенно упростить
повторное использование библиотеки, поскольку для определяемой ею цели можно настроить свойства, используемые
при построении зависимых целей (например, каталоги поиска
заголовочных файлов). Таким образом, эти свойства не нужно
устанавливать заново для каждой цели, к которой подключается библиотека. К сожалению, цель библиотеки, которая
определяется этой командой, нельзя передавать первым параметром командам target_include_directories() (п. 2.6.2)
и т. п. Однако можно устанавливать соответствующие свойства
цели командой set_property() (п. 2.11.2), что менее удобно,
но всё равно не влияет на удобство описания зависимых целей.
90
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
