Добавил:
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()
- •Виды конфигураций
- •Выражения генераторов
- •Информационные выражения
- •Логические выражения
- •Преобразующие выражения
- •Вспомогательные выражения
- •Упражнения
- •Тест рубежного контроля
- •Проектное задание
- •Интерфейс подключения библиотек
- •Подключение заголовочной библиотеки
- •Частичная подмена стандартной библиотеки
- •Интерфейс подключения библиотек
- •Локализация приложения
- •Установка приложения
- •Инструменты разработки
- •Управление версиями
- •Генерирование документации
- •Упражнения
- •Тест рубежного контроля
- •Проектное задание
- •Заключение
- •Библиография
- •Ответы на тесты

3.3. Qt
${FILES_TO_TRANSLATE})
target_link_libraries(
ex-qt-translate Qt5::Widgets)
Здесь при помощи команды find_package() запрашивается использование модуля LinguistTools, в котором определены команды, создающие правила генерирования файлов перевода. Переменной FILES_TO_TRANSLATE присваивается список исходных файлов, которые должны обрабатываться инструментом lupdate. По мере развития проекта сюда можно будеть добавлять другие файлы с расширениями «.cpp», «.h»,
«.ui» и т. д. Переменной TS_FILES присваивается список пу-
тей к промежуточным TS-файлам, создаваемым в каталоге проекта. Их имена должны иметь приведённый выше формат
(«ex-qt-translate_hязыкi.qm», где hязыкi является именем, возвращаемым функцией QLocale::name() для тех языков, для
которых требуется локализация). При помощи логической настройки проекта UPDATE_TRANSLATIONS определяется, нужно ли
генерировать правила для создания промежуточных TS-файлов
в каталоге проекта или только результирующих QM-файлов. Последнее может пригодиться для ускорения процесса сборки, если разработчик в настоящее время не занят обновлением пользовательского интерфейса.
Для удобства запуска правил создания файлов перевода
при помощи команды add_custom_target() создаётся фальшивая цель с именем translations, которая зависит от QMфайлов.
331

3. Примеры использования пакетов
Вызов команды qt5_create_translation() имеет один
нежелательный побочный эффект. Дело в том, что цель clean,
создаваемая генераторами для make-файлов, удаляет все сгенерированные в результате выполнения правил файлы. То же самое относится к цели translations, результатом выполнения
которой является создание файлов TS в каталоге проекта. После
выполнения цели clean эти файлы будут также удалены, что
может привести к потере результатов долгой работы по локализации. Чтобы обойти эту проблему, у каталога текущего подпроекта устанавливается в истину свойство CLEAN_NO_CUSTOM, что
приводит к исключению файлов, генерируемых правилами команд add_custom_command(), из числа удаляемых целью clean.
В результате, правда, при исполнении этой цели также не удаляются файлы QM в каталоге построения.
Чтобы правила создания TS-файлов сработали без ошибок,
необходимо в самом начале в каталоге проекта вручную создать
пустой каталог translations. Далее можно выполнить следующие команды (на примере системы Linux Mint/Ubuntu):
cmake ~/work/ex-qt-translate # каталог проекта
make # сборка исполняемого файла
make translations # генерирование TS и «пустых» QM
/usr/lib/x86_64-linux-gnu/qt5/bin/linguist # правка TS
make translations # генерирование QM
После выполнения третьей команды каталог проекта будет иметь структуру, представленную на рис. 3.12.
332

hкаталог проектаi
translations
ex-qt-translate_ru_RU.ts ....создаётся инструментом lupdate
ex-qt-translate.cpp
CMakeLists.txt
Рис. 3.12. Структура каталога проекта с файлом перевода,
сгенерированным инструментом lupdate
Четвёртая команда запускает редактор Qt Linguist
(рис. 3.13).
3.3. Qt
Рис. 3.13. Редактирование исходного файла перевода
при помощи инструмента Qt Linguist
После завершения редактирования последняя команда со-
здаёт в каталоге построения файл ex-qt-translate_ru_RU.qm.
Замечания:
— Пакет LinguistTools не определяет целей для связы-
вания с библиотеками, поэтому для его использования
333
∗

