= 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 Hitchhiker’s 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
