# Использование conan-пакетов для разработки приложений для ОС Аврора

## Технологические ограничения

В настоящий момент conan-пакеты могут быть использованы только при разработке
CMake-приложений для ОС Аврора. Приложения, разрабатываемые с использованием
системы сборки qmake не поддерживается.

Библиотеки, поставляемые в рамках conan-репозитория, распространяются
исключительно в бинарном формате и не поддерживают компиляцию на стороне
клиента.

Инструмент копирования зависимостей внутрь RPM-пакета приложения поддерживает
установку только библиотек в формате pkg-config.

## Подключение conan-библиотек к CMake-приложению

Для подключения библиотек необходимо выполнить следующие шаги:

1. Сформировать список используемых библиотек.
2. Настроить установку библиотек в рамках процесса сборки приложения внутри
   spec-файла.
3. Подключить использование библиотек внутри конфигурации сборочной среды CMake.
4. Настроить RPath в исполняемом файле для подключения библиотек на мобильном
   устройстве в момент запуска приложения.
5. Настроить корректное добавление библиотек в RPM-архив внутри spec-файла.

### Формирование списка библиотек

В приложении необходимо добавить файл с описанием зависимостей. Ввиду
особенностей работы QtCreator в Аврора SDK рекомендуется использовать следующий
шаблон в формате Python-файла для описания зависимостей.

Предположим, что приложению необходимо использовать библиотеку ffmpeg. В данном
случае зависимости описываются в файле `conanfile.py` следующего содержимого:

```
from conan import ConanFile

class Application(ConanFile):
    settings = "os", "compiler", "arch", "build_type"
    generators = "PkgConfigDeps"

    requires = (
        "ffmpeg/6.1.1@aurora",
    )
```

Данный файл настраивает установку conan-пакетов с целью их дальнейшего
использования с помощью pkg-config, который можно интегрировать в другие системы
сборки. Для этих целей подключается генератор PkgConfigDeps.

В кортеже `requires` перечисляются библиотеки, используемые приложением. Каждая
строка описывает отдельную зависимость. В данном случае в строкой
`ffmpeg/6.1.1@aurora` описывается:

- `ffmpeg` — название пакета, который будет скачан.
- `6.6.1` —-версия пакета для скачивания.
- `@aurora` — имя автора пакета, в данном случае `aurora`.

### Установка зависимостей во время сборки

В spec-файле приложения необходимо выполнить следующие изменения, чтобы
выполнить сборку приложения.

Сначала в списке зависимостей необходимо указать зависимость от conan:

```
BuildRequires:  conan
```

Затем в рамках секции `%build` необходимо выполнить установку зависимостей перед
первым вызовом CMake, в рамках которого генерируются файлы сборочной
последовательности. Установку рекомендуется выполнять с помощью следующих
команд:

```
CONAN_LIB_DIR="%{_builddir}/conan-libs/"
%{set_build_flags}
conan-install-if-modified --source-folder="%{_sourcedir}/.." --output-folder="$CONAN_LIB_DIR" -vwarning
PKG_CONFIG_PATH="$CONAN_LIB_DIR":$PKG_CONFIG_PATH
export PKG_CONFIG_PATH
```

Переменная `CONAN_LIB_DIR` указывает путь к каталогу с устанавливаемыми файлами.
Данный каталог будет располагаться в сборочном каталоге приложения.

Команде `conan-install-if-modified` передаются следующие аргументы:

- `--source-folder="%{_sourcedir}/.."` указывает на каталог с исходными кодами приложения, в
  котором находится файл `conanfile.txt`.
- `--output-folder="$CONAN_LIB_DIR"` указывает путь к каталогу для установки
  зависимостей.
- `-vwarning` указывает желаемый уровень вывода сообщений. Уровень сообщений по
  умолчанию предоставляет больше информации, но провоцирует среду разработки
  сообщать о наличии проблем во время сборки.
- Также команде можно передать любые другие параметры, которые она передаст в conan.

Затем происходит формирование переменной окружения `PKG_CONFIG_PATH`, в которой
указывается путь к установленным библиотекам. Данная переменная затем будет
использована внутри конфигурации системы сборки для поиска зависимостей.

Таким образом первые секция `%build` будет выглядеть следующим образом:

