Всем привет!
Сегодня мы хотим поговорить о нашем опыте работы с пакетным менеджером Conan.io. Если вы так же, как и наша команда разработки Efros Config Inspector столкнулись с вопросами сборки под различные операционные системы, включая отечественные, и используете сторонние библиотеки, возможно, этот материал будет вам интересен.
Conan.io или…?
Efros Config Inspector был разработан как Windows приложение, но впоследствии было принято решение обеспечить совместимость и с отечественными ОС, такими как Astra Linux и РЕДОС. В процессе реализации этой задачи мы столкнулись с рядом трудностей, решить которые могли, во-первых, смена системы сборки программного обеспечения, во-вторых, подключение пакетного менеджера.
Разработка продукта велась на основе технологий Microsoft (Visual Studio и Team Foundation Server), но, как известно, это не самое удобное решение для сборки проекта под *.nix-системы, поэтому появились инструменты CMake. Тема выбора CMake достойна отдельной статьи. Если она вам интересна, напишите в комментариях, и мы обязательно вернемся к обсуждению данного вопроса в следующих публикациях.
А теперь поговорим о Conan. Основные требования, которые мы предъявляли к пакетному менеджеру, – кроссплатформенность и удобство в расширении списка пакетов. Более того, для нас было важно, чтобы в ходе работы менеджер позволял использовать не только пакеты со сторонними библиотеками, но и давал возможность создавать свои собственные.
Потенциально с такой задачей могли справиться Conan.io или vcpkg. Однако по результатам исследований мы определили, что vcpkg нам не подходит из-за особенностей разработки пакетов и сложностей с поддержкой различных версий пакетов.
Изучив документы и статьи о Conan.io, мы окончательно определились с выбором. Советуем ознакомиться с этими материалами, если вы в поиске подходящего решения:
- Welcome to Conan
- Conan: менеджер зависимостей для C/C++
- Jinja2 в мире C++, часть третья. «Теперь ты в конане»
Выбор нас не разочаровал, но без традиционной «ложки дёгтя» тоже не обошлось. Однако обо всём по порядку.
Весомыми достоинствами продукта для нас стали:
- Простота создания своих рецептов и пакетов на их основе.
- Отличная интеграция проектов в CMake.
- Исходный код рецептов, разрабатываемый на Python. Это просто и понятно для большинства членов команды разработки.
- Клиент-серверная архитектура. Такая организация позволяет развернуть собственный сервер пакетов и хранить их централизованно, используя только необходимые в текущий момент.
- Большой репозиторий уже готовых пакетов с библиотеками под различные окружения сборки. Это позволяет использовать существующие библиотеки или собирать свои по имеющимся рецептам.
Теперь подробнее рассмотрим каждый из приведенных выше аспектов.
Собственный сервер с пакетами
JFrog-Artifactory-Cpp-CE от jfrog – немного усилий, и вы уже можете развернуть репозиторий Conan-пакетов на любом поддерживаемом вычислительном комплексе и производить с ним массу манипуляций. Работать с JFrog очень удобно, особенно при условии, что он собран для множества платформ и для него уже есть готовый docker-образ. Сервис имеет удобный web-интерфейс для конфигурирования репозиториев и выполнения операций с пакетами (перенос/копирование/удаление) внутри репозиториев. Пример внешнего вида окна управления пакетами в репозиториях:
Необходимость создания собственного сервера пакетов возникла потому, что на официальном сервере Conan.io отсутствует часть необходимых библиотек, а также отсутствует доступ в интернет из сети, в которой функционируют агенты сборки продукта. Те, кто уже используют дистрибутив Conan, знают, что в него входит приложение, реализующее серверную часть, но нам было гораздо удобнее использовать продукт от jfrog, так как он включал в себя все необходимые функции для менеджмента пакетов с библиотеками, а также имел весьма дружелюбный интерфейс. Инструкцию по установке JFrog-Artifactory можно найти по следующей ссылке: Installing+Artifactory.
Важно, что Conan не только позволяет создавать пакеты, но и обладает большой базой готовых решений в центральном общедоступном репозитории – Conan-center, который содержит много популярных библиотек, собранных под различные окружения. Даже если нужной вам библиотеки не нашлось, можно использовать его как огромную базу примеров рецептов, из которой вы сможете почерпнуть все необходимые знания и создавать свои библиотеки.
Что касается собственных рецептов пакетов, то они весьма просто разрабатываются на Python, а для разных платформ и средств сборки существует множество python-утилит из дистрибутива Сonan. Хотите собрать вашу библиотеку с помощью MSVS? Пожалуйста – используйте утилиту VisualStudioBuildEnvironment. Ваша библиотека собирается с помощью скриптов configure? Нет ничего проще – разработчики предоставляют вам AutoToolsBuildEnvironment.
Со всеми доступными утилитами сборки можно ознакомиться в официальной документации.
Отметим, что разработка собственных пакетов является гибкой и функциональной. Это стало большим плюсом при работе с продуктом.
CMake + Conan.io = Power
Теперь поговорим о совместимости CMake и Conan.io. Применение Conan.io для проектов, написанных с использованием CMake, превращается в запуск пары Сmake-команд, которые открывают для вас все возможности сторонних библиотек. Изучить механизмы интеграции более подробно можно по ссылке: CMake+Conan.io
Перейдём к практике и рассмотрим реальные примеры из нашего проекта. Для интеграции Conan.io в CMake нам понадобились следующие инструменты:
1. Специальный модуль формата cmake, который обеспечивает инициализацию всех необходимых параметров (переменных с путями до бинарных файлов, интерфейсные переменные для линковки и т.д.) для работы с библиотеками внутри CMakeLists.txt. Модуль доступен из официального репозитория на GitHub.
2. Файл (conanfile.txt), содержащий список необходимых библиотек и их настроек.
Пример conanfile.txt:
[requires]
boost/1.71.0
libxml2/2.9.10
libiconv/1.16
snmp_pp/3.3.11
libcurl/7.71.1
log4cplus/1.2.1
libxmldiff/0.2.8
[generators]
cmake
[options]
boost:shared=False
log4cplus:unicode=True
Данный файл содержит 3 основные секции:
- [requires] – отвечает за список необходимых пакетов-библиотек;
- [generators] – отвечает за тип используемого генератора (в нашем случае используется генератор для CMake);
- [options] – секция, отвечающая за определения опций для пакетов. Каждый пакет имеет список опций, которые определяются в рецепте. В данном случае boost:shared=False означает использование статически слинкованной библиотеки, log4cplus:unicode=True означает библиотеку log4cplus с использованием поддержки Unicode.
Команда вызова утилиты Сonan для загрузки пакетов, соответствующих заданному окружению и формированию всех CMake-переменных для использования в вашем CMakeLists.txt.
3. Команда: conan_cmake_run (CONANFILE conanfile.txt BASIC_SETUP CMAKE_TARGETS NO_OUTPUT_DIRS). Если немного подробнее остановиться на параметрах вызова метода conan_cmake_run, то стоит отметить следующее:
- CONANFILE – указывает, что мы используем conanfile.txt со списком пакетов и их настроек;
- conanfile.txt – это путь к файлу со списком пакетов (в нашем случае он находится в корне проекта);
- BASIC_SETUP – указывает на тип использования пакетов в CMake;
- CMAKE_TARGETS – тип использования пакетов, при котором все пакеты из списка conanfile.txt оборачиваются в интерфейсные цели CMake и появляется возможность работать с конструкциями вида
CONAN_PKG::<package>
Пример использования:target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::boost CONAN_PKG::zlib CONAN_PKG::dtl CONAN_PKG::libzip);
- NO_OUTPUT_DIRS – параметр, отвечающий за отключение создания выходных директорий типа «lib», «bin».
В целом Conan – хороший OpenSource-продукт, справляющийся со всеми основными задачами, которые обычно выдвигаются перед решениями данного типа, но…
Ложка дёгтя
При всём удобстве работы с Conan наша команда столкнулась с рядом сложностей. Расскажем подробнее о тех, что доставили больше всего неудобств.
Переключение между наборами пакетов
Наш продукт развивается, мы формируем новые релизы и постоянно работаем над улучшением кода. Это приводит к появлению некоторых условных наборов пакетов для каждого релиза. Так как от релиза к релизу возможны изменения как версионности используемых библиотек, так и настроек их сборки мы формируем для каждого релиза свой conanfile.txt. При переключении между релизами, например, для исправления ошибок и формирования патчей, появляются сложности с подгрузкой необходимых пакетов из Conan. Особенно сильно это проявляется, если поменялись настройки компиляции библиотеки в рецепте. Например, у вас был пакет Example/1.1, вы его использовали в релизе 1, а в релизе 2 вы пересобрали этот пакет, но оставили без изменений версию и не добавили новых опций. В данном случае при переключении на релиз 1 вы подгрузите уже обновлённый пакет Example/1.1. Проблему можно решить двумя способами: изменением версии пакета, что не всегда удобно, так как версия библиотеки в пакете не изменяется, или добавлением опции пакета, которую необходимо будет установить в conanfile.txt в секции “options”.
Использование регистрозависимого названия пакета
Данная проблема актуальна только для применения Conan под ОС Windows. Мы столкнулись с ситуацией, при которой в одном из релизов использовался пакет с названием OpenSSL. Обновив библиотеку, мы выяснили, что теперь пакет называется openssl и предыдущая версия рецепта уже не поддерживается. Решить эту задачу мы смогли при помощи использования переменной среды CONAN_USER_HOME, которая переопределяет директорию с пакетами Conan и позволяет использовать разные настройки и пакеты в собственных директориях.
Пример использования:
if(DEFINED CONAN_USER_HOME)
set(ENV{CONAN_USER_HOME} ${CONAN_USER_HOME})
endif()
Зависимость от очередности подключённых репозиториев пакетов
Представьте, у вас есть свой сервер пакетов. При добавлении его командой <conan remote add …> репозиторий добавляется в конец списка репозиториев (remotes.json). При установке пакетов через <conan install …> поиск необходимого пакета будет проходить в порядке, который задан этим списком. Это неудобно, если вы используете свои кастомные пакеты с общепринятыми названиями. В случае если рецепт пакета с таким названием уже будет находиться на одном из серверов и не будет собран под ваше окружение, то Conan загрузит рецепт, сообщив вам о необходимости сборки пакета под ваше окружение, проигнорировав уже готовый и собранный пакет в вашем репозитории, который находится ниже в списке.
Пример: Вы собрали пакет openssl/1.1.1x с собственными опциями или под своё уникальное окружение и выложили его в свой репозиторий, который находится ниже по списку. При установке этого пакета рецепт его будет найден в официальном репозитории Conan-Center и будет загружен оттуда, что может привести к неожиданному результату.
Решить данную задачу можно при помощи добавления репозитория командой <conan remote add … --insert>. Это не сложно, но об этом нужно постоянно помнить.
Полное обновление пакета при установке
Представим, что есть рецепт и библиотека, на основании которой вы создаёте пакет и проставляете версию (обычно это версия библиотеки). Далее, в своём проекте вы ставите зависимость от данного пакета и работаете с ним. Вся ваша команда при обновлении списка зависимостей автоматически загрузит в локальный кэш этот пакет. В определённый момент вы пересобираете пакет, не меняя при этом версии библиотеки, и отправляете его в репозиторий. Пользователи, которые ранее загрузили этот пакет, никогда не узнают, что он был пересобран (при условии, что не поменялась версия или параметры пакета). Замечание особенно актуально для тех, кто использует пакеты на основе своих библиотек.
Для решения данной проблемы необходимо вручную удалить из локального кэша и заново установить обновлённый пакет. Разработчики Conan.io рекомендуют использовать для таких случаев механизм «ревизий» пакетов, но для нас данный способ не подходит по ряду причин, озвучивать которые в рамках данной статьи не будем.
Вместо заключения
Спасибо за внимание! Надеемся, что наш обзор позволит быстрее и проще начать работать с Conan.io. В данной статье приведены только те особенности, которые показались нам наиболее интересными и с которыми столкнулась команда разработки Efros Config Inspector при переводе проекта на Conan. Если вы используете данный пакетный менеджер и хотите поделиться своим опытом, будем рады комментариям и уточнениям.
Над статьей работали: Денис Морозов, Андрей Параскевопуло, Максим Никитин, Артем Соколовский.