Развертывание приложений со сторонними зависимостями для Linux и Windows с использованием CMake и Conan

Я работаю над проектом, ориентированным как на Windows, так и на Linux (и, возможно, в будущем на MacOS). Он состоит из нескольких приложений с несколькими общими библиотеками. Он написан на современном C++ и современном CMake. Он также использует сторонние библиотеки, такие как Qt, OpenCV, Boost, GraphicsMagick, samplerate, sndfile. Эти зависимости обрабатываются через диспетчер пакетов Conan. Я собираю как на Linux (Ubuntu 18.04, GCC 8.1), так и на Windows (через WSL — также Ubuntu 18.04, MinGW-w64 8.1). Я использую довольно свежие версии сторонних библиотек с настраиваемыми параметрами (строго говоря - версии, отличные от доступных в APT Ubuntu, например, Qt v5.11.3 или пользовательскую сборку GraphicsMagick)

Я использую CPack. В Windows я собираю установщик NSIS, но в Linux я хотел бы использовать генератор DEB (может быть и другой, если нужно). Все мои цели (написанные приложения и общие библиотеки) имеют соответствующие конфигурации CMake INSTALL, поэтому они правильно копируются в сгенерированные установщики (установка на основе компонентов). Настоящая проблема связана с упаковкой сторонних зависимостей.

Проблема

Строго говоря, я понятия не имею, как это сделать хорошо с помощью CMake+CPack+Conan, как в Linux, так и в Windows. Я прочитал много статей и сообщений, но я застрял. Я хотел бы иметь что-то, что автоматически объединяет в установщик все сторонние библиотеки, используемые проектом, с необходимыми плагинами и, что наиболее важно, с необходимыми библиотеками системы/компилятора (libgomp, libstdc++ и т. д.).

Возможное решение

К моему удивлению, в Windows эта задача довольно проста, потому что каждая DLL, используемая приложением (мои библиотеки, сторонние библиотеки и библиотеки системы/компилятора), должна находиться там, где находится исполняемый файл. Я привлекаю к ​​этому Конана, импортируя все используемые библиотеки DLL в каталог bin. В конце концов, самым наивным способом упаковки я просто скопирую каталог bin в установщик, и он должен работать. Но я не уверен, подходит ли этот подход.

В Linux все сложнее. Во-первых, еще нет менеджера пакетов. К сожалению, доступные там библиотеки/компиляторы для меня слишком стары (например, в APT есть только Qt 5.9.6) и построены с использованием разных параметров компиляции. Таким образом, единственный способ для меня — отправить их с моим программным обеспечением (как в Windows). Также есть проблемы с поиском динамических библиотек по ld, обработкой RPATH и так далее. На данный момент единственное решение, которое я вижу, это написать что-то вроде «лаунчера» для моего приложения, которое устанавливает LD_LIBRARY_PATH перед запуском программы. После этого в этом случае мы можем просто скопировать каталог bin или lib в установщик DEB, и это должно сработать. Но все же, я не знаю, правильный ли это подход.

Другие решения

Я также рассмотрел другие решения. Одним из них был BundleUtilities из CMake. Это не работает для меня. У него много проблем с распознаванием, системная какая-то библиотека или локальная. Особенно в WSL, где он застрял в обработке зависимостей от USER32.dll, KERNEL32.dll. BundleUtilities в Windows у меня работало только с MSYS, но в MSYS мне не удалось скомпилировать некоторые сторонние библиотеки (GraphicsMagicks через Conan), поэтому я использую WSL.

Резюме

Я ищу хороший и проверенный метод упаковки проектов C++ с несколькими приложениями, библиотеками и сторонними библиотеками, как для Windows, так и для Linux. Как вы делаете такие вещи? Вы просто копируете каталоги bin и/или lib в установщики? Как (с точки зрения кода CMake/CPack) вы это делаете? INSTALL(DIRECTORY ...) или аналогичный? Я не уверен, но думаю, что эта проблема уже должна быть решена в отрасли. ;)

Спасибо за все предложения.


person akowalew    schedule 18.09.2019    source источник
comment
Для Linux существуют такие вещи, как SnapPak (flatpak.org) и/или AppImages (appimage.org). Может быть, это полезно для того, что вы пытаетесь сделать   -  person Raven    schedule 23.09.2019


Ответы (1)


Во-первых, Conan — это менеджер пакетов для разработки, а не для распространения, поэтому вы не нашли простого способа решить свою проблему. Во-вторых, большинство обсуждений ведется на выпуске Conan, включая ошибки и вопросы. Там вы найдете большое сообщество + разработчики Conan, которые очень полезны.

с необходимыми библиотеками системы/компилятора

Это не часть Конана. Почему вы не используете статическую компоновку для системных библиотек?

Говоря о CPack, у нас есть открытое обсуждение его использования с Conan: https://github.com/conan-io/conan/issues/5655 Пожалуйста, присоединяйтесь к нам.

Я вижу несколько вариантов для вашего случая:

  • на методе package запустите self.copy и все зависимости от self.cpp_deps, которые включают в себя все библиотеки, чтобы вы могли запустить Cpack
  • Используйте генератор развертывания Conan для развертывания всех артефактов, а также хук вы можете запустить cpack или любой другой инструмент установки

Наш друг SSE4 пишет новый пост в блоге о Deployment + Conan, я думаю, он может вам очень помочь. Вы можете прочитать предварительный просмотр здесь.

С Уважением!

person uilianries    schedule 18.09.2019
comment
Спасибо, я проверю это! Согласно библиотекам системы/компилятора: я решил не связывать их статически из-за ненужных накладных расходов. Этот проект состоит из некоторых общих библиотек и некоторых приложений. Все скомпилировано одним и тем же набором компиляторов, даже сторонние библиотеки. С динамической компоновкой, например. libstdc++ все результирующие двоичные файлы немного меньше, и нет дублирования кода. На самом деле, если честно, я не измерял реальный размер накладных расходов на статическое связывание... Я попробую. Ваше предложение также практично с точки зрения безопасности. Спасибо! - person akowalew; 18.09.2019
comment
Я много раз видел, что Конан в основном сосредоточен на разработке, а не на распространении. Но, на мой взгляд, большая часть проектов будет наконец-то распространена! Я действительно не понимаю этого барьера. ;) - person akowalew; 18.09.2019
comment
Нет барьера, но есть фокус. Например, Conan поддерживает множество генераторов, начиная со старого make-файла и заканчивая cmake. Это потребовало больших усилий. Таким образом, добавить эту новую поддержку для развертывания будет большой проблемой, много изменений в коде, много работы и, по нашим отзывам, не большая просьба от большинства пользователей. В любом случае, я знаю, о чем вы говорите, потому что у меня была такая же проблема в прошлом. - person uilianries; 18.09.2019
comment
IIRC libstdc++ составляет ~ 24 МБ (в зависимости от версии, ОС, дистрибутива ...). Если вы хотите предоставить установщики, избегая статической привязки, вам нужно будет предоставить один установщик для дистрибутива (красная шляпа, Centos, Debian, Ubuntu, ...) и арх. Я помню, что когда-то делал скрипт с cmake для Gitlab. Мне нужно было предоставить установщик для Linux, FreeBSD и Windows, это была хорошая задача. - person uilianries; 18.09.2019
comment
Спасибо за ссылку на запись в блоге. Это помогло мне больше всего. Я буду использовать conan-deploy-tool и посмотрю, как создать двоичный файл AppImage. Это выглядит наиболее удобным для меня, и все больше проектов идут по этому пути. - person akowalew; 23.09.2019