3. Примеры использования пакетов
не нужно передавать дополнительных аргументов коман-
дам target_link_libraries().
— При запуске приложения этого примера из интегрирован-
ной среды Microsoft Visual Studio для него в качестве рабо-
чего каталога устанавливается каталог построения (в кото-
ром расположены файлы проекта). Так как QM-файл гене-
рируется в этом же каталоге, запускаемое приложение на-
ходит его, хотя оно и расположено в подкаталоге с именем
конфигурации («Debug» и т. д.). Если запустить приложе-
ние, например из проводника Windows, оно уже не сможет
найти его.
N
3.3.4. Установка приложения
Приложения, использующие библиотеки Qt, имеют зависимости от некоторых вспомогательных файлов. Это могут быть
разделяемые библиотеки Qt, загружаемые модули (plugins), библиотеки поддержки времени исполнения компиляторов, файлы локализации и т. д. В таких условиях становится актуальной задача автоматизации установки приложения или выгрузки его вместе со всеми необходимыми для его работы файлами
в отдельный каталог для подготовки пакета установки. Для облегчения этой задачи в CMake, помимо команды install()
(п. 2.10.3), также может быть использован стандартный мо-
дуль DeployQt4. Несмотря на название, он вполне работоспособен по отношению к приложениям, разрабатываемым с помощью Qt версии 5, если для этого приложить небольшие усилия
(см. пример ниже). В нём определено несколько команд, однако
334

3.3. Qt
основной, из которой вызываются все остальные, является команда install_qt4_executable(). Она при помощи команды
install(CODE ...) добавляет к цели install код, который выполняет копирование в каталог установки требуемых библиотечных модулей. Команда использует другой стандартный модуль — BundleUtilities. Он предназначен для подготовки автономных пакетов приложений (application bundles) системы
OS X, однако также способен создавать в других системах директории, имеющие свойства пакетов (автономность, переносимость на другие компьютеры).
Замечание: как станет понятно из приведённого далее примера,
на самом деле модуль DeployQt4 можно использовать для установки разделяемых модулей, от которых зависит любое приложение, а не только использующее библиотеки Qt.
N
Синтаксис команды install_qt4_executable():
install_qt4_executable(
hисполняемый_файлifhмодули_Qtifhбиблиотекиi
f
hкаталогиifhкаталог_модулей_Qtifhписать_qt.confi
f
hимя_компонентаi
Если в аргументах команды со второго по четвёртый необ-
ходимо передать несколько элементов, они отделяются точка-
g gg gg g
)
ми с запятой и помещаются в двойные кавычки, чтобы CMake
не воспринял их как несколько отдельных аргументов (п. 2.2.2).
Команда выполняет копирование всех несистемных разде-
ляемых и загружаемых модулей, от которых зависит заданный
335

3. Примеры использования пакетов
исполняемый модуль. В результате в каталог приложения копируются все нужные библиотеки Qt, если только они не установлены вместе с системой (например, установлены из репозитариев Linux). Затем команда выполняет (зависящую от системы) правку исполняемого модуля и разделяемых модулей так,
чтобы их можно было копировать и запускать на других системах, для которых эти модули совместимы на уровне системных
библиотек. Зависимости определяются средствами стандартного модуля CMake GetPrerequisites, который пытается использовать для этого внешние утилиты dumpbin (поставляется вместе со средствами разработки Microsoft, также может быть установлена отдельно), objdump (входит в состав MinGw), ldd (Linux
и т. п.) и otool (OS X).
— В качестве аргумента hисполняемый_файлi команде пере-
даётся относительный путь к исполняемому файлу, кото-
рый требуется проанализировать на зависимости. Путь
задаётся относительно каталога установки (переменная
окружения DESTDIR + специальная переменная CMake
CMAKE_INSTALL_PREFIX). На момент установки файл дол-
жен быть уже скопирован в указанное место, т. е. перед
командной install_qt4_executable() нужно вызвать ко-
манду install(TARGETS ...) для цели приложения.
— В необязательном аргументе hмодули_Qti перечисляются
загружаемые модули Qt, от которых зависит прило-
жение и которые также должны быть установлены
в соответствующий каталог. В отличие от разделяемых
модулей библиотек, зависимость от которых определена
336

