Добавил:
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.9. Команды работы с файлами
hимя_переменнойi hкомандаi
g
PROGRAMfPROGRAM_ARGS hимя_переменной_аргументовi
f
CACHEg)
С помощью команды get_filename_component() в первой
форме можно выделить из заданного пути файловой системы
(передаётся команде вторым аргументом) нужную часть (имя,
расширение и т. д.) или преобразовать путь к абсолютной форме. Относительные пути интерпретируются по отношению к каталогу текущего подпроекта. При этом файл или каталог, к которому указывается путь, не обязательно должен существовать.
Возвращаемые пути содержат символы «/» в качестве раздели-
телей имён каталогов и не содержат последнего символа «/».
Результат выполнения команды записывается в переменную, имя которой передаётся в качестве первого аргумента. Третий аргумент определяет, что именно должно быть получено
в качестве результата (табл. 2.12).
Таблица 2.12
Значения третьего аргумента команды
get_filename_component(), определяющие
возвращаемый результат
Аргумент Возвращаемый результат
DIRECTORY Каталог, содержащий заданный файл
или каталог
NAME Имя с расширением без каталога
EXT Расширение (часть имени от первой точки)
151

2. Основы языка CMake
Окончание табл. 2.12
Аргумент Возвращаемый результат
NAME_WE Имя без каталога и расширения (до первой
точки)
ABSOLUTE Полный путь относительно каталога под-
проекта
REALPATH Как ABSOLUTE, но с разрешением символи-
ческих ссылок
Замечание: значение REALPATH является единственным, при ко-
тором исполнение команды приводит к попытке обращения
к файлу по указанному пути.
N
— При помощи необязательного аргумента CACHE можно по-
местить результирующую переменную в кэш.
Вторая форма команды ищет исполняемый файл по заданной командной строке с учётом системных путей поиска исполняемых файлов (значение переменной окружения PATH и т. д.).
Возвращается полный путь к файлу или пустая строка, если
файл не найден.
— После необязательного аргумента PROGRAM_ARGS можно
указать имя переменной, в которую будут записаны аргу-
менты команды (начиная с первого пробела).
ПРИМЕР
Пусть требуется указать в описании проекта список файлов,
из которых должна собираться некоторая цель. При этом
152

2.9. Команды работы с файлами
для некоторых из этих CPP-файлов в каталоге проекта также
существуют соответствующие им H-файлы, которые в списке
не указаны. Их нужно найти и также включить в цель.
Эту задачу можно решить при помощи следующего файла
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(ex-find-h)
set(
FILES_SRC
main.cpp source1.cpp subdir/source2.cpp)
set(FILES_H)
foreach(SRC IN LISTS FILES_SRC)
get_filename_component(
SRC_EXT "${SRC}" EXT)
if(SRC_EXT STREQUAL .cpp)
get_filename_component(
SRC_FULL "${SRC}" ABSOLUTE)
get_filename_component(
SRC_DIR "${SRC_FULL}" DIRECTORY)
get_filename_component(
SRC_NAME "${SRC}" NAME_WE)
set(SRC_H "${SRC_DIR}/${SRC_NAME}.h")
if(
EXISTS "${SRC_H}" AND
153

2. Основы языка CMake
NOT IS_DIRECTORY "${SRC_H}")
message(STATUS "Found ${SRC_H}")
list(APPEND FILES_H "${SRC_H}")
endif()
endif()
endforeach()
add_executable(ex-find-h ${FILES_SRC} ${FILES_H})
Здесь список файлов в переменной FILES_SRC обходится
командой foreach() (п. 2.8.3). Для каждого пути выделяется
расширение файла и проверяется, что оно равно строке «.cpp».
Дальше путь к файлу преобразуется к абсолютной форме, затем
из него выделяются каталог и имя без расширения. Из них строится имя H-файла и проверяется, что такой файл существует
и является файлом, а не каталогом, при помощи команды if()
(п. 2.8.1). Если это так, путь добавляется к списку в переменной
FILES_H при помощи команды list(APPEND ...) (п. 2.7.3). ∗
Замечание: в make, CMake и других системах построения суще-
ствуют средства для поиска файлов с заданными расширениями в каталоге проекта и автоматического их добавления к целям. Такой подход является плохой практикой, так как добавление новых исходных файлов не приводит к изменению описаний проектов. Из-за этого механизм автоматического перестроения в таких случаях не срабатывает и возникают непредвиденные ошибки времени компоновки. Кроме того, сильно замедляется построение крупных проектов. При этом поиск и автомати-
154

