2020-04-11 12:13:41 +00:00
|
|
|
|
= CMake: управление проектом
|
|
|
|
|
:title-separator: {sp}|
|
|
|
|
|
:category: Программирование
|
2020-04-14 09:17:22 +00:00
|
|
|
|
:tags: программирование, cmake, qt
|
2020-04-14 13:54:05 +00:00
|
|
|
|
ifdef::lang[include::attributes-{lang}.adoc[]]
|
2020-04-11 12:13:41 +00:00
|
|
|
|
:toc:
|
|
|
|
|
|
|
|
|
|
== Полезные ссылки
|
|
|
|
|
|
|
|
|
|
* https://github.com/onqtam/awesome-cmake[Каталог ссылок]
|
|
|
|
|
* https://cgold.readthedocs.io/en/latest/index.html[CGold: The Hitchhiker’s Guide to the CMake]
|
|
|
|
|
|
|
|
|
|
== Структура каталогов проекта
|
|
|
|
|
|
|
|
|
|
Файлы проекта и результаты компиляции размещаются в каталогах:
|
|
|
|
|
|
|
|
|
|
....
|
|
|
|
|
└── project
|
|
|
|
|
├── _build
|
|
|
|
|
│ ├── debug
|
|
|
|
|
│ │ ├── bin
|
|
|
|
|
│ │ ├── etc
|
|
|
|
|
│ │ ├── files
|
|
|
|
|
│ │ │ ├── data
|
|
|
|
|
│ │ │ ├── lib
|
|
|
|
|
│ │ │ └── log
|
|
|
|
|
│ │ ├── include
|
|
|
|
|
│ │ └── lib
|
|
|
|
|
│ └── release
|
|
|
|
|
├── .git
|
|
|
|
|
├── .gitlab-ci
|
|
|
|
|
├── cmake
|
|
|
|
|
│ ├── cmlib
|
|
|
|
|
│ ├── doc
|
|
|
|
|
│ ├── etc
|
|
|
|
|
│ │ └── uncrustify
|
|
|
|
|
│ ├── find
|
|
|
|
|
│ └── generators
|
|
|
|
|
├── doc
|
|
|
|
|
├── files
|
|
|
|
|
│ ├── data
|
|
|
|
|
│ ├── etc
|
|
|
|
|
│ ├── lib
|
|
|
|
|
│ └── log
|
|
|
|
|
├── l10n
|
|
|
|
|
├── src
|
|
|
|
|
│ ├── app
|
|
|
|
|
│ └── lib
|
|
|
|
|
├── thirdparty
|
|
|
|
|
└── tools
|
|
|
|
|
....
|
|
|
|
|
|
|
|
|
|
Назначение каталогов приведено в таблице.
|
|
|
|
|
|
2020-04-14 13:54:05 +00:00
|
|
|
|
.Назначение каталогов
|
2020-04-11 12:13:41 +00:00
|
|
|
|
[cols="2,4",options="header",]
|
|
|
|
|
|===
|
|
|
|
|
|Каталог | Назначение
|
|
|
|
|
|`_build` | Результаты компиляции
|
|
|
|
|
|`_build/debug` | Результаты компиляции в режиме отладки
|
|
|
|
|
|`_build/debug/bin` | Исполняемые файлы
|
|
|
|
|
|`_build/debug/etc` | Символическая ссылка на каталог `cmex/files/etc`
|
|
|
|
|
|`_build/debug/files/data` | Символическая ссылка на каталог `cmex/files/data`
|
|
|
|
|
|`_build/debug/files/lib` | Символическая ссылка на каталог `cmex/files/lib`
|
|
|
|
|
|`_build/debug/files/log` | Символическая ссылка на каталог `cmex/files/log`
|
|
|
|
|
|`_build/debug/include` | Заголовочные файлы копируемые и генерируемые во время сборки
|
|
|
|
|
|`_build/debug/lib` | Статические и динамические библиотеки
|
|
|
|
|
|`_build/release` | Результаты компиляции в режиме выпуска (иерархия аналогична `debug`)
|
|
|
|
|
|`.git` | Системные файлы репозитория git
|
|
|
|
|
|`.gitlab.ci` | Шаблон правил для автоматической сборки на сервере Gitlab
|
|
|
|
|
|`cmake` | Файлы с дополнительными функциями для CMake
|
|
|
|
|
|`cmake/cmlib` | Библиотека функций для CMake
|
|
|
|
|
|`cmake/doc` | Правила для автоматической генерации документации
|
|
|
|
|
|`cmake/etc` | Файлы настроек, используемые в CMake
|
|
|
|
|
|`cmake/etc/uncrustify` | Файл настройки для программы автоматического форматирования исходных текстов
|
|
|
|
|
|`cmake/find` | Модули CMake для поиска внешних программ и библиотек
|
|
|
|
|
|`cmake/generators` | Генераторы проектов
|
|
|
|
|
|`doc` | Документация для проекта
|
|
|
|
|
|`files` | Каталог для дополнительных файлов
|
|
|
|
|
|`files/etc` | Каталог для файлов настроек проекта
|
|
|
|
|
|`files/data` | Каталог для неизменяемых файлов
|
|
|
|
|
|`files/lib` | Каталог для изменяемых файлов
|
|
|
|
|
|`files/log` | Каталог для журналов
|
|
|
|
|
|`l10n` | Файлы переводов
|
|
|
|
|
|`src` | Исходные тексты
|
|
|
|
|
|`src/app` | Исходные тексты программы
|
|
|
|
|
|`src/lib` | Исходные тексты библиотеки
|
|
|
|
|
|`thirdparty` | Исходные тексты дополнительных и сторонних проектов
|
|
|
|
|
|`tools` | Дополнительные утилиты
|
|
|
|
|
|===
|
|
|
|
|
|
|
|
|
|
Каталог `_build` создаётся, чтобы избежать попадания создаваемых во время
|
|
|
|
|
сборки файлов в иерархию основного проекта. Запись результатов сборки
|
|
|
|
|
проекта внутрь иерархии каталогов с исходными текстами приводит к
|
|
|
|
|
засорению формируемыми на этапе сборки файлами, которые затрудняют
|
|
|
|
|
разработку, поиск в оригинальных файлах и мешают ориентироваться в
|
|
|
|
|
проекте. При работе с несколькими типами сборки, например, отладка и
|
|
|
|
|
выпуск, появляется необходимость корректного полного удаления
|
|
|
|
|
результатов предыдущего тип сборки.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[base-project]]
|
|
|
|
|
== Базовый проект
|
|
|
|
|
|
|
|
|
|
Проект, в котором выполнены приведённые в данном разделе действия,
|
|
|
|
|
можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-base[здесь]
|
|
|
|
|
или сделать его копию командой:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-base
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
=== Инициализация подмодулей
|
|
|
|
|
|
|
|
|
|
Для начала нужно создать каталог для проекта, перейти в него и
|
|
|
|
|
инициализировать репозиторий git:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
mkdir cmlib-example-base
|
|
|
|
|
cd cmlib-example-base
|
|
|
|
|
git init
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Для подключения основных подмодулей, содержащих дополнительные функции
|
|
|
|
|
для работы с проектом, и фиксации произведённого изменения нужно выполнить:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git submodule add https://git.246060.ru/f1x1t/cmlib.git cmake/cmlib
|
|
|
|
|
git submodule add https://git.246060.ru/f1x1t/cmake-find.git cmake/find
|
|
|
|
|
git submodule add https://git.246060.ru/f1x1t/cmake-generators.git cmake/generators
|
|
|
|
|
git submodule add https://git.246060.ru/f1x1t/cmake-doc.git cmake/doc
|
|
|
|
|
git submodule add https://git.246060.ru/f1x1t/uncrustify-config.git cmake/etc/uncrustify
|
|
|
|
|
git commit -a -m "Начало проекта"
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Отправить изменения в проекте на сервер и сделать ветку `master` основной
|
|
|
|
|
(можно пропустить):
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git remote add origin АДРЕС_РЕПОЗИТОРИЯ_НА_СЕРВЕРЕ
|
|
|
|
|
git push -u origin master
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Загрузить шаблоны для автоматической сборки проекта в разных вариантах
|
|
|
|
|
программных окружений и зафиксировать изменения:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
mkdir .gitlab-ci
|
|
|
|
|
wget -O .gitlab-ci/scheduled.yml https://git.246060.ru/f1x1t/gitlab-ci/raw/branch/master/.gitlab-ci/scheduled.yml
|
|
|
|
|
wget -O .gitlab-ci.yml https://git.246060.ru/f1x1t/gitlab-ci/raw/branch/master/.gitlab-ci.yml
|
|
|
|
|
git add .gitlab-ci.yml .gitlab-ci/scheduled.yml
|
|
|
|
|
git commit -m "Настройка автосборки"
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Загрузить файл настройки для анализатора Clang-Tidy:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
wget https://git.246060.ru/f1x1t/clang-tidy-config/raw/branch/master/.clang-tidy
|
|
|
|
|
git add .clang-tidy
|
|
|
|
|
git commit -m "Настройка Clang-Tidy"
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Создать стандартные файлы и каталоги:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
mkdir -p doc/breathe
|
|
|
|
|
touch doc/breathe/index.md.in
|
|
|
|
|
mkdir -p files/etc
|
|
|
|
|
touch files/etc/.keep-directory
|
|
|
|
|
mkdir -p files/data
|
|
|
|
|
touch files/data/.keep-directory
|
|
|
|
|
mkdir -p files/lib
|
|
|
|
|
touch files/lib/.keep-directory
|
|
|
|
|
mkdir -p files/log
|
|
|
|
|
touch files/log/.keep-directory
|
|
|
|
|
git add doc files
|
|
|
|
|
git commit -m "Стандартные файлы и каталоги"
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Создать файл `.gitignore` для исключения каталогов и файлов из-под контроля git:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
wget https://git.246060.ru/f1x1t/cmlib-gitignore/raw/branch/master/.gitignore
|
|
|
|
|
git add .gitignore
|
|
|
|
|
git commit -m "Шаблон для игнорирования каталогов и файлов"
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=== Базовые инструкции в CMake
|
|
|
|
|
|
|
|
|
|
В корневом каталоге проекта нужно создать файл `CMakeLists.txt`:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Минимальная версия CMake
|
|
|
|
|
cmake_minimum_required(VERSION 3.3)
|
|
|
|
|
|
|
|
|
|
# Предпочтительно следовать стандартам принятым в указанном диапазоне версий
|
|
|
|
|
cmake_policy(VERSION 3.0.2..3.7)
|
|
|
|
|
|
|
|
|
|
# Название и версия проекта и используемые языки программирования
|
|
|
|
|
project(cmlib-example-base VERSION 0.2.0 LANGUAGES C CXX)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Значение версии следует формировать согласно правилам
|
|
|
|
|
https://semver.org/lang/ru/[семантического версионирования].
|
|
|
|
|
|
|
|
|
|
Для подключения функций для CMake из библиотеки CMLib, нужно добавить
|
|
|
|
|
в файл `CMakeLists.txt` строки:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# В каталоге cmake/cmlib находятся файлы с библиотечными функциями
|
|
|
|
|
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmlib)
|
|
|
|
|
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/cmlib)
|
|
|
|
|
else()
|
|
|
|
|
message(FATAL_ERROR "CMake library directory does not exist")
|
|
|
|
|
endif()
|
|
|
|
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/find)
|
|
|
|
|
|
|
|
|
|
include(CMLibCommon)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
[[variables-cmake]]
|
|
|
|
|
В каталоге `cmake/etc` требуется создать файл `Variables.cmake`,
|
|
|
|
|
в котором должны быть определены переменные, используемые
|
|
|
|
|
библиотекой CMLib для архивирования исходных текстов, автоматического
|
|
|
|
|
создания пакетов, генерации документации:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
set(ORGANIZATION_NAME "org")
|
|
|
|
|
set(AUTHOR_NAME "John Doe")
|
|
|
|
|
|
|
|
|
|
set(DOXYGEN_PROJECT_TITLE "Пример проекта (начало)")
|
|
|
|
|
set(DOXYGEN_GENERATE_LATEX YES)
|
|
|
|
|
set(DOXYGEN_GENERATE_HTML YES)
|
|
|
|
|
|
|
|
|
|
set(CPACK_GENERATOR "TXZ;DEB")
|
|
|
|
|
set(CPACK_PACKAGE_CONTACT "John Doe <box@mail.domain>")
|
|
|
|
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "CMake project example")
|
|
|
|
|
set(CPACK_DEBIAN_PACKAGE_SECTION "misc")
|
|
|
|
|
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
|
|
|
|
set(CPACK_SOURCE_IGNORE_FILES
|
|
|
|
|
"${CMAKE_BINARY_DIR}"
|
|
|
|
|
"/\\\\.git/"
|
|
|
|
|
"/\\\\.gitlab-ci/"
|
|
|
|
|
"^${CMAKE_SOURCE_DIR}/.?build.?/"
|
|
|
|
|
"^${CMAKE_SOURCE_DIR}/.?output.?/"
|
|
|
|
|
"^${CMAKE_SOURCE_DIR}/files/lib"
|
|
|
|
|
"^${CMAKE_SOURCE_DIR}/files/log"
|
|
|
|
|
"\\\\.clang-tidy$"
|
|
|
|
|
"\\\\.cmake-format$"
|
|
|
|
|
"\\\\.gitignore$"
|
|
|
|
|
"\\\\.gitattributes$"
|
|
|
|
|
"\\\\.gitmodules$"
|
|
|
|
|
"\\\\.gitlab-ci.yml"
|
|
|
|
|
"CMakeLists.txt.user.*"
|
|
|
|
|
"~$"
|
|
|
|
|
"\\\\.swp$")
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-11 12:13:41 +00:00
|
|
|
|
Произведённые изменения можно зафиксировать:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git add cmake/etc/Variables.cmake CMakeLists.txt
|
|
|
|
|
git commit -m "Подключение библиотеки CMLib"
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Чтобы проверить корректность подключения CMLib, можно выполнить команду:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
(mkdir -p _build && cd _build && cmake .. && make && echo OK)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Если последней строкой вывода будет `OK`, то настройка завершена верно.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
== Поиск системных библиотек
|
|
|
|
|
|
|
|
|
|
Поиск программ, библиотек и заголовочных файлов, установленных в системе, можно
|
|
|
|
|
выполнять с помощью программы https://en.wikipedia.org/wiki/Pkg-config[`pkg-config`]
|
|
|
|
|
или функции CMake `find_package`. В любом случае для указания того,
|
|
|
|
|
что наличие искомого объекта обязательно для сборки, используется
|
|
|
|
|
параметр `REQUIRED`.
|
|
|
|
|
|
|
|
|
|
=== Поиск с помощью программы `pkg-config`
|
|
|
|
|
|
|
|
|
|
Программа `pkg-config` хранит базу данных параметров (обычно в каталогах
|
|
|
|
|
`/usr/share/pkgconfig`, `/usr/lib/pkgconfig` и `/usr/lib/x86_64-linux-gnu/pkgconfig`),
|
|
|
|
|
содержащую флаги компиляции для поиска заголовочных файлов и компоновки
|
|
|
|
|
библиотек, установленных в систему. Для использования в CMake сначала
|
|
|
|
|
необходимо выполнить проверку наличия программы `pkg-config` в системе
|
|
|
|
|
и подключить определённую в модуле `PkgConfig` функцию `pkg_check_modules`.
|
|
|
|
|
Например, для поиска библиотек `gsl`, `fftw3` и `udev` можно написать
|
|
|
|
|
в файле `CMakeLists.txt`:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Поиск библиотек с помощью pkgconfig
|
|
|
|
|
find_package(PkgConfig REQUIRED)
|
|
|
|
|
pkg_check_modules(GSL REQUIRED gsl)
|
|
|
|
|
pkg_check_modules(FFTW3 REQUIRED fftw3)
|
|
|
|
|
pkg_check_modules(UDEV udev)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
=== Поиск с помощью функции `find_package`
|
|
|
|
|
|
|
|
|
|
Если системная библиотека поставляется без файла описания для `pkg-config`
|
|
|
|
|
или необходимо произвести более сложный поиск, например, включающий поиск
|
|
|
|
|
исполняемого файла, то может быть написан специальный модуль для `CMake`,
|
|
|
|
|
который вызывается функцией `find_package`. Примеры вызова функции:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Поиск с помощью функции find_package
|
|
|
|
|
find_package(LibXml2)
|
|
|
|
|
find_package(CURL REQUIRED)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
== Автоматически генерируемый заголовочный файл
|
|
|
|
|
|
|
|
|
|
На этапе конфигурирования проекта можно сгенерировать файл, в который
|
|
|
|
|
будут записаны собранные значения параметров. В библиотеке CMLib
|
|
|
|
|
присутствует функция `cmlib_config_hpp_generate()`, создающая файл
|
|
|
|
|
`${CMAKE_BINARY_DIR}/include/cmlib_private_config.hpp`, в который
|
|
|
|
|
записывается информация о имени и версии проекта, дате и типе сборки.
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Автоматически генерируемый заголовочный файл
|
|
|
|
|
cmlib_config_hpp_generate()
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
== Удаление установленных файлов
|
|
|
|
|
|
|
|
|
|
В библиотеку CMLib добавлена цель `uninstall`, позволяющая удалить файлы,
|
|
|
|
|
которые могут быть установлены в результате выполнения цели `install`:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
cd _build/debug
|
|
|
|
|
make install
|
|
|
|
|
make uninstall
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
== Архивирование проекта и создание пакетов
|
|
|
|
|
|
|
|
|
|
Стандартный модуль `CPack` предназначен для архивирования исходных
|
|
|
|
|
текстов проекта и создания пакетов для установки в целевую систему.
|
|
|
|
|
Необходимые переменные устанавливаются в файле `cmake/etc/Variables.cmake`
|
|
|
|
|
<<variables-cmake,см. выше>>.
|
|
|
|
|
|
|
|
|
|
Устанавливаемые файлы делятся на две группы `MAIN` и `DEV` с помощью
|
|
|
|
|
параметра `COMPONENT` функции `install`. В группу `MAIN` необходимо
|
|
|
|
|
помещать файлы для установки на целевую систему (исполняемые файлы,
|
|
|
|
|
файлы настроек, файлы данных, разделяемые библиотеки), а в группу `DEV` ---
|
|
|
|
|
для установки на систему для разработки (заголовочные файлы, статические
|
|
|
|
|
библиотеки).
|
|
|
|
|
|
|
|
|
|
По умолчанию цель для упаковки исходных текстов называется `package_source`.
|
|
|
|
|
Бинарные пакеты создаются программой `cpack`. Пример:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
cd _build/debug
|
|
|
|
|
make
|
|
|
|
|
make package_source
|
|
|
|
|
cpack
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
== Примеры библиотек и приложений
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
[[base-lib-project]]
|
2020-04-11 12:13:41 +00:00
|
|
|
|
=== Базовая библиотека
|
|
|
|
|
|
|
|
|
|
Проект с базовой библиотекой реализован на основе <<base-project,базового проекта>>.
|
|
|
|
|
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
|
|
|
|
|
Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-library[здесь]
|
|
|
|
|
или сделать его копию командой:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-library
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
В файл `CMakeLists.txt`, находящийся в корневом каталоге проекта, нужно добавить:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Поиск библиотеки Boost
|
|
|
|
|
set(Boost_USE_STATIC_LIBS ON)
|
|
|
|
|
set(Boost_USE_MULTITHREADED OFF)
|
|
|
|
|
set(Boost_USE_STATIC_RUNTIME ON)
|
|
|
|
|
find_package(Boost 1.55.0 REQUIRED COMPONENTS headers)
|
|
|
|
|
|
|
|
|
|
# Автоматически генерируемый заголовочный файл
|
|
|
|
|
cmlib_config_hpp_generate()
|
|
|
|
|
|
|
|
|
|
# Каталог с исходными текстами библиотеки
|
|
|
|
|
add_subdirectory(src/cmlib-example)
|
|
|
|
|
|
|
|
|
|
# Документация
|
|
|
|
|
add_subdirectory(cmake/doc)
|
|
|
|
|
|
|
|
|
|
# Создание вспомогательных символических ссылок
|
|
|
|
|
add_dependencies(cmlib-example create_auxilary_symlinks)
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
В подкаталоге `src/cmlib-example` нужно создать файл `CMakeLists.txt`:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Название основной цели и имя библиотеки в текущем каталоге
|
|
|
|
|
set(TRGT cmlib-example)
|
|
|
|
|
|
|
|
|
|
# Список файлов исходных текстов
|
2020-04-13 21:57:48 +00:00
|
|
|
|
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/init.cpp)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
# Список заголовочных файлов (используется для установки)
|
2020-04-13 21:57:48 +00:00
|
|
|
|
set(TRGT_hpp ${CMAKE_CURRENT_SOURCE_DIR}/init.hpp)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
# Функция для создания цели, результатом которой будет сборка библиотеки
|
2020-04-13 21:57:48 +00:00
|
|
|
|
add_common_library(${TRGT} SOURCES ${TRGT_cpp})
|
2020-04-11 12:13:41 +00:00
|
|
|
|
common_target_properties(${TRGT})
|
|
|
|
|
|
|
|
|
|
# Добавление к пути поиска заголовочных файлов
|
|
|
|
|
target_include_directories(${TRGT} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
|
|
|
|
|
|
|
|
|
|
# Цель, используемая только для установки
|
|
|
|
|
# заголовочных файлов без компиляции проекта
|
|
|
|
|
add_custom_target(${TRGT}-install-headers COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=DEV -P
|
|
|
|
|
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
|
|
|
|
|
|
|
|
|
# Установка статической библиотеки
|
|
|
|
|
install(TARGETS ${TRGT}_static COMPONENT DEV ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
|
|
|
|
|
|
|
|
# Установка динамической библиотеки
|
|
|
|
|
if(BUILD_SHARED_LIBS)
|
|
|
|
|
install(TARGETS ${TRGT}_shared COMPONENT DEV LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
|
|
|
endif()
|
|
|
|
|
|
|
|
|
|
# Установка заголовочных файлов
|
2020-04-13 21:57:48 +00:00
|
|
|
|
install(FILES ${TRGT_hpp} COMPONENT DEV DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${TRGT})
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
# Установка файла для pkg-config
|
|
|
|
|
install(FILES ${CMAKE_BINARY_DIR}/${TRGT}.pc COMPONENT DEV DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
файл `init.hpp`:
|
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
|
|
|
|
#ifndef CMLIB_EXAMPLE_HPP_
|
|
|
|
|
#define CMLIB_EXAMPLE_HPP_
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
int32_t cmlib_example_init(int32_t i);
|
|
|
|
|
|
|
|
|
|
#endif // CMLIB_EXAMPLE_HPP_
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
и файл `init.cpp`:
|
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
|
|
|
|
#include "init.hpp"
|
|
|
|
|
|
|
|
|
|
#include <boost/range/counting_range.hpp>
|
|
|
|
|
|
|
|
|
|
int32_t cmlib_example_init(int32_t i = 0)
|
|
|
|
|
{
|
|
|
|
|
int32_t s = 0;
|
|
|
|
|
for ( auto r : boost::counting_range( 1, i ) )
|
|
|
|
|
{
|
|
|
|
|
s += r;
|
|
|
|
|
}
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
|
|
|
|
|
[[base-app-project]]
|
2020-04-11 12:13:41 +00:00
|
|
|
|
=== Базовое приложение
|
|
|
|
|
|
|
|
|
|
Проект с базовым приложением реализован на основе <<base-project,базового проекта>>.
|
|
|
|
|
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
|
|
|
|
|
Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-app[здесь]
|
|
|
|
|
или сделать его копию командой:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-app
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-11 12:13:41 +00:00
|
|
|
|
В файл `CMakeLists.txt`, находящийся в корневом каталоге проекта, нужно добавить:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Boost
|
|
|
|
|
set(Boost_USE_STATIC_LIBS ON)
|
|
|
|
|
set(Boost_USE_MULTITHREADED OFF)
|
|
|
|
|
set(Boost_USE_STATIC_RUNTIME ON)
|
|
|
|
|
find_package(Boost 1.55.0 REQUIRED COMPONENTS headers)
|
|
|
|
|
|
|
|
|
|
# Автоматически генерируемый заголовочный файл
|
|
|
|
|
cmlib_config_hpp_generate()
|
|
|
|
|
|
|
|
|
|
# Приложение
|
|
|
|
|
add_subdirectory(src/cmlib-example)
|
|
|
|
|
|
|
|
|
|
# Документация
|
|
|
|
|
add_subdirectory(cmake/doc)
|
|
|
|
|
|
|
|
|
|
# Создание вспомогательных символических ссылок
|
|
|
|
|
add_dependencies(cmlib-example create_auxilary_symlinks)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
В подкаталоге `src/cmlib-example` нужно создать файл `CMakeLists.txt`:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Название основной цели и имя библиотеки в текущем каталоге
|
|
|
|
|
set(TRGT cmlib-example)
|
|
|
|
|
|
|
|
|
|
# Список файлов исходных текстов
|
2020-04-13 21:57:48 +00:00
|
|
|
|
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
# Функция для создания цели, результатом которой будет сборка приложения
|
2020-04-13 21:57:48 +00:00
|
|
|
|
add_executable(${TRGT} ${TRGT_cpp})
|
2020-04-11 12:13:41 +00:00
|
|
|
|
common_target_properties(${TRGT})
|
|
|
|
|
|
|
|
|
|
# Добавление к пути поиска заголовочных файлов
|
|
|
|
|
target_include_directories(${TRGT} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
|
|
|
|
|
|
|
|
|
|
# Имя целевого каталога и выходного файла для цели
|
|
|
|
|
set_target_properties(${TRGT}
|
|
|
|
|
PROPERTIES
|
|
|
|
|
OUTPUT_NAME ${TRGT}
|
|
|
|
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Правила для установки
|
|
|
|
|
install(TARGETS ${TRGT} COMPONENT MAIN RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-11 12:13:41 +00:00
|
|
|
|
и файл `main.cpp`:
|
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
|
|
|
|
#include "compiler_features.hpp"
|
|
|
|
|
#include "cmlib_private_config.hpp"
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <boost/range/counting_range.hpp>
|
|
|
|
|
|
|
|
|
|
int32_t nsum(int32_t i = 0)
|
|
|
|
|
{
|
|
|
|
|
int32_t s = 0;
|
|
|
|
|
for ( auto r : boost::counting_range( 1, i ) )
|
|
|
|
|
{
|
|
|
|
|
s += r;
|
|
|
|
|
}
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
|
{
|
|
|
|
|
// Значение из compiler_features.hpp
|
|
|
|
|
std::cout << CMLIB_EXAMPLE_APP_COMPILER_VERSION_MAJOR << std::endl;
|
|
|
|
|
// Значение из cmlib_private_config.hpp
|
|
|
|
|
std::cout << CMLIB_BUILD_TYPE << std::endl;
|
|
|
|
|
// Значение из cmlib_private_config.hpp
|
|
|
|
|
std::cout << CMLIB_BUILD_DATE << std::endl;
|
|
|
|
|
|
|
|
|
|
auto s = nsum( argc );
|
|
|
|
|
std::cout << s << std::endl;
|
|
|
|
|
|
|
|
|
|
return ( s );
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
=== Подключение внешнего проекта
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
Проект, использующий для сборки внешний проект, реализован на основе проектов
|
|
|
|
|
<<base-lib-project,базовой библиотеки>> и <<base-app-project,базового приложения>>.
|
|
|
|
|
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
|
|
|
|
|
Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-app-ext[здесь]
|
|
|
|
|
или сделать его копию командой:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
[source,sh]
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
2020-04-11 13:19:35 +00:00
|
|
|
|
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-app-ext
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
Для подключения проекта базовой библиотеки нужно выполнить:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
[source,sh]
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
2020-04-11 13:19:35 +00:00
|
|
|
|
git submodule add https://git.246060.ru/f1x1t/cmlib-example-library thirdparty/cmlib-example-library
|
|
|
|
|
git submodule update --init --recursive
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
В файл `CMakeLists.txt`, находящийся в корневом каталоге проекта, перед функциями
|
|
|
|
|
`add_subdirectories` нужно добавить:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Подключение внешних проектов
|
|
|
|
|
include(ExternalProject)
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
ExternalProject_Add(ext-lib
|
2020-04-11 12:13:41 +00:00
|
|
|
|
EXCLUDE_FROM_ALL TRUE
|
2020-04-11 13:19:35 +00:00
|
|
|
|
SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/cmlib-example-library
|
2020-04-11 12:13:41 +00:00
|
|
|
|
INSTALL_DIR ${CMAKE_BINARY_DIR}
|
|
|
|
|
DOWNLOAD_COMMAND ""
|
2020-04-11 13:19:35 +00:00
|
|
|
|
BUILD_BYPRODUCTS <INSTALL_DIR>/lib/libcmlib-example.a
|
2020-04-11 12:13:41 +00:00
|
|
|
|
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_BUILD_TYPE=Release
|
|
|
|
|
)
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
В результате будет создана цель `ext-lib`, являющаяся результатом сборки
|
2020-04-11 15:07:10 +00:00
|
|
|
|
подключённой библиотеки. Все функции `ExternalProject_Add` необходимо
|
|
|
|
|
располагать перед функциям `add_subdirectories`, чтобы в указанных подкаталогах
|
|
|
|
|
можно было использовать добавленные цели для определения зависимостей.
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-11 15:07:10 +00:00
|
|
|
|
В файле `src/cmlib-example/CMakeLists.txt` после создания цели `${TRGT}` нужно
|
|
|
|
|
подключить внешний проект `ext-lib`:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Зависимость от библиотеки из внешнего проекта проекта
|
2020-04-11 13:19:35 +00:00
|
|
|
|
add_dependencies(${TRGT} ext-lib)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
# Добавление каталога, в который устанавливаются заголовочные файлы
|
|
|
|
|
# от внешнего проекта, к списку путей для поиска
|
|
|
|
|
target_include_directories(${TRGT} PUBLIC $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
# Компоновка с библиотекой из внешнего проекта
|
|
|
|
|
target_link_libraries(${TRGT} ${CMAKE_BINARY_DIR}/lib/libcmlib-example.a)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
Для проверки работоспособности в файле `src/cmlib-example/main.cpp` нужно
|
|
|
|
|
вызвать функцию `cmlib_example_init` из библиотеки, предоставляемой внешним
|
2020-04-11 12:13:41 +00:00
|
|
|
|
проектом. Например, можно заменить его содержимое на:
|
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
2020-04-11 13:19:35 +00:00
|
|
|
|
#include <cmlib-example/init.hpp>
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
int main(int argc, char* argv[])
|
2020-04-11 12:13:41 +00:00
|
|
|
|
{
|
2020-04-11 13:19:35 +00:00
|
|
|
|
auto s = cmlib_example_init( argc );
|
|
|
|
|
std::cout << s << std::endl;
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
return ( s );
|
2020-04-11 12:13:41 +00:00
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-11 13:19:35 +00:00
|
|
|
|
|
2020-04-11 15:07:10 +00:00
|
|
|
|
=== Qt5
|
|
|
|
|
|
2020-04-13 22:26:01 +00:00
|
|
|
|
В данном разделе будут приведены примеры создания консольного и графического
|
|
|
|
|
приложений, а также подключения локализации, вызовы препроцессоров `moc`,
|
|
|
|
|
`uic` и `rcc`.
|
2020-04-13 21:57:48 +00:00
|
|
|
|
|
2020-04-13 22:26:01 +00:00
|
|
|
|
[[qt5-con]]
|
2020-04-13 21:57:48 +00:00
|
|
|
|
==== Консольное приложение и локализация
|
|
|
|
|
|
|
|
|
|
Пример консольного приложения на Qt5 с поддержкой локализации основан
|
|
|
|
|
на проекте <<base-app-project,базового приложения>> и библиотеке
|
|
|
|
|
https://git.246060.ru/f1x1t/myxlib[MyXLib].
|
|
|
|
|
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
|
|
|
|
|
Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-app-qt5-con[здесь]
|
|
|
|
|
или сделать его копию командой:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-app-qt5-con
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
Для подключения проекта библиотеки https://git.246060.ru/f1x1t/myxlib[MyXLib] нужно выполнить:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git submodule add https://git.246060.ru/f1x1t/myxlib thirdparty/myxlib
|
|
|
|
|
git submodule update --init --recursive
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-13 22:26:01 +00:00
|
|
|
|
В файлах `CMakeLists.txt` и `src/cmlib-example/CMakeLists.txt` нужно
|
2020-04-13 22:11:23 +00:00
|
|
|
|
заменить все строки `cmlib-example` на `cmlib-example-app-qt5-con`.
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-13 22:11:23 +00:00
|
|
|
|
В файл `CMakeLists.txt`, находящийся в корневом каталоге проекта,
|
|
|
|
|
перед функциями `add_subdirectories` нужно добавить:
|
2020-04-13 21:57:48 +00:00
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Подключение внешних проектов
|
|
|
|
|
include(ExternalProject)
|
|
|
|
|
|
|
|
|
|
ExternalProject_Add(
|
|
|
|
|
myxlib
|
|
|
|
|
SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/myxlib
|
|
|
|
|
INSTALL_DIR ${CMAKE_BINARY_DIR}
|
|
|
|
|
DOWNLOAD_COMMAND ""
|
|
|
|
|
CONFIGURE_COMMAND
|
|
|
|
|
${CMAKE_COMMAND} -"G${CMAKE_GENERATOR}" -DCMAKE_BUILD_TYPE=Debug
|
|
|
|
|
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
|
|
|
|
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
|
|
|
|
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} <SOURCE_DIR>
|
|
|
|
|
BUILD_COMMAND true)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
В результате будет создана цель `myxlib`, являющаяся результатом сборки
|
|
|
|
|
подключённой библиотеки. Все функции `ExternalProject_Add` необходимо
|
|
|
|
|
располагать перед функциям `add_subdirectories`, чтобы в указанных подкаталогах
|
|
|
|
|
можно было использовать добавленные цели для определения зависимостей.
|
|
|
|
|
|
|
|
|
|
В файле `src/cmlib-example/CMakeLists.txt` после создания цели `${TRGT}` нужно
|
|
|
|
|
подключить внешний проект `myxlib`:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Зависимость от библиотеки из внешнего проекта проекта
|
|
|
|
|
add_dependencies(${TRGT} myxlib)
|
|
|
|
|
|
|
|
|
|
# Добавление каталога, в который устанавливаются заголовочные файлы
|
|
|
|
|
# от внешнего проекта, к списку путей для поиска
|
|
|
|
|
target_include_directories(${TRGT} PUBLIC $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
|
|
|
|
|
|
|
|
|
|
# Компоновка с библиотеками из внешнего проекта
|
|
|
|
|
target_link_libraries(${TRGT} myx-qt myx-filesystem myx-base)
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-13 08:52:00 +00:00
|
|
|
|
Для поиска необходимых компонентов Qt5 нужно в файле `CMakeLists.txt`,
|
2020-04-13 21:57:48 +00:00
|
|
|
|
находящемся в корневом каталоге проекта, перед вызовом функции
|
2020-04-11 15:07:10 +00:00
|
|
|
|
`cmlib_config_hpp_generate()` добавить строку:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
2020-04-13 21:57:48 +00:00
|
|
|
|
# Используемые компоненты Qt5
|
|
|
|
|
find_package(Qt5 COMPONENTS Core REQUIRED)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
В файл `src/cmlib-example/CMakeLists.txt` перед вызовом функции
|
|
|
|
|
`add_executable` добавить строки:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Правила для создания файла ресурсов с вложенными файлами переводов
|
|
|
|
|
qt5_translation(
|
|
|
|
|
TRGT_qrc
|
|
|
|
|
OUTPUT_DIR ${CMAKE_SOURCE_DIR}/l10n BASE_NAME ${TRGT}
|
|
|
|
|
SOURCES ${TRGT_cpp} LANGUAGES ru_RU)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
# Путь поиска библиотек созданных при компиляции проекта,
|
|
|
|
|
# включая библиотеки из подключённых внешних проектов, например MyXLib
|
|
|
|
|
# Функция link_directories обязательно должна находиться перед
|
|
|
|
|
# функцией add_executable, иначе компоновка не может быть выполнена
|
|
|
|
|
link_directories(${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
В вызове `add_executable` подключить использование файла ресурсов
|
|
|
|
|
с переводами:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
2020-04-13 21:57:48 +00:00
|
|
|
|
add_executable(${TRGT} ${TRGT_cpp} ${TRGT_qrc})
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
После чего добавить подключение Qt5 и MyXLib:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Qt5: подключение заголовочных файлов
|
2020-04-11 13:19:35 +00:00
|
|
|
|
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
# Qt5: подключение библиотек
|
2020-04-11 13:19:35 +00:00
|
|
|
|
target_link_libraries(${TRGT} Qt5::Core)
|
2020-04-13 21:57:48 +00:00
|
|
|
|
|
|
|
|
|
# Добавление к пути поиска заголовочных файлов
|
|
|
|
|
target_include_directories(${TRGT} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
|
|
|
|
|
|
|
|
|
|
# Зависимость от библиотеки из внешнего проекта проекта
|
|
|
|
|
add_dependencies(${TRGT} myxlib)
|
|
|
|
|
|
|
|
|
|
# Добавление каталога, в который устанавливаются заголовочные файлы
|
|
|
|
|
# от внешнего проекта, к списку путей для поиска
|
|
|
|
|
target_include_directories(${TRGT} PUBLIC $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
|
|
|
|
|
|
|
|
|
|
# Компоновка с библиотеками из внешнего проекта
|
|
|
|
|
target_link_libraries(${TRGT} myx-qt myx-filesystem myx-base)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
2020-04-13 21:57:48 +00:00
|
|
|
|
|
2020-04-11 12:13:41 +00:00
|
|
|
|
Для проверки работоспособности подключения Qt5 файл
|
2020-04-13 21:57:48 +00:00
|
|
|
|
`src/cmlib-example/main.cpp` нужно заменить на:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
2020-04-13 21:57:48 +00:00
|
|
|
|
#include "cmlib_private_config.hpp"
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
#include <myx/qt/translators.hpp>
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QDebug>
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
namespace MQ = myx::qt;
|
|
|
|
|
|
|
|
|
|
int main( int argc, char** argv )
|
2020-04-11 12:13:41 +00:00
|
|
|
|
{
|
2020-04-13 21:57:48 +00:00
|
|
|
|
QCoreApplication app( argc, argv );
|
|
|
|
|
MQ::QTranslatorsList tl;
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
qDebug() << QObject::tr( "No" );
|
|
|
|
|
MQ::append_translators( tl, QStringLiteral( CMLIB_PROJECT_NAME ) );
|
|
|
|
|
qDebug() << QObject::tr( "Yes" );
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-13 21:57:48 +00:00
|
|
|
|
return( 0 );
|
2020-04-11 12:13:41 +00:00
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 08:56:35 +00:00
|
|
|
|
Для сбора списка строк из файлов исходных кодов и описаний интерфейса,
|
|
|
|
|
подлежащих переводу, создаётся цель `l10n`. В результате выполнения
|
|
|
|
|
в каталоге сборки команды `make l10n` в каталоге `l10n`, находящемся
|
|
|
|
|
в корне проекта, появится файл `cmlib-example-app-qt5-con_ru_RU.ts`,
|
|
|
|
|
в котором нужно отредактировать переводы с помощью программы `linguist`.
|
|
|
|
|
После сохранения файла переводов проект нужно пересобрать, файл
|
|
|
|
|
переводов в скомпилированном виде будет встроен в исполняемый файл
|
|
|
|
|
`cmlib-example-app-qt5-con`, а доступ к нему будет осуществляться
|
|
|
|
|
с помощью кода:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
2020-04-13 22:11:23 +00:00
|
|
|
|
MQ::QTranslatorsList tl;
|
|
|
|
|
MQ::append_translators( tl, QStringLiteral( CMLIB_PROJECT_NAME ) );
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 10:10:34 +00:00
|
|
|
|
[[qt5-gui]]
|
2020-04-14 08:56:35 +00:00
|
|
|
|
==== Графическое приложение, файлы описания ресурсов и интерфейсов
|
2020-04-13 22:26:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Пример приложения на Qt5 с использованием графического интерфейса основан
|
|
|
|
|
на проекте <<qt5-con,консольного приложения для Qt5>>.
|
|
|
|
|
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
|
|
|
|
|
Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-app-qt5-gui[здесь]
|
|
|
|
|
или сделать его копию командой:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-app-qt5-gui
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
В каталоге `files/data` создать файл описания включаемых ресурсов `icon.qrc`:
|
|
|
|
|
|
|
|
|
|
[source,xml]
|
|
|
|
|
----
|
|
|
|
|
<RCC>
|
|
|
|
|
<qresource prefix="/icon">
|
|
|
|
|
<file alias="icon.png">icon.png</file>
|
|
|
|
|
</qresource>
|
|
|
|
|
</RCC>
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
и загрузить файл иконки:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
wget https://git.246060.ru/f1x1t/cmlib-example-app-qt5-gui/raw/branch/master/files/data/icon.png
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
Для графического приложения нужно создать файл описания интерфейса
|
|
|
|
|
`src/cmlib-example/test_window.ui`:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,xml]
|
|
|
|
|
----
|
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<ui version="4.0">
|
2020-04-14 06:37:33 +00:00
|
|
|
|
<class>TestWindow</class>
|
|
|
|
|
<widget class="QMainWindow" name="TestWindow">
|
2020-04-11 12:13:41 +00:00
|
|
|
|
<property name="geometry">
|
2020-04-14 09:37:56 +00:00
|
|
|
|
<rect><x>0</x><y>0</y><width>413</width><height>253</height></rect>
|
2020-04-11 12:13:41 +00:00
|
|
|
|
</property>
|
|
|
|
|
<property name="windowTitle">
|
2020-04-14 06:37:33 +00:00
|
|
|
|
<string>Test Window</string>
|
2020-04-11 12:13:41 +00:00
|
|
|
|
</property>
|
2020-04-14 06:37:33 +00:00
|
|
|
|
<widget class="QWidget" name="centralwidget">
|
|
|
|
|
<widget class="QPushButton" name="exitButton">
|
|
|
|
|
<property name="geometry">
|
2020-04-14 09:37:56 +00:00
|
|
|
|
<rect><x>170</x><y>30</y><width>80</width><height>26</height></rect>
|
2020-04-14 06:37:33 +00:00
|
|
|
|
</property>
|
|
|
|
|
<property name="text">
|
|
|
|
|
<string>Press me</string>
|
|
|
|
|
</property>
|
|
|
|
|
</widget>
|
|
|
|
|
</widget>
|
2020-04-11 12:13:41 +00:00
|
|
|
|
</widget>
|
|
|
|
|
<resources/>
|
|
|
|
|
<connections/>
|
|
|
|
|
</ui>
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
заголовочный файл `src/cmlib-example/test_window.hpp`:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
2020-04-14 06:37:33 +00:00
|
|
|
|
#ifndef TEST_WINDOW_HPP_
|
|
|
|
|
#define TEST_WINDOW_HPP_
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "ui_test_window.h"
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
#include <QMainWindow>
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
class TestWindow : public QMainWindow, private Ui::TestWindow {
|
2020-04-11 12:13:41 +00:00
|
|
|
|
Q_OBJECT
|
2020-04-14 06:37:33 +00:00
|
|
|
|
public:
|
|
|
|
|
TestWindow(QMainWindow *parent = nullptr);
|
|
|
|
|
virtual ~TestWindow();
|
2020-04-11 12:13:41 +00:00
|
|
|
|
};
|
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
#endif /* TEST_WINDOW_HPP_ */
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
и файл с реализацией конструктора, в котором проводится инициализация
|
|
|
|
|
графических элементов, `src/cmlib-example/test_window.cpp`:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
2020-04-14 06:37:33 +00:00
|
|
|
|
#include "test_window.hpp"
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
TestWindow::TestWindow(QMainWindow* parent) :
|
|
|
|
|
QMainWindow(parent),
|
|
|
|
|
Ui::TestWindow()
|
|
|
|
|
{
|
|
|
|
|
setupUi(this);
|
2020-04-11 12:13:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
TestWindow::~TestWindow() = default;
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
<<<
|
|
|
|
|
|
2020-04-11 12:13:41 +00:00
|
|
|
|
Для отображения графического окна нужно заменить файл
|
2020-04-14 06:37:33 +00:00
|
|
|
|
`src/cmlib-examples/main.cpp` на:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cpp]
|
|
|
|
|
----
|
2020-04-14 06:37:33 +00:00
|
|
|
|
#include "cmlib_private_config.hpp"
|
|
|
|
|
#include "test_window.hpp"
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
#include <myx/qt/translators.hpp>
|
|
|
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
|
#include <QIcon>
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
|
|
namespace MQ = myx::qt;
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
int main( int argc, char** argv )
|
2020-04-11 12:13:41 +00:00
|
|
|
|
{
|
2020-04-14 06:37:33 +00:00
|
|
|
|
QApplication app( argc, argv );
|
|
|
|
|
qDebug() << QObject::tr( "No" );
|
|
|
|
|
|
|
|
|
|
// Подключение переводов
|
|
|
|
|
MQ::QTranslatorsList tl;
|
|
|
|
|
MQ::append_translators( tl, QStringLiteral( CMLIB_PROJECT_NAME ) );
|
|
|
|
|
qDebug() << QObject::tr( "Yes" );
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
// Установка иконки для программы
|
|
|
|
|
QApplication::setWindowIcon( QIcon( ":/icon/icon.png" ) );
|
|
|
|
|
|
|
|
|
|
// Создание и отображение главного окна
|
|
|
|
|
auto* w = new TestWindow();
|
|
|
|
|
w->show();
|
|
|
|
|
return( QApplication::exec() );
|
2020-04-11 12:13:41 +00:00
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 06:37:33 +00:00
|
|
|
|
|
|
|
|
|
В файлах `CMakeLists.txt` и `src/cmlib-example/CMakeLists.txt` нужно
|
|
|
|
|
заменить все строки `cmlib-example-app-qt5-con` на `cmlib-example-app-qt5-gui`.
|
|
|
|
|
|
|
|
|
|
Для поиска необходимых компонентов Qt5 нужно в файле `CMakeLists.txt`,
|
|
|
|
|
находящемся в корневом каталоге проекта, добавить поиск компонентов
|
|
|
|
|
`Gui` и `Widgets`:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Используемые компоненты Qt5
|
|
|
|
|
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
В файле `src/cmake-example/CMakeLists.txt` добавить новые файлы к списку
|
|
|
|
|
файлов, используемых для компиляции:
|
2020-04-14 06:37:33 +00:00
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
###
|
|
|
|
|
# Списки файлов проекта
|
|
|
|
|
###
|
|
|
|
|
# Исходные коды
|
|
|
|
|
set(TRGT_cpp
|
|
|
|
|
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
|
|
|
|
|
${CMAKE_CURRENT_SOURCE_DIR}/test_window.cpp)
|
2020-04-14 06:37:33 +00:00
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
# Заголовочные файлы, для которых необходима обработка препроцессором moc
|
|
|
|
|
# (содержат класс, унаследованный от QObject, использующий сигналы и/или слоты)
|
|
|
|
|
set(TRGT_moc_hpp
|
|
|
|
|
${CMAKE_CURRENT_SOURCE_DIR}/test_window.hpp)
|
2020-04-14 06:37:33 +00:00
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
# Другие заголовочные файлы
|
|
|
|
|
set(TRGT_hpp)
|
2020-04-14 06:37:33 +00:00
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
# Файлы с описанием графического интерфейса для Qt
|
|
|
|
|
set(TRGT_ui
|
|
|
|
|
${CMAKE_CURRENT_SOURCE_DIR}/test_window.ui)
|
2020-04-14 06:37:33 +00:00
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
# Файлы описания ресурсов, включаемых в исполняемый файл
|
|
|
|
|
set(TRGT_qrc
|
|
|
|
|
${CMAKE_SOURCE_DIR}/files/data/icon.qrc)
|
|
|
|
|
###
|
|
|
|
|
# Конец списков файлов
|
|
|
|
|
###
|
|
|
|
|
----
|
2020-04-14 06:37:33 +00:00
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
Для обеспечения работы препроцессоров Qt необходимо создать правила
|
|
|
|
|
преобразования файлов:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
2020-04-14 07:01:33 +00:00
|
|
|
|
# Правило для автоматической генерации препроцессором uic
|
|
|
|
|
qt5_wrap_ui(TRGT_ui_h ${TRGT_ui})
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
# Правило для автоматической генерации препроцессором moc
|
|
|
|
|
qt5_wrap_cpp(TRGT_moc_cpp ${TRGT_moc_hpp})
|
|
|
|
|
|
|
|
|
|
# Правила для создания файла ресурсов с вложенными файлами переводов
|
|
|
|
|
qt5_translation(
|
|
|
|
|
TRGT_qrc_cpp
|
|
|
|
|
OUTPUT_DIR ${CMAKE_SOURCE_DIR}/l10n BASE_NAME ${TRGT}
|
|
|
|
|
SOURCES ${TRGT_cpp} ${TRGT_ui} LANGUAGES ru_RU)
|
|
|
|
|
|
|
|
|
|
# Правило для автоматической генерации препроцессором qrc
|
|
|
|
|
# (обязательно после вызова функции qt5_translation, если она есть,
|
|
|
|
|
# так как она добавляет свои файлы к списку ресурсов)
|
|
|
|
|
qt5_add_resources(TRTG_qrc_cpp ${TRGT_qrc})
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
Цель для создания исполняемого файла нужно изменить таким образом,
|
|
|
|
|
чтобы она зависела от файлов с исходными кодами и файлов, генерируемых
|
|
|
|
|
препроцессорами:
|
|
|
|
|
|
2020-04-11 12:13:41 +00:00
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
2020-04-14 07:01:33 +00:00
|
|
|
|
add_executable(${TRGT} ${TRGT_ui_h} ${TRGT_moc_cpp} ${TRGT_qrc_cpp} ${TRGT_cpp})
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 07:01:33 +00:00
|
|
|
|
Подключение заголовочных файлов и библиотек Qt должно выглядеть так:
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
2020-04-14 07:01:33 +00:00
|
|
|
|
# Qt5: подключение заголовочных файлов
|
|
|
|
|
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
|
2020-04-11 13:19:35 +00:00
|
|
|
|
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Gui_INCLUDE_DIRS})
|
|
|
|
|
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Widgets_INCLUDE_DIRS})
|
2020-04-14 07:01:33 +00:00
|
|
|
|
|
|
|
|
|
# Qt5: подключение библиотек
|
|
|
|
|
target_link_libraries(${TRGT} Qt5::Core Qt5::Gui Qt5::Widgets)
|
2020-04-11 12:13:41 +00:00
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 08:56:35 +00:00
|
|
|
|
В результате выполнения в каталоге сборки команды `make l10n`
|
|
|
|
|
в каталоге `l10n`, находящемся в корне проекта, появится файл
|
|
|
|
|
`cmlib-example-app-qt5-gui_ru_RU.ts`,
|
|
|
|
|
в котором нужно отредактировать переводы с помощью программы `linguist`.
|
|
|
|
|
После сохранения файла переводов проект нужно пересобрать, файл
|
|
|
|
|
переводов в скомпилированном виде будет встроен в исполняемый файл.
|
2020-04-11 12:13:41 +00:00
|
|
|
|
|
2020-04-14 09:31:39 +00:00
|
|
|
|
|
2020-04-14 10:10:34 +00:00
|
|
|
|
== Дополнительные возможности
|
|
|
|
|
|
|
|
|
|
Библиотека CMLib содержит шаблонные функции для использования
|
|
|
|
|
в программных проектах. Пример проекта с примерами использования
|
|
|
|
|
функций основан на проекте <<qt5-gui,графического приложения для Qt5>>.
|
|
|
|
|
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
|
|
|
|
|
Проект можно посмотреть https://git.246060.ru/f1x1t/cmlib-example-app-features[здесь]
|
|
|
|
|
или сделать его копию командой:
|
|
|
|
|
|
|
|
|
|
[source,sh]
|
|
|
|
|
----
|
|
|
|
|
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-app-features
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=== Форматирование исходных текстов
|
|
|
|
|
|
|
|
|
|
Функция `add_format_sources` используется для форматирования файлов проекта
|
|
|
|
|
в едином стандарте, для её использования требуются установленные программы
|
|
|
|
|
`dos2unix` и `uncrustify`. Утилита `dos2unix` приводит переводы строк в
|
|
|
|
|
файлах к стандарту, принятому в Unix. Утилита `uncrustify` форматирует
|
2020-04-14 10:35:51 +00:00
|
|
|
|
файлы с исходными кодами на языке C{plus}{plus} в соответствии с правилами,
|
2020-04-14 10:10:34 +00:00
|
|
|
|
перечисленными в файле `cmake/etc/uncrustify/default.cfg`. Пример использования:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Создание цели format-sources для автоматического форматирования кода
|
|
|
|
|
add_format_sources(${TRGT} ${TRGT_sources} ${TRGT_headers})
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 10:19:33 +00:00
|
|
|
|
=== Статический анализ исходных кодов
|
|
|
|
|
|
2020-04-14 10:35:51 +00:00
|
|
|
|
Для работы с программами на языке C{plus}{plus} используются утилиты,
|
|
|
|
|
выполняющие статический анализ кода и генерирующие отчёты, помогающие
|
|
|
|
|
программисту находить и устранять ошибки. Эти программы применяют методы,
|
|
|
|
|
позволяющие в синтаксически корректном коде находить недостатки или ошибки,
|
|
|
|
|
которые пропускает компилятор, ценой продолжительного анализа исходных текстов.
|
2020-04-14 10:10:34 +00:00
|
|
|
|
|
2020-04-14 10:25:21 +00:00
|
|
|
|
Библиотека CMLib поддерживает анализаторы https://github.com/KDE/clazy[clazy],
|
|
|
|
|
https://clang.llvm.org/extra/clang-tidy[Clang Tidy],
|
|
|
|
|
https://clang-analyzer.llvm.org[Clang Static Analyzer] и
|
|
|
|
|
https://www.viva64.com/ru/pvs-studio[PVS-Studio].
|
|
|
|
|
|
2020-04-14 10:35:51 +00:00
|
|
|
|
==== clazy
|
|
|
|
|
|
2020-04-14 10:45:26 +00:00
|
|
|
|
Функция `add_clazy_check` создаёт цели, которые используются
|
2020-04-14 10:35:51 +00:00
|
|
|
|
для проверки исходных текстов анализатором `clang`.
|
|
|
|
|
Пример использования:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Создание цели clazy-check для проверки утилитой clazy
|
|
|
|
|
add_clazy_check(${TRGT} ${TRGT_cpp} ${TRGT_hpp} ${TRGT_moc_hpp})
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 10:10:34 +00:00
|
|
|
|
|
2020-04-14 10:45:26 +00:00
|
|
|
|
==== Clang Tidy
|
|
|
|
|
|
|
|
|
|
Функция `add_clang_tidy_check` создаёт цели, которые используются
|
|
|
|
|
для проверки исходных текстов анализатором `clang-tidy`.
|
|
|
|
|
Пример использования:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Создание цели clang-tidy-check для проверки утилитой clang-tidy
|
|
|
|
|
add_clang_tidy_check(${TRGT} ${TRGT_cpp} ${TRGT_hpp} ${TRGT_moc_hpp})
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
==== Clang Static Analyzer
|
|
|
|
|
|
|
|
|
|
Функция `add_clang_analyze_check` создаёт цели, которые используются
|
|
|
|
|
для проверки исходных текстов анализатором `clang-analyze`.
|
|
|
|
|
Пример использования:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Создание цели clang-analyze-check для проверки утилитой clang-analyze
|
|
|
|
|
add_clang_analyze_check(${TRGT} ${TRGT_cpp} ${TRGT_hpp} ${TRGT_moc_hpp})
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
==== PVS-Studio
|
|
|
|
|
|
|
|
|
|
Функция `add_pvs_check` создаёт цели, которые используются
|
|
|
|
|
для проверки исходных текстов анализатором `pvs-studio-analyzer`.
|
|
|
|
|
Пример использования:
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Создание цели pvs-check для проверки утилитой pvs-studio-analyzer
|
|
|
|
|
add_pvs_check(${TRGT})
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
2020-04-14 11:20:29 +00:00
|
|
|
|
=== Динамический анализ программы
|
|
|
|
|
|
|
|
|
|
Динамический анализ программы позволяет ценой значительного замедления
|
|
|
|
|
скорости работы получить дополнительную информацию о ходе её выполнения.
|
|
|
|
|
Современные компиляторы делают вставку инструкций в определённые точки
|
|
|
|
|
программы, во время работы программы в них собирается необходимая информация,
|
|
|
|
|
а по её завершению предоставляется отчёт. Основная информация о работе
|
|
|
|
|
таких анализаторов находится https://github.com/google/sanitizers/wiki[здесь].
|
|
|
|
|
|
|
|
|
|
Для обеспечения возможности подключения динамического анализа к проекту
|
|
|
|
|
нужно выполнить функцию (обязательно после подключения всех библиотек):
|
|
|
|
|
|
|
|
|
|
[source,cmake]
|
|
|
|
|
----
|
|
|
|
|
# Подключение настроек для динамического анализа программы
|
|
|
|
|
add_sanitizers(${TRGT})
|
|
|
|
|
----
|
|
|
|
|
|
2020-04-14 13:37:35 +00:00
|
|
|
|
Подключение анализатора осуществляется включением опциям при запуске
|
|
|
|
|
CMake для генерации сборочных файлов. Некоторые из опций между собой
|
|
|
|
|
несовместимы, в случае попытки совместного использования будет выведено
|
|
|
|
|
сообщение об ошибке.
|
2020-04-14 11:20:29 +00:00
|
|
|
|
|
2020-04-14 13:37:35 +00:00
|
|
|
|
.Назначение опций для динамического анализа
|
|
|
|
|
[cols="2m,7",options="header"]
|
2020-04-14 13:27:02 +00:00
|
|
|
|
|===
|
|
|
|
|
| Опция | Назначение
|
|
|
|
|
| SANITIZE_ADDRESS | Определение ошибок при работе с памятью: использование после освобождения,
|
|
|
|
|
использование за пределами области видимости, переполнения буферов в стеке, на куче, в общей памяти,
|
|
|
|
|
утечки памяти, нарушение порядка инициализации
|
|
|
|
|
| SANITIZE_CFI | Определение нарушений путей исполнения инструкций программы
|
|
|
|
|
| SANITIZE_LEAK | Определение утечек памяти
|
|
|
|
|
| SANITIZE_LINK_STATIC | Статическая компоновка анализатора с программой
|
|
|
|
|
| SANITIZE_MEMORY | Определение попыток доступа к неинициализированным областям памяти
|
|
|
|
|
| SANITIZE_SS | Определение переполнения буфера стека
|
|
|
|
|
| SANITIZE_THREAD | Определение состояние гонок
|
|
|
|
|
| SANITIZE_UNDEFINED | Определение невыровненных и нулевых указателей, переполнения знаковых целых,
|
|
|
|
|
преобразования типов с плавающей точкой, ведущих к переполнению результирующей переменной
|
|
|
|
|
|===
|
2020-04-14 11:20:29 +00:00
|
|
|
|
|