```
CONAN_LIB_DIR="%{_builddir}/conan-libs/"
%{set_build_flags}
conan-install-if-modified --source-folder="%{_sourcedir}/.." --output-folder="$CONAN_LIB_DIR" -vwarning
PKG_CONFIG_PATH="$CONAN_LIB_DIR:$PKG_CONFIG_PATH"
export PKG_CONFIG_PATH
%cmake
%make_build
```

### Использование conan-библиотек внутри CMake

Библиотека подключается штатными средствами CMake.

1. Сначала необходимо выполнить подключение пакета PkgConfig, который
   обеспечивает поиск библиотек через приложение pkg-config:
   ```
   find_package(PkgConfig REQUIRED)
   ```
2. Затем для каждой подключаемой библиотеки необходимо выполнить подключение
   библиотеки. В случае с ffmpeg подключение будет выглядеть следующим образом:
   ```
   pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET ffmpeg)
   ```

   Параметр `REQUIRED` указывает, что эта зависимость является обязательной.
   Параметр `IMPORTED_TARGET` позволяет обращаться к библиотеке как к цели в
   терминах CMake по имени `PkgConfig::FFMPEG`.
3. Данную библиотеку необходимо подключить к списку каталогов с заголовочными
   файлами:
   ```
   target_include_directories(${PROJECT_NAME} PRIVATE
     $<BUILD_INTERFACE:
     ...
     PkgConfig::FFMPEG
     >
   )
   ```
4. Также необходимо выполнить линковку с данными библиотеками:
   ```
   target_link_libraries(
     ${PROJECT_NAME}
     ...
     PkgConfig::FFMPEG
   )
   ```

### Использование conan-пакетов с QML-модулями

В случаях, когда conan-пакет содержит QML-модуль, к обычному алгоритму подключения
пакета добавляется ещё один шаг.

Требуется указать в файле с точкой в хода в приложение `main.cpp` путь к модулям.
Все поставляемые conan-пакетами QML-модули устанавливаются по пути `/usr/share/<название пакета приложения>/lib/qmlplugins`.
Поэтому для их подключение потребуется внести следующие правки:

```cpp
QScopedPointer<QQuickView> view(Aurora::Application::createView());
auto engine = view->engine();
engine->addImportPath(Aurora::Application::pathTo(QStringLiteral("lib/qmlplugins")).toString());
```

### Настройка rpath исполняемого файла в CMake

Согласно [требованиям к установочным пакетам](https://developer.auroraos.ru/doc/software_development/guidelines/rpm_requirements)
в ОС Аврора разделяемые библиотеки приложения должны быть установлены в каталог
`/usr/share/<название пакета>/lib`. Чтобы этот каталог использовался приложением
при старте, данный путь должен быть указан внутри rpath исполняемого файла.

Для решения этой задачи необходимо в начале spec-файла добавить следующую
строчку:

```
%define _cmake_skip_rpath %{nil}
```

Также внутри CMake-файла необходимо перед определением исполняемого файла
настроить rpath по умолчанию. Следующая конструкция настраивает корректный путь
для любого приложения.

```
set(CMAKE_SKIP_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/lib")

```

### Перенос библиотек в RMP-файл

В рамках секции `%install` необходимо поместить все разделяемые библиотеки в
целевой каталог. Следующие команды создают данный каталог и копируют в него
файлы разделяемых библиотек, которые были явно связаны с исполняемым файлом.
Если необходимо перенести больше данных, то эту секцию необходимо
модифицировать.

```
CONAN_LIB_DIR="%{_builddir}/conan-libs/"
SHARED_LIBRARIES="%{buildroot}/%{_datadir}/%{name}/lib"
mkdir -p "$SHARED_LIBRARIES"
conan-deploy-libraries "%{buildroot}/%{_bindir}/%{name}" "$CONAN_LIB_DIR" "$SHARED_LIBRARIES"
```

Также необходимо выполнить корректную модификацию RPM-архива, чтобы он не
предоставлял данные библиотеки для других RPM-архивов. Это реализуется путём
добавления следующих директив в .spec-файл:

```
%define __provides_exclude_from ^%{_datadir}/%{name}/lib/.*$
%define __requires_exclude ^(libavcodec.*|libavdevice.*|libavfilter.*|libavformat.*|libavutil.*|libswresample.*|libswscale.*)$
```