2.9. Команды работы с файлами
ческое включение заголовочных файлов, продемонстрированные в примере выше, вполне допустимы, так как заголовочные
файлы не передаются системой построения на обработку компилятору, а только используются интегрированными средами
разработки для отображения в списке исходных файлов.
N
2.9.2. find_file(), find_library(), find_path(),
find_program()
Эти команды предназначены для поиска файла общего
назначения (find_file() — как правило, заголовочных файлов), каталога, содержащего заданный файл (find_path()),
библиотеки (find_library()) или исполняемого файла
(find_program()) по заданным именам в указываемых каталогах, а также в некоторых стандартных каталогах.
Замечание: если программный пакет поддерживает систему
CMake, для его использования вместо описанных здесь команд
предпочтительнее применять более высокоуровневую команду
find_package() (п. 2.11.1).
N
Все команды имеют почти одинаковый синтаксис аргументов и позволяют указать множество дополнительных аргументов для исключения тех или иных стандартных каталогов из поиска. Ниже приведён сокращённый вариант синтаксиса с основными настройками.
hимя_командыi(
hимя_переменнойi
hальтернативные_именаi
155

2. Основы языка CMake
f
HINTS hпуть
i ... hпуть
1,1
ifENV hимя_окружения1i
1,m
f
PATHS hпуть
i ... hпуть
2,1
ifENV hимя_окружения2i
2,p
f
PATH_SUFFIXES hсуффикс1i ... hсуффиксki
f
DOC hстрока_документацииig)
hимя_командыi F
find_file
find_library
hальтернативные_именаi F
hимяi
NAMES hимя1i ... hимяni
Команды сначала проверяют наличие переменной с задан-
find_path
g g
g g
g
find_program
ным именем в кэше. Только если переменной там нет или её
значение равно «...-NOTFOUND» (см. также табл. 2.1), команды выполняют поиск и записывают найденный путь первого
встреченного файла, удовлетворяющего критериям, в переменную кэша. Если файл не был найден, в переменную запишется
значение «hимя_переменнойi-NOTFOUND». Таким образом, при последующих запусках инструмента CMake без очистки кэша ранее удавшийся поиск пропускается и генерирование проектов
для конечной системы построения выполняется быстрее.
— После аргумента NAMES указывается одно или несколь-
ко альтернативных имён искомого файла . Команда
find_program() может добавить к ним расширение ис-
156
полняемого файла, специфичное для системы, на которой
выполняется инструмент CMake. Аналогично, команда
find_library() может добавлять префикс в начале име-

2.9. Команды работы с файлами
ни и расширение в конце, например «libhимяi.so». Если
указывается одно имя, аргумент NAMES можно не переда-
вать.
— После необязательного аргумента HINTS можно указать до-
полнительные пути для поиска файла. Здесь рекомендует-
ся указывать пути, которые были ранее найдены в резуль-
тате исследования системы, например каталоги, где рас-
положены другие ранее найденные файлы. После необяза-
тельного аргумента ENV можно указать имя переменной
окружения, из которой будут прочитаны дополнительные
пути поиска.
— Необязательный аргумент PATHS аналогичен аргументу
HINTS, однако в отличие от него указываемые здесь пу-
ти будут проверены в последнюю очередь (о порядке про-
смотра путей см. ниже). Здесь рекомендуется указывать
при необходимости жёстко заданные пути к каталогам, та-
кие как C:\Program Files\SomeProg или /usr/local. Ес-
ли другие необязательные аргументы не указаны (вклю-
чая NAMES), аргумент PATHS также можно не передавать,
указывая в команде пути к каталогам сразу после един-
ственного имени файла.
— После необязательного аргумента PATH_SUFFIXES можно
указать дополнительные подкаталоги, которые будут ис-
пользованы для поиска в каждом из каталогов.
157

