Linux 和 Windows 的第 3 方依赖项的应用程序部署,使用 CMake 和 Conan

Application deployment with 3rd-party dependencies for both Linux and Windows, using CMake and Conan

我正在做一个项目,它同时针对 Windows 和 Linux(并且可能在未来的 MacOS 中)。它由一些具有多个共享库的应用程序组成。它是用现代 C++ 和现代 CMake 编写的。它还使用第 3 方库,如 Qt、OpenCV、Boost、GraphicsMagick、samplerate、sndfile。这些依赖项通过 Conan 包管理器处理。我正在 Linux(Ubuntu 18.04,GCC 8.1)和 Windows(通过 WSL - 还有 Ubuntu 18.04,MinGW-w64 8.1)上构建。我正在使用具有自定义构建选项的相当新版本的 3rd 方库(严格来说 - 与 Ubuntu 的 APT 上可用的版本不同,例如 Qt v5.11.3,或自定义构建的 GraphicsMagick)

我正在使用 CPack。在 Windows 上,我正在构建 NSIS 安装程序,但在 Linux 上,我想使用 DEB 生成器(如果需要,可以使用其他生成器)。我的所有目标(编写的应用程序和共享库)都有适当的 CMake INSTALL 配置,因此它们被正确地复制到生成的安装程序中(基于组件的安装)。真正的问题在于打包 3rd 方依赖项。

问题

严格来说,我不知道如何在 Linux 和 Windows 上使用 CMake+CPack+Conan 做好它。我已经阅读了很多文章和帖子,但我被卡住了。我想要一些东西,它会自动将项目使用的所有第 3 方库与所需的插件捆绑到安装程序中,最重要的是,需要 system/compiler 库(libgomplibstdc++ 等等)。

可能的解决方案

令我惊讶的是,在 Windows 上,此任务相当简单,因为应用程序使用的每个 DLL(我的库、第 3 方库和 system/compiler 库)都需要位于可执行文件的位置是。我通过将所有使用的 DLL 导入 bin 目录来让柯南参与其中。最后,以最简单的打包方式,我只需将 bin 目录复制到安装程序中,它应该可以工作。但是我不确定,这种方法是否可以。

在Linux,事情比较复杂。首先,有一个包管理器。不幸的是,可用的 libraries/compilers 对我来说太旧了(例如,在 APT 上只有 Qt 5.9.6 )并且是使用不同的编译选项构建的。所以,对我来说,唯一的方法是将它们与我的软件一起发布(如 Windows)。通过 ld、RPATH 处理等搜索动态库也存在问题。目前,我看到的唯一解决方案是为我的应用程序编写类似 'launcher' 的内容,它会在程序启动前设置 LD_LIBRARY_PATH 。之后,在这种情况下,我们可以将 binlib 目录复制到 DEB 安装程序,这应该可以工作。但是,我仍然不知道这是否是正确的方法。

其他解决方案

我也研究过其他解决方案。其中之一是来自 CMake 的 BundleUtilities。它对我不起作用。一些库是系统库还是本地库,在识别上有很多问题。尤其是在 WSL 中,它卡在处理对 USER32.dllKERNEL32.dll 的依赖性上。 Windows 中的 BundleUtilities 仅适用于 MSYS,但在 MSYS 中,我无法编译某些第 3 方库(通过 Conan 的 GraphicsMagicks),这就是我使用 WSL 的原因。

总结

我正在为 Windows 和 Linux 寻找使用多个应用程序、库和已发布的第 3 方库打包 C++ 项目的良好且经过验证的方法。你是怎么做到的?您只是将 bin and/or lib 目录复制到安装程序吗?你是怎么做到的(就 CMake/CPack 代码而言)? INSTALL(DIRECTORY ...),或类似的?我不确定,但我认为这个问题在业界应该已经解决了。 ;)

感谢所有建议。

首先,Conan 是用于开发而非分发的包管理器,这就是为什么您没有找到解决问题的简单方法的原因。其次,大部分讨论都是在 Conan issue 进行的,包括错误和问题。在那里你会发现一个非常有帮助的大社区 + Conan 开发者。

with needed system/compiler libraries

这不是柯南的一部分。为什么不对系统库使用静态链接?

谈到 CPack,我们与 Conan 公开讨论了它的用法:https://github.com/conan-io/conan/issues/5655 请加入我们。

我看到你的情况有几个选项:

  • package 方法上,运行 self.copy 和来自 self.cpp_deps 的所有依赖项,其中包括所有库,因此您可以 运行 Cpack
  • 使用 Conan deploy generator to deploy all artifacts, and using a hook 你可以 运行 cpack 或任何其他安装程序工具

外友SSE4正在写一篇关于Deployment + Conan的新博客post,我觉得对你有很大的帮助。您可以阅读预览 here.

此致!