Я работаю над проектом, ориентированным как на 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 ...)
или аналогичный? Я не уверен, но думаю, что эта проблема уже должна быть решена в отрасли. ;)
Спасибо за все предложения.