2. Основы языка CMake
— После необязательного аргумента DOC можно указать стро-
ку документации, которая будет записана в кэш для создаваемой переменной (см. описание команды set(), п. 2.7.1).
Поиск файла выполняется внутри каталогов в следующем
порядке:
1) Каталоги, пути к которым указаны в переменных кэша
CMake:
— Команды find_file() и find_path() ищут в катало-
гах:
— hпутьi/include для всех путей из специаль-
ной переменной CMAKE_PREFIX_PATH. Также,
если установлено значение специальной переменной CMAKE_LIBRARY_ARCHITECTURE (ар-
хитектура библиотек), используются каталоги
hпутьi/include/hархитектураi.
— Пути из переменной CMAKE_INCLUDE_PATH.
— Пути из переменной CMAKE_FRAMEWORK_PATH.
— Команда find_library() ищет в каталогах:
— hпутьi/lib для всех путей из специальной
переменной CMAKE_PREFIX_PATH. Также, если установлено значение специальной переменной CMAKE_LIBRARY_ARCHITECTURE, ис-
158
пользуются каталоги hпутьi/lib/hархитектураi.
При необходимости для заданной архитектуры также выполняется поиск в каталогах
lib64 (чтобы повлиять на это, можно вручную

2.9. Команды работы с файлами
установить значение глобального свойства
FIND_LIBRARY_USE_LIB64_PATHS).
— Пути из переменной CMAKE_LIBRARY_PATH.
— Пути из переменной CMAKE_FRAMEWORK_PATH.
— Команда find_program() ищет в каталогах:
— hпутьi/bin и hпутьi/sbin для путей из перемен-
ной CMAKE_PREFIX_PATH.
— Пути из переменной CMAKE_PROGRAM_PATH.
— Пути из переменной CMAKE_APPBUNDLE_PATH.
2) Аналогично пункту 1, но вместо указанных переменных
CMake используются одноимённые переменные окружения.
3) Пути, переданные командам после аргумента HINTS.
4) Пути, перечисленные в переменной окружения PATH. Ко-
манды find_file() и find_path() также используют переменную INCLUDE, а команда find_library() — LIB.
5) Аналогично пункту 1, но вместо переменных кэша CMake с именами CMAKE_..._PATH используются специальные переменные CMake с именами в форме CMAKE_SYSTEM_..._PATH (например,
CMAKE_SYSTEM_PREFIX_PATH).
6) Пути, переданные командам после аргумента PATHS.
В системах, которые не используют имени диска и т. п.
в начале полного пути, возможно перенаправление поиска в ка-
159

2. Основы языка CMake
талоги, пути к которым добавляются в виде префиксов в начало всех перечисленных выше путей. Это может быть удобно
для выполнения кросс-компиляции, когда файлы сборки для целевой системы располагаются в отдельных каталогах. Поиск выполняется в следующем порядке:
1) Префиксы путей, перечисленные в специальной переменной CMake CMAKE_FIND_ROOT_PATH. При этом пути, попадающие в каталог, путь к которому хранится в переменной
CMAKE_STAGING_PREFIX (путь установки при кросс-компиляции), не изменяются.
2) Префикс из специальной переменной CMAKE_SYSROOT.
3) Далее выполняется поиск в исходных каталогах без пре-
фиксов.
Пример создания цели вызова архиватора 7-zip при помо-
щи команды add_custom_target() на с. 192 также демонстрирует использование команды find_program(). Пример подключения библиотеки Crypto++ на с. 350 демонстрирует использование команд find_library() и find_path().
2.10. Команды добавления специальных целей
2.10.1. configure_file()
configure_file(
hвходной_файлi hвыходной_файлi
f
COPYONLY
160
g f
ESCAPE_QUOTES
g f
g
@ONLY
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
