Добавил:
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.2. Boost
" nor Boost library was found. Please install "
"Boost.")
endif()
endif()
endif()
add_executable(ex-shared ex-shared.cpp compatibility.h)
Здесь значение истины присваивается специальной переменной CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS для того, чтобы можно было не повторять условия в аргументах команд (elseif() и т. д., старое требование CMake). Начиная с CMake версии 2.6 такое присваивание излишне, однако в этом описании запрашивается совместимость с версией
2.4. Также по причине совместимости используется команда
add_definitions() вместо add_compile_options() для передачи флага «-std=c++11». Перед запуском первой тестовой компиляции в случае компилятора gcc ему передаётся этот флаг (включение совместимости со стандартом C++11) через переменную
CMAKE_REQUIRED_FLAGS. Перед второй проверкой значение переменной очищается, так как старые компиляторы gcc не понимают флагов «-std=...» и реагируют на них ошибкой.
Тестирование приведённого кода показывает, что он выбирает пространство имён std в операционной системе Windows 7
с компиляторами Microsoft Visual C++2012 и TDM-GCC 4.9.2, а также в Windows XP с компилятором Microsoft Visual C++2010. В системе Slackware 12.0 с компилятором gcc 4.1.2 он использует про-
291

3. Примеры использования пакетов
странство std::tr1. И наконец, в системе Windows XP с компиляторами Microsoft Visual C++6.0, 2008 и gcc-MinGW 3.4.5 и библиотекой Boost 1.35.0 он использует пространство имён boost.
Замечания:
— В более сложных ситуациях вместо использования услов-
ных директив препроцессора в файле compatibility.h
может оказаться удобнее генерировать файл в каталоге построения при помощи команды configure_file()
(п. 2.10.1).
∗
— Другим способом проверки соответствия компилятора
стандарту C++11 является проверка значения макроса
__cplusplus. Следует, однако, учитывать, что старые ком-
пиляторы могут его не поддерживать либо устанавливать
его значениями, отличными от стандартного.
N
3.3. Qt
3.3.1. Интерфейс подключения библиотек
Qt6содержит большой набор библиотек и инструментов
для реализации каркасов приложений с поддержкой графического интерфейса пользователя, а также других возможностей,
востребованных в крупных проектах (многопоточность, сетевые взаимодействия, интерфейс с различными СУБД и т. д.). Основной задачей Qt является обеспечение переносимости кода,
6
http://www.qt.io/ (дата обращения: 25.02.2015).
292

3.3. Qt
написанного с его применением, на большое количество настольных, встроенных и мобильных платформ. При этом быстродействие и размеры программного кода остаются на приемлемом уровне по сравнению с эквивалентным ему кодом, реализованным на местных API (при существенном выигрыше в скорости разработки и переносимости). Qt доступен в нескольких
вариантах лицензий — от свободных (GNU GPL v2, LGPL v2.1 и 3)
до коммерческих с дополнительными возможностями.
Современные версии Qt (5.x.x) распространяются вместе
с конфигурационными файлами CMake. Кроме этого, в CMake
есть стандартные модули для подключения Qt версий 3 и 4. В настоящем учебнике будут рассмотрены вопросы, связанные с использованием Qt 57.
На сайте Qt доступны предварительно собранные библиотеки в виде разделяемых модулей для различных платформ
и компиляторов. Статические варианты можно собрать самостоятельно из исходных кодов. При одновременном использовании для разработки статических и динамических библиотек их следует устанавливать в разные каталоги. Таким образом, выбор варианта используемых библиотек Qt можно определять, например, значением переменной CMAKE_PREFIX_PATH,
записывая в неё нужный каталог. Кроме этого, может понадобиться настройка проекта для использования статических библиотек аналогично примеру с подключением OpenCV на с. 258.
В дальнейшем будем рассматривать использование динамических (разделяемых) библиотек.
7
В [14] отдельная глава посвящена использованию CMake совместно с Qt 4.
293

3. Примеры использования пакетов
Использовать нужно тот же самый компилятор, которым были собраны библиотеки. При установке версии для
gcc-MinGW можно дополнительно установить сам компилятор
в подкаталог Qt.
Замечание: при одновременно установленных в систе-
ме нескольких вариантах сборки Qt необходимо следить
за тем, чтобы инструмент CMake при исполнении команды
find_package() находил ту версию, которая соответствует
выбранному генератору. В противном случае можно получить
ошибки компоновки, из которых будет трудно понять причину
возникновения проблемы.
N
Способ подключения Qt зависит от версии CMake. Минимальной поддерживаемой версией является 2.8.3. При использовании 2.8.11 или выше интерфейс подключения выглядит
проще всего — за счёт доступных в ней аргументов INTERFACE/
PUBLIC в командах target_include_directories() (п. 2.6.2)
и т. д. Общая схема в таком случае будет следующей:
# ...
find_package(
Qt5fhверсияigREQUIRED hкомпонент1i ... hкомпонентmi)
# или если подключается только один компонент:
# find_package(Qt5hкомпонентifhверсияigREQUIRED)
add_executable(hцельi WIN32 hфайл1i ... hфайлni)
target_link_libraries(hцельi Qt5::hкомпонентki ...)
294