3.3. Qt
в исполняемом файле, загружаемые модули активизируются во время работы программы вызовами специальных API (см. пример на с. 230), поэтому команда
install_qt4_executable() не может самостоятельно
определить эти зависимости. В аргументе перечисляются
либо пути к библиотечным файлам, либо их имена (для
модулей из состава Qt: qjpeg, qsqlite и т. д.). В последнем
случае пути должны храниться в переменных CMake
«QT_hимя_в_верхнем_регистреi_PLUGIN_DEBUG
RELEASE».
Такие переменные создаются модулем поиска пакета Qt4,
но не Qt5. При использовании Qt5 их можно создавать
самостоятельно.
— В необязательном аргументе hбиблиотекиi в дополнение
к модулям передаются пути к другим загружаемым модулям, разделяемым библиотекам и исполняемым файлам,
которые также нужно исправить для возможности автономной работы.
— В необязательном аргументе hкаталогиi перечисляются до-
полнительные пути к каталогам, в которых будет выполняться поиск библиотечных модулей, представляющих зависимости. Также для поиска будут использоваться каталоги, указанные в системных настройках (например, перечисленные в переменной окружения PATH
в Windows), а также перечисленные в переменных CMake
QT_LIBRARY_DIR и QT_BINARY_DIR. Эти переменные создаются модулем поиска пакета Qt4. Если используется Qt5, их
можно создать самостоятельно (см. пример ниже).
337

3. Примеры использования пакетов
— В необязательном аргументе hкаталог_модулей_Qti передаёт-
ся путь к каталогу, куда будут скопированы разделяемые
модули (по умолчанию в каталог приложения или специ-
альный каталог в OS X). Этот путь будет добавлен в файл
настроек qt.conf в каталоге приложения — так, чтобы он
использовался Qt для поиска загружаемых модулей.
— Передачей значения «ложь» в качестве необязательного
логического аргумента hписать_qt.confi можно запретить
команде сохранять путь к загружаемым модулям в файл
настроек qt.conf. В этом случае приложение может, на-
пример, самостоятельно передать нужный ему путь с мо-
дулями функции QCoreApplication::addLibraryPath().
— Необязательный аргумент hимя_компонентаi может быть
передан команде install() в качестве имени компонента
после аргумента COMPONENT (п. 2.10.3).
ПРИМЕР
Пусть требуется к проекту из предыдущего примера (с. 328) добавить цель установки с каталогом, имеющим структуру, представленную на рис. 3.14.
Файл ex-qt-deploy.cpp аналогичен CPP-файлу из предыдущего примера за исключением указания пути, по которому
объект translator должен искать файл локализации:
#include <QApplication>
#include <QTranslator>
#include <QMessageBox>
338

hкаталог установкиi
bin
ex-qt-deploy ... (+ расширение) — исполняемый модуль
hразделяемые модулиi
translations
ex-qt-deploy_ru_RU.qm
Рис. 3.14. Структура каталога установки программы,
использующей библиотеки Qt
int main(int nArgC, char *apszArgV[])
{
QApplication app(nArgC, apszArgV);
3.3. Qt
//
QTranslator translator;
const bool cbLoaded = translator.load(
QLocale::system(), "ex-qt-deploy_", "",
app.applicationDirPath() + "/../translations/");
//
// ... (как в предыдущем примере)
} // main()
Здесь функции QTranslator::load() последним аргументом передаётся путь к каталогу translations относительно каталога, где расположен сам исполняемый файл (возвращается функцией QCoreApplication::applicationDirPath()). Символы «/ », разделяющие компоненты пути, библиотека QtCore
при необходимости заменит на нужные символы для текущей
платформы. Таким образом, каталог файлов локализации определяется независимо от текущего каталога программы.
339

3. Примеры использования пакетов
Файл CMakeLists.txt отличается от предыдущего коман-
дами определения цели установки:
cmake_minimum_required(VERSION 2.8.11)
project(ex-qt-deploy)
# ... (аналогично предыдущему примеру)
# Installation
install(
TARGETS ex-qt-deploy
RUNTIME DESTINATION bin)
install(
FILES ${QM_FILES}
DESTINATION translations)
get_property(
LIB_QT5CORE_PATH
TARGET Qt5::Core
PROPERTY IMPORTED_LOCATION_RELEASE)
get_filename_component(
QT_LIBRARY_DIR "${LIB_QT5CORE_PATH}" DIRECTORY)
set(
340
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
