dsp-site/wiki/Prog/Development/CMake управление проектом v2.adoc

1525 lines
64 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

= CMake: управление проектом v2
:title-separator: {sp}|
:category: Программирование
:tags: программирование, cmake, qt
:icons: font
:toc:
include::{l10ndir}/{lang}.adoc[]
== Полезные ссылки
* https://github.com/onqtam/awesome-cmake[Каталог ссылок]
* https://cgold.readthedocs.io/en/latest/index.html[CGold: The Hitchhikers Guide to the CMake]
== Инструментарий
В таблице приведён перечень используемых программ.
.Программы
[cols="2,4",options="header",]
|===
|Программа | Назначение
|GCC | Компилятор C/C{plus}{plus}
|LLVM | Компилятор C/C{plus}{plus} и средства статического анализа
|GDB | Отладчик
|Qt Creator | Среда разработки
|uncrustify | Форматирование исходных текстов на языке C/C{plus}{plus}
|git | Система контроля версий
|CMake | Система управления проектом
|cmake-format | Форматирование исходных текстов для CMake
|Doxygen | Автоматическая генерация документации
|===
Установка:
[source,sh]
----
sudo apt-get install build-essential clang clang-tidy gdb qtcreator qt5-default
sudo apt-get install cmake cmake-format doxygen git uncrustify
----
Для дальней работы потребуется установка пакетов `myx-dev`, в котором
находятся скрипты для выполнения типовых команд, и `myx-cmake` с библиотекой
MyxCMake, содержащей дополнительные функции для проекта на CMake.
[source,sh]
----
sudo apt-get install myx-dev myx-cmake
----
Если пакеты не доступны для `apt-get`, то установить их можно так:
[source,sh]
----
sudo apt-get install wget
wget -A ".deb" -c -q -np -nd -r -l 1 https://deb.246060.ru/ubuntu/focal/pool/main/m/myx-cmake/
wget -A ".deb" -c -q -np -nd -r -l 1 https://deb.246060.ru/ubuntu/focal/pool/main/m/myx-dev/
sudo dpkg -i myx-cmake*deb myx-dev*deb
sudo apt-get -f install
----
== Структура каталогов проекта
Файлы проекта и результаты компиляции размещаются в каталогах:
....
└── project
├── _build
│ ├── debug
│ │ ├── bin
│ │ ├── etc
│ │ ├── include
│ │ ├── lib
│ │ ├── log
│ │ ├── share
│ │ └── var
│ └── release
├── .git
├── cmake
├── doc
├── files
│ ├── etc
│ ├── log
│ ├── share
│ └── var
├── l10n
├── src
│ ├── app
│ └── lib
├── thirdparty
└── tools
....
Назначение каталогов приведено в таблице.
.Назначение каталогов
[cols="2,4",options="header",]
|===
|Каталог | Назначение
|`_build` | Результаты компиляции
|`_build/debug` | Результаты компиляции в режиме отладки
|`_build/debug/bin` | Исполняемые файлы
|`_build/debug/etc` | Символическая ссылка на каталог `cmex/files/etc`
|`_build/debug/include` | Заголовочные файлы копируемые и генерируемые во время сборки
|`_build/debug/lib` | Статические и динамические библиотеки
|`_build/debug/log` | Символическая ссылка на каталог `cmex/files/log`
|`_build/debug/share` | Символическая ссылка на каталог `cmex/files/share`
|`_build/debug/var` | Символическая ссылка на каталог `cmex/files/var`
|`_build/release` | Результаты компиляции в режиме выпуска (иерархия аналогична `debug`)
|`.git` | Системные файлы репозитория Git
|`cmake` | Файлы с дополнительными функциями для CMake
|`doc` | Документация для проекта
|`files` | Каталог для дополнительных файлов
|`files/etc` | Каталог для файлов настроек проекта
|`files/log` | Каталог для журналов
|`files/share` | Каталог для неизменяемых файлов
|`files/var` | Каталог для изменяемых файлов
|`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
----
=== Инициализация проекта
Проект создаётся командой `myx-dev-git-init`. В качестве параметра можно
указать git-сервер, на котором планируется сохранять проект, и имя каталога
для проекта. Например:
[source,sh]
----
myx-dev-git-init -s git.246060.ru myx-cmake-example-base
----
Во время инициализации проекта создаются некоторые типовые каталоги:
IMPORTANT: Файлы `.gitkeep` позволяют защитить каталоги от удаления
(будет выводиться дополнительное предупреждение, что каталог не пуст) и
обеспечивают возможность помещения каталогов с систему контроля версий Git,
в которой пустые каталоги недопустимы (это правильно!).
WARNING: Эти команды выполнять не нужно.
[source,sh]
----
mkdir -p files/{etc,log,share,var}
touch files/{etc,log,share,var}/.gitkeep
----
а также автоматически создаётся типовой минимальный файл `CMakeLists.txt`,
загружаются файл для форматирования исходных текстов
на языке C++ `.uncrustify.cfg`, форматирования файлов CMake `.cmake-format.py`,
типовой файл исключений для Git `.gitignore`, файл `.gitlab-ci.yml` для правил
автоматической сборки проекта на сервере GitLab, файл `.clang-tidy` с правилами
для анализатора исходных текстов `.clang-tidy` и файлы сценариев для выполнения
автоматических действий в репозитории, которые устанавливаются в каталог `.git/hooks`.
Отправить изменения в проекте на сервер и сделать ветку `master` основной
(можно пропустить):
[source,sh]
----
cd myx-cmake-example-base
git remote add origin АДРЕС_РЕПОЗИТОРИЯ_НА_СЕРВЕРЕ
git push -u origin master
----
=== Базовые инструкции в CMake
В корневом каталоге проекта нужно создать файл `CMakeLists.txt`:
[source,cmake]
----
# Минимальная версия CMake
cmake_minimum_required(VERSION 3.3)
# Предпочтительно следовать стандартам принятым в указанном диапазоне версий
cmake_policy(VERSION 3.0.2..3.7)
# Название и версия проекта и используемые языки программирования
project(myx-cmake-example-base VERSION 0.2.0 LANGUAGES C CXX)
----
Значение версии проекта следует формировать согласно правилам
https://semver.org/lang/ru/[семантического версионирования].
[[project-required-variables]]
Для подключения функций для CMake из библиотеки MyxCMake, нужно добавить
в файл `CMakeLists.txt` строки, содержащие обязательные переменные:
[source,cmake]
----
###
# Обязательные переменные для MyxCMake
###
# Название организации
set(MYX_CMAKE_ORGANIZATION_NAME "Org." CACHE STRING "")
# Имя автора
set(MYX_CMAKE_AUTHOR_NAME "John Doe" CACHE STRING "")
# Почта автора
set(MYX_CMAKE_AUTHOR_EMAIL "mail@johndoe.com" CACHE STRING "")
# Краткое описание проекта
set(MYX_CMAKE_DESCRIPTION "Пример проекта: начало" CACHE STRING "")
find_package(MyxCMake 0.1.8 REQUIRED)
----
Значения обязательных переменных, используемых библиотекой MyxCMake
для архивирования исходных текстов, автоматического создания пакетов,
генерации документации, следует отредактировать, после чего
произведённые изменения можно зафиксировать:
[source,sh]
----
git commit -m "Подключение библиотеки MyxCMake" CMakeLists.txt
----
Чтобы проверить корректность подключения MyxCMake, можно выполнить команду:
[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 >= 3.3.2)
pkg_check_modules(UDEV udev)
----
Если настройка проекта завершается с ошибкой, то нужно установить пакеты:
[source,sh]
----
sudo apt-get install pkg-config libgsl-dev libfftw3-dev
----
=== Поиск с помощью функции `find_package`
Если системная библиотека поставляется без файла описания для `pkg-config`
или необходимо произвести более сложный поиск, например, включающий поиск
исполняемого файла, то может быть написан специальный модуль для `CMake`,
который вызывается функцией `find_package`. Примеры вызова функции:
[source,cmake]
----
# Поиск с помощью функции find_package
find_package(LibXml2)
find_package(CURL REQUIRED)
find_package(Boost 1.55.0 REQUIRED)
----
Если настройка проекта завершается с ошибкой, то нужно установить пакеты:
[source,sh]
----
sudo apt-get install libxml2-dev curl libcurl-dev libboost-all-dev
----
== Автоматически генерируемый заголовочный файл
На этапе конфигурирования проекта можно генерировать файлы, в которые будут записаны
собранные значения параметров. Функция `myx_cmake_generate_private_config_header()`,
из библиотеки MyxCMake создаёт файл `${CMAKE_BINARY_DIR}/include/myx_cmake_private_config.hpp`,
в который записывается информация о имени и версии проекта, дате и типе сборки.
[source,cmake]
----
# Автоматически генерируемый заголовочный файл
myx_cmake_generate_private_config_header()
----
== Автоматически генерируемый файл о состоянии проекта
Функция `myx_cmake_generate_git_info_header` библиотеки MyxCMake
предоставляет возможность генерировать при каждой сборке проекта
файл `${CMAKE_BINARY_DIR}/include/myx_cmake_git_info.hpp`,
в который записывается информация о теге, текущей ветки и последнем
коммите в ней.
[source,cmake]
----
# Автоматически генерируемый файл с информацией о репозитории
myx_cmake_generate_git_info_header()
----
== Примеры библиотек и приложений
[[base-lib-project]]
=== Базовая библиотека
Проект с базовой библиотекой реализован на основе <<base-project,базового проекта>>.
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
Проект можно посмотреть https://git.246060.ru/f1x1t/myx-cmake-example-library[здесь]
или сделать его копию командой:
[source,sh]
----
git clone --recursive https://git.246060.ru/f1x1t/myx-cmake-example-library
----
В находящийся в корневом каталоге проекта файл `CMakeLists.txt` нужно записать:
[source,cmake]
----
# Минимальная версия CMake
cmake_minimum_required(VERSION 3.3)
# Предпочтительно следовать стандартам принятым в указанном диапазоне версий
cmake_policy(VERSION 3.0.2..3.7)
# Название и версия проекта и используемые языки программирования
project(myx-cmake-example-library VERSION 0.2.0 LANGUAGES C CXX)
###
# Обязательные переменные для MyxCMake
###
# Название организации
set(MYX_CMAKE_ORGANIZATION_NAME "Org." CACHE STRING "")
# Имя автора
set(MYX_CMAKE_AUTHOR_NAME "John Doe" CACHE STRING "")
# Почта автора
set(MYX_CMAKE_AUTHOR_EMAIL "mail@johndoe.com" CACHE STRING "")
# Краткое описание проекта
set(MYX_CMAKE_DESCRIPTION "Пример проекта: библиотека" CACHE STRING "")
find_package(MyxCMake REQUIRED)
# Автоматически генерируемый заголовочный файл
myx_cmake_generate_private_config_header()
# Автоматически генерируемый файл с информацией о репозитории
myx_cmake_generate_git_info_header()
# Исходные тексты библиотеки
add_subdirectory(src/myx-cmake-example-library)
----
<<<
В подкаталоге `src/myx-cmake-example-library` нужно создать файл `CMakeLists.txt`:
[source,cmake]
----
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT myx-cmake-example-library)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/init.cpp)
# Список заголовочных файлов (используется для установки)
set(TRGT_hpp ${CMAKE_CURRENT_SOURCE_DIR}/init.hpp)
# Функция для создания цели, результатом которой будет сборка библиотеки
# Обязательно использовать тип OBJECT
add_library(${TRGT} OBJECT ${TRGT_cpp} ${TRGT_hpp})
# Автоматическая установка значений свойств для цели
myx_cmake_common_target_properties(${TRGT})
# Создание разделяемой библиотеки
myx_cmake_add_shared_library(${TRGT})
# Создание статической библиотеки
myx_cmake_add_static_library(${TRGT})
# Установка заголовочных файлов
install(FILES ${TRGT_hpp} COMPONENT dev DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${TRGT})
# Установка файла для pkg-config
myx_cmake_generate_pkgconfig(${TRGT} COMPONENT dev INSTALL_LIBRARY true)
----
<<<
файл `init.hpp`:
[source,cpp]
----
#ifndef MYX_CMAKE_EXAMPLE_LIBRARY_INIT_HPP_
#define MYX_CMAKE_EXAMPLE_LIBRARY_INIT_HPP_
#pragma once
#include <cstdint>
int32_t init( int32_t v );
#endif // MYX_CMAKE_EXAMPLE_LIBRARY_INIT_HPP_
----
и файл `init.cpp`:
[source,cpp]
----
#include <myx-cmake-example-library/init.hpp>
#include <cmath>
int32_t init( int32_t v = 0 )
{
int32_t s = 0;
for ( auto i = std::abs( v ); i > 0; i-- )
{
s += i;
}
return( s );
}
----
[[base-app-project]]
=== Базовое приложение
Проект с базовым приложением реализован на основе <<base-project,базового проекта>>.
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
Проект можно посмотреть https://git.246060.ru/f1x1t/myx-cmake-example-app[здесь]
или сделать его копию командой:
[source,sh]
----
git clone --recursive https://git.246060.ru/f1x1t/myx-cmake-example-app
----
<<<
В находящийся в корневом каталоге проекта файл `CMakeLists.txt` нужно записать:
[source,cmake]
----
# Минимальная версия CMake
cmake_minimum_required(VERSION 3.3)
# Предпочтительно следовать стандартам принятым в указанном диапазоне версий
cmake_policy(VERSION 3.0.2..3.7)
# Название и версия проекта и используемые языки программирования
project(myx-cmake-example-app VERSION 0.2.0 LANGUAGES C CXX)
###
# Обязательные переменные для MyxCMake
###
# Название организации
set(MYX_CMAKE_ORGANIZATION_NAME "Org." CACHE STRING "")
# Имя автора
set(MYX_CMAKE_AUTHOR_NAME "John Doe" CACHE STRING "")
# Почта автора
set(MYX_CMAKE_AUTHOR_EMAIL "mail@johndoe.com" CACHE STRING "")
# Краткое описание проекта
set(MYX_CMAKE_DESCRIPTION "Пример проекта: программа" CACHE STRING "")
find_package(MyxCMake REQUIRED)
# 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)
# Автоматически генерируемый заголовочный файл
myx_cmake_generate_private_config_header()
# Автоматически генерируемый файл с информацией о репозитории
myx_cmake_generate_git_info_header()
# Исходные тексты программы
add_subdirectory(src/myx-cmake-example-app)
----
В подкаталоге `src/myx-cmake-example-app` нужно создать файл `CMakeLists.txt`:
[source,cmake]
----
# Название основной цели и имени программы в текущем каталоге
set(TRGT myx-cmake-example-app)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
# Функция для создания цели, результатом которой будет сборка приложения
add_executable(${TRGT} ${TRGT_cpp})
myx_cmake_common_target_properties(${TRGT})
# Добавление к пути поиска заголовочных файлов
target_include_directories(${TRGT} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS})
# Правила для установки
install(TARGETS ${TRGT} COMPONENT main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
----
<<<
и файл `main.cpp`:
[source,cpp]
----
#include <myx_cmake_git_info.hpp>
#include <myx_cmake_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[] )
{
// Значение из myx_cmake_private_config.hpp
std::cout << "Build type: " << MYX_CMAKE_BUILD_TYPE << std::endl;
// Значение из myx_cmake_git_info.hpp
std::cout << "Git revision: " << MYX_CMAKE_EXAMPLE_APP_GIT_REV << std::endl;
auto s = nsum( argc );
std::cout << s << std::endl;
return ( s );
}
----
=== Подключение внешнего проекта
Проект, использующий для сборки внешний проект, реализован на основе проектов
<<base-lib-project,базовой библиотеки>> и <<base-app-project,базового приложения>>.
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
Проект можно посмотреть https://git.246060.ru/f1x1t/myx-cmake-example-app-ext[здесь]
или сделать его копию командой:
[source,sh]
----
git clone --recursive https://git.246060.ru/f1x1t/myx-cmake-example-app-ext
----
Для подключения проекта базовой библиотеки нужно выполнить:
[source,sh]
----
git submodule add https://git.246060.ru/f1x1t/myx-cmake-example-library thirdparty/myx-cmake-example-library
git submodule update --init --recursive
----
В находящийся в корневом каталоге проекта файл `CMakeLists.txt` нужно записать:
[source,cmake]
----
# Минимальная версия CMake
cmake_minimum_required(VERSION 3.3)
# Предпочтительно следовать стандартам принятым в указанном диапазоне версий
cmake_policy(VERSION 3.0.2..3.7)
# Название и версия проекта и используемые языки программирования
project(myx-cmake-example-app-ext VERSION 0.2.0 LANGUAGES C CXX)
###
# Обязательные переменные для MyxCMake
###
# Название организации
set(MYX_CMAKE_ORGANIZATION_NAME "Org." CACHE STRING "")
# Имя автора
set(MYX_CMAKE_AUTHOR_NAME "John Doe" CACHE STRING "")
# Почта автора
set(MYX_CMAKE_AUTHOR_EMAIL "mail@johndoe.com" CACHE STRING "")
# Краткое описание проекта
set(MYX_CMAKE_DESCRIPTION "Пример проекта: программа с поключенной библиотекой" CACHE STRING "")
find_package(MyxCMake REQUIRED)
# Подключение внешних проектов
include(ExternalProject)
ExternalProject_Add(extlib <1>
EXCLUDE_FROM_ALL TRUE
SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/myx-cmake-example-library <2>
INSTALL_DIR ${CMAKE_BINARY_DIR} <3>
DOWNLOAD_COMMAND ""
BUILD_BYPRODUCTS <INSTALL_DIR>/lib/libmyx-cmake-example-library.a
CMAKE_ARGS ${MYX_CMAKE_EXTERNAL_PROJECT_ARGS} -DBUILD_MYX_CMAKE_EXAMPLE_LIBRARY_SHARED=OFF <4>
)
# Исходные тексты программы
add_subdirectory(src/myx-cmake-example-app-ext)
----
<1> Название цели, от которой будет зависеть основная программа
<2> Каталог с внешней библиотекой
<3> Каталог, в который устаналиваются результаты сборки внешней библиотеки
<4> Аргументы для сборки внешней библиотеки
В результате будет создана цель `extlib`, являющаяся результатом сборки
подключённой библиотеки. Все функции `ExternalProject_Add` необходимо
располагать перед функциям `add_subdirectories`, чтобы в указанных подкаталогах
можно было использовать добавленные цели для определения зависимостей.
В файле `src/myx-cmake-example-app-ext/CMakeLists.txt` после создания цели `${TRGT}`
нужно подключить внешний проект `extlib`:
[source,cmake]
----
# Название основной цели и имени программы в текущем каталоге
set(TRGT myx-cmake-example-app-ext)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
# Функция для создания цели, результатом которой будет сборка приложения
add_executable(${TRGT} ${TRGT_cpp})
myx_cmake_common_target_properties(${TRGT})
# Зависимость от библиотеки из внешнего проекта
add_dependencies(${TRGT} extlib)
# Компоновка с библиотекой из внешнего проекта
target_link_libraries(${TRGT} myx-cmake-example-library)
----
<<<
Для проверки работоспособности в файле `src/myx-cmake-example-app-ext/main.cpp` нужно
вызвать функцию `init` из библиотеки, предоставляемой внешним проектом. Например:
[source,cpp]
----
#include <myx-cmake-example-library/init.hpp>
#include <iostream>
int main( int argc, char* argv[] )
{
auto s = init( argc );
std::cout << "Value: " << s << std::endl;
return ( 0 );
}
----
=== Qt5
В данном разделе будут приведены примеры создания консольного и графического
приложений, а также подключения локализации, вызовы препроцессоров `moc`,
`uic` и `rcc`.
[[qt5-con]]
==== Консольное приложение
Пример консольного приложения на Qt5 с поддержкой локализации основан
на проекте <<base-app-project,базового приложения>>.
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
Проект можно посмотреть https://git.246060.ru/f1x1t/myx-cmake-example-app-qt5-con[здесь]
или сделать его копию командой:
[source,sh]
----
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-app-qt5-con
----
<<<
В находящийся в корневом каталоге проекта файл `CMakeLists.txt` нужно записать:
[source,cmake]
----
# Минимальная версия CMake
cmake_minimum_required(VERSION 3.3)
# Предпочтительно следовать стандартам принятым в указанном диапазоне версий
cmake_policy(VERSION 3.0.2..3.7)
# Название и версия проекта и используемые языки программирования
project(myx-cmake-example-qt5-console VERSION 0.2.0 LANGUAGES C CXX)
###
# Обязательные переменные для MyxCMake
###
# Название организации
set(MYX_CMAKE_ORGANIZATION_NAME "Org." CACHE STRING "")
# Имя автора
set(MYX_CMAKE_AUTHOR_NAME "John Doe" CACHE STRING "")
# Почта автора
set(MYX_CMAKE_AUTHOR_EMAIL "mail@johndoe.com" CACHE STRING "")
# Краткое описание проекта
set(MYX_CMAKE_DESCRIPTION "Пример проекта: консольная программа Qt5" CACHE STRING "")
find_package(MyxCMake REQUIRED)
# Qt5
find_package(Qt5 COMPONENTS Core REQUIRED) <1>
find_package(Qt5Core COMPONENTS Private REQUIRED) <2>
# Исходные тексты программы
add_subdirectory(src/myx-cmake-example-qt5-console)
----
<1> Поиск необходимых компонентов Qt5
<2> Поиск приватных заголовочных файлов из пакета `qtbase5-private-dev`
<<<
В подкаталоге `src/myx-cmake-example-qt5-console` нужно создать файл `CMakeLists.txt`:
[source,cmake]
----
# Название основной цели и имени программы в текущем каталоге
set(TRGT myx-cmake-example-qt5-console)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
# Функция для создания цели, результатом которой будет сборка приложения
add_executable(${TRGT} ${TRGT_cpp})
myx_cmake_common_target_properties(${TRGT})
# Qt5: подключение заголовочных файлов
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_PRIVATE_INCLUDE_DIRS})
# Qt5: подключение библиотек
target_link_libraries(${TRGT} Qt5::Core)
----
<<<
Фалй `myx-cmake-example-qt5-console/main.cpp`:
[source,cpp]
----
#include <QCoreApplication>
#include <QDebug>
#include <QtCore/private/minimum-linux_p.h>
int main( int argc, char** argv )
{
QCoreApplication app( argc, argv );
qDebug() << "Qt5";
qDebug() << "Min Linux: " << MINLINUX_MAJOR << "." << MINLINUX_MINOR << "." << MINLINUX_PATCH;
return( 0 );
}
----
[[qt5-gui]]
==== Графическое приложение, файлы описания ресурсов и интерфейсов
Пример приложения на Qt5 с использованием графического интерфейса основан
на проекте <<qt5-con,консольного приложения для Qt5>>.
Исходные тексты содержат комментарии, объясняющие назначение используемых функций.
Проект можно посмотреть https://git.246060.ru/f1x1t/myx-cmake-example-qt5-gui[здесь]
или сделать его копию командой:
[source,sh]
----
git clone --recursive https://git.246060.ru/f1x1t/myx-cmake-example-qt5-gui
----
В находящийся в корневом каталоге проекта файл `CMakeLists.txt` нужно записать:
[source,cmake]
----
# Минимальная версия CMake
cmake_minimum_required(VERSION 3.3)
# Предпочтительно следовать стандартам принятым в указанном диапазоне версий
cmake_policy(VERSION 3.0.2..3.7)
# Название и версия проекта и используемые языки программирования
project(myx-cmake-example-qt5-gui VERSION 0.2.0 LANGUAGES CXX)
###
# Обязательные переменные для MyxCMake
###
# Название организации
set(MYX_CMAKE_ORGANIZATION_NAME "Org." CACHE STRING "")
# Имя автора
set(MYX_CMAKE_AUTHOR_NAME "John Doe" CACHE STRING "")
# Почта автора
set(MYX_CMAKE_AUTHOR_EMAIL "mail@johndoe.com" CACHE STRING "")
# Краткое описание проекта
set(MYX_CMAKE_DESCRIPTION "Пример проекта: графическая программа Qt5" CACHE STRING "")
find_package(MyxCMake REQUIRED)
# Qt5
find_package(Qt5Core COMPONENTS Private REQUIRED)
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
# Исходные тексты программы
add_subdirectory(src/myx-cmake-example-qt5-gui)
----
В подкаталоге `src/myx-cmake-example-qt5-gui` нужно создать файл `CMakeLists.txt`:
[source,cmake]
----
# Название основной цели и имени программы в текущем каталоге
set(TRGT myx-cmake-example-qt5-gui)
# cmake-format: off
###
# Списки файлов проекта
###
# Исходные коды
set(TRGT_cpp
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_window.cpp)
# Заголовочные файлы, для которых необходима обработка препроцессором moc
# (содержат класс, унаследованный от QObject, использующий сигналы и/или слоты)
set(TRGT_moc_hpp
${CMAKE_CURRENT_SOURCE_DIR}/test_window.hpp)
# Другие заголовочные файлы
set(TRGT_hpp)
# Файлы с описанием графического интерфейса для Qt
set(TRGT_ui
${CMAKE_CURRENT_SOURCE_DIR}/test_window.ui)
# Файлы описания ресурсов, включаемых в исполняемый файл
set(TRGT_qrc
${CMAKE_SOURCE_DIR}/files/share/icon.qrc)
###
# Конец списков файлов
###
# cmake-format: on
set(TRGT_headers ${TRGT_hpp} ${TRGT_moc_hpp})
# Правило для автоматической генерации препроцессором uic
qt5_wrap_ui(TRGT_ui_h ${TRGT_ui})
# Правило для автоматической генерации препроцессором moc
qt5_wrap_cpp(TRGT_moc_cpp ${TRGT_moc_hpp})
# Правило для автоматической генерации препроцессором qrc
# (обязательно после вызова функции qt5_translation, если она есть,
# так как она добавляет свои файлы к списку ресурсов)
qt5_add_resources(TRTG_qrc_cpp ${TRGT_qrc})
# Функция для создания цели, результатом которой будет сборка приложения
add_executable(${TRGT} ${TRGT_headers} ${TRGT_ui_h} ${TRGT_moc_cpp} ${TRGT_qrc_cpp} ${TRGT_cpp})
myx_cmake_common_target_properties(${TRGT})
# Qt5: подключение заголовочных файлов
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Gui_INCLUDE_DIRS})
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Widgets_INCLUDE_DIRS})
# Qt5: подключение библиотек
target_link_libraries(${TRGT} Qt5::Core Qt5::Gui Qt5::Widgets)
----
В каталоге `files/share` создать файл описания включаемых ресурсов `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/myx-cmake-example-qt5-gui/raw/branch/master/files/share/icon.png
----
Для графического приложения нужно создать файл описания интерфейса
`src/myx-cmake-example-qt5-gui/test_window.ui`:
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TestWindow</class>
<widget class="QMainWindow" name="TestWindow">
<property name="geometry">
<rect><x>0</x><y>0</y><width>413</width><height>253</height></rect>
</property>
<property name="windowTitle">
<string>Test Window</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="exitButton">
<property name="geometry">
<rect><x>170</x><y>30</y><width>80</width><height>26</height></rect>
</property>
<property name="text">
<string>Press me</string>
</property>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>
----
<<<
заголовочный файл `src/myx-cmake-example-qt5-gui/test_window.hpp`:
[source,cpp]
----
#ifndef TEST_WINDOW_HPP_
#define TEST_WINDOW_HPP_
#pragma once
#include "ui_test_window.h"
#include <QMainWindow>
class TestWindow : public QMainWindow, private Ui::TestWindow
{
Q_OBJECT
public:
TestWindow( QMainWindow* parent = nullptr );
virtual ~TestWindow();
};
#endif /* TEST_WINDOW_HPP_ */
----
и файл с реализацией конструктора, в котором проводится инициализация
графических элементов, `src/myx-cmake-example-qt5-gui/test_window.cpp`:
[source,cpp]
----
#include "test_window.hpp"
TestWindow::TestWindow( QMainWindow* parent ) :
QMainWindow ( parent ),
Ui::TestWindow()
{
setupUi( this );
}
TestWindow::~TestWindow() = default;
----
<<<
Для отображения графического окна нужно создать файл
`src/myx-cmake-example-qt5-gui/main.cpp`:
[source,cpp]
----
#include "test_window.hpp"
#include <QApplication>
#include <QIcon>
int main( int argc, char** argv )
{
QApplication app( argc, argv );
// Установка иконки для программы
QApplication::setWindowIcon( QIcon( ":/icon/icon.png" ) );
// Создание и отображение главного окна
auto* w = new TestWindow();
w->show();
return( QApplication::exec() );
}
----
== Дополнительные возможности
Библиотека MyxCMake содержит шаблонные функции для использования
в программных проектах. Цели для автоматического форматирования и статического
анализа исходных текстов создаются автоматически при вызове функции
`myx_cmake_common_target_properties` из библиотеки MyxCMake.
=== Форматирование исходных текстов
Функция `myx_cmake_common_target_properties` создаёт для файлов исходных текстов,
формирующих цель, дополнительные цели `${target}-format-sources-uncrustify`
для форматирования исходных текстов на языке C{plus}{plus} в соответствии с правилами,
перечисленными в файле `.uncrustify.cfg`, находящимся в корне проекта, а также
`${target}-format-sources-dos2unix` для преобразования переводов строк в
файлах к стандарту, принятому в Unix. Для проекта создаётся цель `myx-cmake-format-sources`,
которая объединяет все цели, выполняющие форматирование исходных текстов.
IMPORTANT: Настройка правил форматирования помогает другим разработчикам
придерживаться вашего стиля программирования и отправлять изменения в ваш
проект в формате, который удобен вам. Проявите заботу о своих коллегах и
своём проекте!
Чтобы выполнить форматирование, нужно в каталоге `${CMAKE_BINARY_DIR}`
выполнить команду:
[source,sh]
----
make myx-cmake-format-sources
----
При создании типового проекта командой `myx-dev-git-init` к локальному
репозиторию подключается обработчик, который автоматически проверяет
исходные тексты на соответствие стандарту форматирования перед
выполнением фиксации (`pre-commit`). Таким образом в репозитории будут
сохраняться исходные тексты, соответствующие принятым правилам форматирования.
=== Статический анализ исходных кодов
Для работы с программами на языке C{plus}{plus} используются утилиты,
выполняющие статический анализ кода и генерирующие отчёты, помогающие
программисту находить и устранять ошибки. Эти программы применяют методы,
позволяющие в синтаксически корректном коде находить недостатки или ошибки,
которые пропускает компилятор, ценой продолжительного анализа исходных текстов.
Библиотека MyxCMake поддерживает анализаторы 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].
[[analyze-clazy]]
==== clazy
Функция `myx_cmake_common_target_properties` создаёт для файлов исходных
текстов, формирующих цель, дополнительную цель `${target}-analyze-clazy`
для проверки исходных текстов анализатором `clang`.
Для всего проекта создаётся цель `myx-cmake-analyze-clazy`, которая
выполняет все цели для анализатора.
Чтобы выполнить статический анализ, нужно в каталоге `${CMAKE_BINARY_DIR}`
выполнить команду:
[source,sh]
----
make myx-cmake-analyze-clazy
----
[[analyze-clang-check]]
==== Clang Static Analyzer
Функция `myx_cmake_common_target_properties` создаёт для файлов исходных
текстов, формирующих цель, дополнительную цель `${target}-analyze-clang-check`
для проверки исходных текстов анализатором `clang-check`.
Для всего проекта создаётся цель `myx-cmake-analyze-clang-check`, которая
выполняет все цели для анализатора.
Чтобы выполнить статический анализ, нужно в каталоге `${CMAKE_BINARY_DIR}`
выполнить команду:
[source,sh]
----
make myx-cmake-analyze-clang-check
----
[[analyze-clang-tidy]]
==== Clang Tidy
Функция `myx_cmake_common_target_properties` создаёт для файлов исходных
текстов, формирующих цель, дополнительную цель `${target}-analyze-clang-tidy`
для проверки исходных текстов анализатором `clang-tidy`.
Для всего проекта создаётся цель `myx-cmake-analyze-clang-tidy`, которая
выполняет все цели для анализатора.
Чтобы выполнить статический анализ, нужно в каталоге `${CMAKE_BINARY_DIR}`
выполнить команду:
[source,sh]
----
make myx-cmake-analyze-clang-tidy
----
[[analyze-pvs-studio]]
==== PVS-Studio
Функция `myx_cmake_common_target_properties` создаёт для всего проекта
цель `myx-cmake-analyze-clang-tidy` для проверки исходных текстов
анализатором `pvs-studio-analyzer`.
Чтобы выполнить статический анализ, нужно в каталоге `${CMAKE_BINARY_DIR}`
выполнить команду:
[source,sh]
----
make myx-cmake-analyze-pvs-studio
----
=== Автоматическое исправление кода
IMPORTANT: Редактирование кода в автоматическом режиме может приводить
к его неработоспособности, хотя это и маловероятно. Перед выполнением
действий, приведённых в данном раздела, желательно фиксировать текущее
состояние в репозитории или делать резервную копию.
==== clazy
Программа clazy может преобразовывать в программах, использующих Qt,
подключения сигналов и слотов старого типа, производить замену старых ключевых
слов, подставлять оптимизированные способы для инициализации строк,
исправлять циклы и передачу аргументов в функции для избежания лишних копирований.
Для включения автоматического исправления нужно в настройках сборки проекта
menu:Проекты[Настройки сборки] выбрать цель `myx-cmake-analyze-clazy`:
[.text-center]
.Выбор цели
image::cmake-fixes/clazy1.png[clazyfix1,pdfwidth=90%,scaledwidth=90%,align="center"]
{empty} +
Затем в перечне опций включить `MYX_CMAKE_CLAZY_FIX`, нажать кнопку
btn:[Применить изменения], а затем скомпилировать проект kbd:[Ctrl+B]:
[.text-center]
.Разрешение автозамены
image::cmake-fixes/clazy2.png[clazyfix2,pdfwidth=90%,scaledwidth=90%,align="center"]
{empty} +
Пример проекта, в котором показаны возможности `clazy`, можно посмотреть
https://git.246060.ru/f1x1t/cmlib-example-clazy-fix[здесь]. Содержание
изменений, произведённых автоматически, можно увидеть
https://git.246060.ru/f1x1t/cmlib-example-clazy-fix/commit/81ed1e72b14f17bac0a39ab41bc3ba0ba2bdcb8e?style=split[здесь].
Можно сделать копию репозитория и выполнить правки в автоматическом режиме
самостоятельно:
[source,sh]
----
git clone --recursive https://git.246060.ru/f1x1t/cmlib-example-clazy-fix
----
==== Clang-Tidy
Анализатор Clang-Tidy предоставляет более широкие возможности по
автоматической правке кода. В проектах, использующих Qt, желательно
использовать Clang-Tidy после clazy.
Для включения автоматического исправления нужно в настройках сборки проекта
menu:Проекты[Настройки сборки] выбрать цель `clang-tidy-check`:
[.text-center]
.Выбор цели
image::cmake-fixes/clang-tidy1.png[clangtidyfix1,pdfwidth=90%,scaledwidth=90%,align="center"]
{empty} +
Затем в перечне опций включить `MYX_CMAKE_CLANG_TIDY_FIX`, нажать кнопку
btn:[Применить изменения], а затем скомпилировать проект kbd:[Ctrl+B]:
[.text-center]
.Разрешение автозамены
image::cmake-fixes/clang-tidy2.png[clangtidyfix2,pdfwidth=90%,scaledwidth=90%,align="center"]
{empty} +
=== Динамический анализ программы
Динамический анализ программы позволяет ценой значительного замедления
скорости работы получить дополнительную информацию о ходе её выполнения.
Современные компиляторы делают вставку инструкций в определённые точки
программы, во время работы программы в них собирается необходимая информация,
а по её завершению предоставляется отчёт. Основная информация о работе
таких анализаторов находится https://github.com/google/sanitizers/wiki[здесь].
Для обеспечения возможности подключения динамического анализа к проекту
нужно выполнить функцию (обязательно после подключения всех библиотек):
[source,cmake]
----
# Подключение настроек для динамического анализа программы
add_sanitizers(${TRGT})
----
Подключение анализатора осуществляется включением опций при запуске
CMake для генерации сборочных файлов. Некоторые из опций между собой
несовместимы, в случае попытки совместного использования будет выведено
сообщение об ошибке.
.Назначение опций для динамического анализа
[cols="2m,7",options="header"]
|===
| Опция | Назначение
| SANITIZE_ADDRESS | Определение ошибок при работе с памятью: использование после освобождения,
использование за пределами области видимости, переполнения буферов в стеке, на куче, в общей памяти,
утечки памяти, нарушение порядка инициализации
| SANITIZE_CFI | Определение нарушений путей исполнения инструкций программы
| SANITIZE_LEAK | Определение утечек памяти
| SANITIZE_LINK_STATIC | Статическая компоновка анализатора с программой
| SANITIZE_MEMORY | Определение попыток доступа к неинициализированным областям памяти
| SANITIZE_SS | Определение переполнения буфера стека
| SANITIZE_THREAD | Определение состояние гонок
| SANITIZE_UNDEFINED | Определение невыровненных и нулевых указателей, переполнения знаковых целых,
преобразования типов с плавающей точкой, ведущих к переполнению результирующей переменной
|===
=== Анализ покрытия кода
Для сбора информации о точном количестве исполнений
для каждого оператора в программе используется программа
https://gcc.gnu.org/onlinedocs/gcc/Gcov.html[Gcov],
входящая в состав компилятора https://gcc.gnu.org[GCC].
Для обеспечения возможности подключения анализа покрытия кода к проекту
нужно выполнить функцию (обязательно после подключения всех библиотек):
[source,cmake]
----
# Подключение возможности использования утилиты Gcov
# для исследования покрытия кода
add_code_coverage(${TRGT})
----
Подключение осуществляется включением опции `ENABLE_CODE_COVERAGE`
при запуске CMake для генерации сборочных файлов. В результате будут
созданы две дополнительные цели `coverage-${TRGT}` для сбора статистики
после работы программы и `coverage-report-${TRGT}` для её вывода
в виде HTML-страниц.
Пример анализа покрытия кода на примере проекта `cmlib-example-app-features`:
[source,sh]
----
mkdir -p _build/debug
cd _build/debug
cmake ../.. -DENABLE_CODE_COVERAGE=ON -DCMAKE_BUILD_TYPE=Debug
make
bin/cmlib-example-app-features
make coverage-cmlib-example-app-features
make coverage-report-cmlib-example-app-features
----
После выполнения этих команд в каталоге `report-cmlib-example-app-features`
будет сформирован отчёт в виде HTML-страниц.
=== Профилирование кода
Библиотека CMLib предоставляет вариант сборки для профилирования кода,
для которого можно сгенерировать сборочные файлы, присвоив переменной
`CMAKE_BUILD_TYPE` значение `Profile`:
[source,sh]
----
mkdir -p _build/profile
cd _build/profile
cmake ../.. -DCMAKE_BUILD_TYPE=Profile
----
По окончании работы исполняемого файла будет сгенерирован файл
`gmon.out`, по данным из которого можно строить отчёты утилитой `gprof`.
Например:
[source,sh]
----
./cmlib-example-app-features
gprof -b cmlib-example-app-features gmon.out > analysis-tree.txt
gprof -b -p cmlib-example-app-features gmon.out > analysis-flat.txt
----
=== Ускорение компиляции
Для ускорения компиляции используется сторонний модуль
https://github.com/sakra/cotire[cotire], который автоматизирует
использование предварительно откомпилированных заголовков и
организует пакетный режим обработки исходных файлов в генератора.
Аналогичные функции встроены в CMake, начиная с версии 3.16.
Для обеспечения возможностей, предоставляемых модулем cotire,
нужно выполнить функцию (обязательно после подключения всех библиотек):
[source,cmake]
----
# Подключение возможности включения пакетного режима обработки
# исходных файлов в генераторах для ускорения сборки
cotire(${TRGT})
----
В результате будут созданы цели с суффиксом `_unity`, при сборки
которых будут применяться приведённые выше методы ускорения.
Пример использования cotire для ускорения сборки
на примере проекта `cmlib-example-app-features`:
[source,sh]
----
mkdir -p _build/debug
cd _build/debug
cmake ../..
make all_unity
----
=== Документирование кода
Для документирования кода используются блоки комментариев,
оформленные для обработки программой https://www.doxygen.nl[Doxygen].
Установка программы:
[source,sh]
----
sudo apt-get install doxygen
----
Пример комментария:
[source,c++]
----
/**
* @brief Базовый класс
*/
class Base {
public:
/**
* @brief Конструктор
*/
Base();
/**
* @brief Деструктор
*/
~Base();
/**
* @brief Вычисление квадратного корня
* @param value Входное значение
* @return Квадратный корень от value
*/
double sqrt(double value);
};
----
Поддержка автоматической генерации документации реализована
в функциях библиотеки CMLib `add_doxygen_target` и
`add_breathe_target`, которые необходимо вызвать в основном
файле `CMakeLists.txt` проекта.
[source,cmake]
----
# Документация
add_doxygen_target(doc-doxygen LATEX YES HTML YES)
add_breathe_target(doc-breathe)
----
В результате будут добавлены цели `doc-doxygen` и `doc-breathe`,
которые можно использовать после конфигурирования проекта:
[source,cmake]
----
make doc-doxygen
make doc-breathe
----
Шаблоны для комментирования файлов, классов и функций
можно автоматически расставить в файлах исходных кодов
исполнением цели `doc-add-comments` при наличии установленной
программы `uncrustify`:
[source,cmake]
----
make doc-add-comments
----
== Удаление установленных файлов
В библиотеку MyxCMake добавлена цель `uninstall`, позволяющая удалить файлы,
которые могут быть установлены в результате выполнения цели `install`:
[source,sh]
----
cd _build
make install
make uninstall
----
== Архивирование проекта и создание пакетов
Стандартный модуль `CPack` предназначен для архивирования исходных
текстов проекта и создания пакетов для установки в целевую систему.
Необходимые переменные устанавливаются в начале файла `CMakeLists.txt`
<<project-required-variables,см. выше>>.
Библиотека MyxCMake предоставляет возможность стандартного разбиения
на пакеты в соответствии с критериями, приведёнными в таблице.
.Критерии разбиения на пакеты
[cols="3m,3m,8",options="header"]
|===
| Компонент | Имя пакета | Назначение
| main | proj | Основные файла проекта (исполняемые файлы, файлы данных, настроек, ресурсов)
| dev | libproj-dev | Заголовочные файлы, дополнительные файлы необходимые для разработки
| static | libproj-static-dev | Статические библиотеки
| doc | proj-doc | Документация
|===
Принадлежность устанавливаемого файла к компоненту определяется с помощью
параметра `COMPONENT` функции `install`. В компонент `main` необходимо
помещать файлы для установки на целевую систему (исполняемые файлы,
файлы настроек, файлы данных, разделяемые библиотеки), в компоненты `dev`
и `static` --- для установки на систему для разработки (заголовочные
файлы, статические библиотеки). Пример включения устанавливаемых файлов
в компоненты можно посмотреть
https://git.246060.ru/f1x1t/myxlib/src/branch/master/src/myx/base/CMakeLists.txt#L46-L54[здесь].
По умолчанию цель для упаковки исходных текстов называется `package_source`,
цель для создания общего архива скомпилированного проекта --- `package`,
цель для создания пакетов в формате Debian --- `deb`.
Примера работы с архивированием можно сделать копию репозитория
библиотеки https://git.246060.ru/f1x1t/myxlib[MyXLib]:
[source,sh]
----
git clone --recursive https://git.246060.ru/f1x1t/myxlib
----
Дальнейшие шаги:
[source,shell]
----
cd myxlib # <1>
mkdir -p _build/debug # <2>
cd _build/debug # <3>
cmake ../.. -DMYXLIB_BUILD_LIBRARIES=ON -DMYXLIB_BUILD_EXAMPLES=ON # <4>
make -j4 # <5>
make doc-doxygen # <6>
make package # <7>
make package_source # <8>
make deb # <9>
----
<1> Перейти в каталог проекта
<2> Создать каталог для сборки проекта
<3> Перейти в каталог для сборки проекта
<4> Создать конфигурацию для сборки проекта
<5> Скомпилировать проект
<6> Сгенерировать документацию
<7> Создать архив с результатами компиляции `myx_amd64_0.4.0.tar.xz`
<8> Создать архив с исходными текстами `myx-0.4.0.tar.xz`
<9> Создать пакеты в формате Debian