# ...
При необходимости в команде поиска указывается мини-
мальная версия, с которой должен связываться проект.
Замечания:
— Передача имени компонента Qt5 команде find_package()
(вместо Qt5hкомпонентi) также требует указания хотя бы од-
ного компонента, иначе исполнение конфигурационного
файла Qt приведёт к выводу сообщения об ошибке.
— Не со всеми используемыми компонентами требуется свя-
3.3. Qt
зывание при помощи команды target_link_libraries().
— Поиск и подключение некоторых компонент автоматиче-
ски подключает другие, от которых они зависимы. Например, подключение библиотеки Widgets также приводит
к подключению библиотек Core и Gui.
— Если приложение использует консоль, аргумент WIN32 ко-
манды add_executable() необходимо не указывать.
N
Если используется CMake версии 2.8.9 или выше, вместо команды target_link_libraries() можно использовать команду, которая определяется в конфигурационном файле компонента Core (становится доступной после вызова find_package()):
qt5_use_modules(
hимя_целиi
f
LINK_PUBLIC
...
LINK_PRIVATEghкомпонент1i
295

3. Примеры использования пакетов
f
LINK_PUBLIC
LINK_PRIVATEghкомпонентni)
— Необязательные аргументы LINK_PUBLIC/LINK_PRIVATE
имеют такой же смысл, как аргументы PUBLIC/PRIVATE
команд target_link_libraries() (п. 2.6.7) и т. п.
Эта команда используется следующим образом:
# ...
find_package(Qt5Widgets)
add_executable(hцельi WIN32 hфайл1i ... hфайлni)
qt5_use_modules(hцельi Widgets)
target_link_libraries(
hцельi
${Qt5Core_QTMAIN_LIBRARIES})
Здесь и в следующем фрагменте кода в переменной
Qt5Core_QTMAIN_LIBRARIES содержится имя цели библиотеки
qtmain, в которой определяется точка входа в программу для
компилятора Microsoft Visual C++. Эта библиотека автоматически подключается, если приложение должно работать в системе
Windows без отображения консоли (см. также пример подключе-
ния библиотек OpenCV на с. 258). Если приложению требуется
выводить информацию на консоль, обращение к этой перемен-
296

3.3. Qt
ной необходимо убрать из команды target_link_libraries(),
как и аргумент WIN32 команды add_executable().
Наконец, если версия CMake ниже 2.8.9 (но не ниже 2.8.3),
необходимо устанавливать отдельными командами все требуемые настройки проекта в соответствующих переменных, которые инициализируются в результате вызова find_package().
В этом случае необходимо вызывать find_package() для каждого компонента по отдельности, в результате будут создаваться
аналогичные переменные Qt5hкомпонентi_INCLUDE_DIRS и т. д.
# ...
find_package(Qt5Widgets)
set(FLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_definitions(${Qt5Widgets_DEFINITIONS})
add_executable(hцельi WIN32 hфайл1i ... hфайлni)
target_link_libraries(
hцельi
${Qt5Widgets_LIBRARIES}
${Qt5Core_QTMAIN_LIBRARIES})
297

3. Примеры использования пакетов
В дальнейшем будем предполагать, что используется
CMake версии 2.8.11 или выше.
ПРИМЕРЫ
1) Рассмотрим простейшую программу с пользовательским
интерфейсом на основе Qt [1] (ex-qt-hello.cpp):
#include <QApplication>
#include <QLabel>
int main(int nArgC, char *apszArgV[])
{
QApplication app(nArgC, apszArgV);
QLabel *pLabel = new QLabel("Hello Qt!");
pLabel->show();
//
return app.exec();
}
Файл CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.11)
project(ex-qt-hello)
298
find_package(Qt5Widgets)
add_executable(ex-qt-hello WIN32 ex-qt-hello.cpp)
target_link_libraries(ex-qt-hello Qt5::Widgets)

3.3. Qt
Здесь командой cmake_minimum_required() устанавливается совместимость с версией 2.8.11, начиная с которой
поддерживается связывание с библиотеками Qt при помощи команды target_link_libraries().
В Windows команды запуска CMake из каталога построения
могут быть следующими:
set PATH=C:\Qt5.5.0\Tools\mingw492_32\bin;%PATH%
set QT_PATH=C:\Qt5.5.0\5.5\mingw492_32
cmake^
-G "MinGW Makefiles"^
-D CMAKE_PREFIX_PATH=%QT_PATH%^
D:\Work\ex-qt-hello
Первая команда может пригодиться в случае использования компилятора gcc-MinGW, чтобы генератор CMake создал правила с вызовами инструментов из каталога установки библиотеки.
Собранное для платформы Windows приложение будет зависеть от библиотеки Qt Qt5Widgets.dll, которая, в свою
очередь, зависит от Qt5Core.dll и Qt5Gui.dll (или, если сборка происходила в отладочной конфигурации, от их
отладочных версий Qt5Widgetsd.dll и т. д.). Библиотека
Core зависит от библиотек ICU (International Components
for Unicode)8. Также, если используется компилятор MinGW,
приложение будет зависеть от его библиотек поддержки
8
http://site.icu-project.org/ (дата обращения: 02.03.2015).
299

3. Примеры использования пакетов
исполнения программ. Таким образом, для работоспособности приложения необходимо поместить в каталог с ним
(или поместить путь их расположения в переменную окру-
жения PATH) библиотеки, перечисленные в табл. 3.6.
Библиотеки, от которых зависит приложение,
использующее компонент Qt Core
Библиотека Примечание
icudt53.dll
International Components for
icuin53.dll
Unicode
icuuc53.dll
Таблица 3.6
libgcc_s_dw2-1.dll*Поддержка способа обработки
9
++
libstdc++-6.dll
исключений DW2
*
Стандартная библиотека C
Qt5Core.dll
Qt5Gui.dll
Или их отладочные варианты
Qt5Widgets.dll
*
Только для компилятора gcc-MinGW.
Все эти библиотеки расположены в подкаталоге bin каталога установки Qt.
2) Рассмотрим консольное приложение, использующее компонент Qt Concurrent:
#include <QApplication>
9
http://tdm-gcc.tdragon.net/quirks (дата обращения: 02.03.2015).
300
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
