【问题标题】:Dealing with library dependencies on linux处理linux上的库依赖
【发布时间】:2017-10-12 19:40:36
【问题描述】:

我在我的项目中使用 libcurl,它在运行时依赖于 openssl 和一堆其他 .so。
这种依赖有点让人头疼,因为不同的发行版/版本可能包含不同的 openssl 版本。

例如,如果我在 Ubuntu 9.10 上编译我的应用程序,我会在 Ubuntu 11.10 上运行时遇到问题。

我看到了两个如何解决这个问题的选项,但它们都不足以解决我的问题:

  1. 打包我的应用,让包管理器解决这类问题

  2. 静态链接所有部门

我的应用程序非常小,打包/维护它会有点过头了。另外,要求之一是它应该可以下载和运行。所以,(1) 对我来说不是一个选项。

静态链接 (2) 将是不错的解决方案,但似乎没有 libopenssl、libcrypto 和 libcurl 附带的其他传递依赖项的静态二进制分发。

理论上我可以尝试在 libcurl 后面手动构建所有库库,但这似乎会使维护变得更加复杂。

那么,问题来了——我错过了什么吗?在 linux 世界(具体来说是 Ubuntu)中,有没有一种不那么痛苦的方式来做我想做的事,而且痛苦更少?欢迎提出任何建议。

【问题讨论】:

  • 如果你不使用很多libcurl函数,你可以编写简单的GET,POST调用你自己并手动解析HTTP响应。您将很容易找到有关如何解析此数据的示例代码。
  • 如果您不使用 GUI,我无法想象会有超过三四个库。您提到的两个库:libcurl 和 openssl - 在向后兼容性方面非常好。问:你确定这里真的有问题吗?
  • 如果它是一个小应用程序,它可以用 Python 编写,其中这些库是标准的,版本控制不是问题。
  • 其实我做不到。好吧,至少它不会像看起来那么便宜。问题是这个应用程序是跨平台的,应该能够在 windows/linux/mac 上工作,我需要 libcurl 作为抽象层。另外,我不仅需要纯 HTTP,还需要 HTTPS,这让事情变得有点复杂。
  • Python 和其他需要 vm 的东西不是一个选项。应用程序是跨平台的,强制 Windows 用户安装 vm 是我负担不起的。

标签: c++ linux dependencies openssl libcurl


【解决方案1】:

我在我的项目中使用 libcurl,它依赖于 openssl 和 bundle 其他.so 在运行时。这种依赖有点让人头疼, 因为不同的发行版/版本可能包含不同的 openssl 版本。

例如,如果我在 Ubuntu 11.10 上运行时遇到问题 在 Ubuntu 9.10 上编译我的应用程序。

首先,这有什么问题?如果您从旧版本的 Ubuntu 升级到新版本,您应该不会遇到问题。如果我没记错的话,您只需要指定您需要的库的最低版本,并且包管理器应该能够安装合适的版本。除非您使用已弃用的功能,否则较新版本的库不应破坏现有应用。

我的应用程序非常小,打包/维护它会有点过头了。加, 要求之一是它应该可以下载和运行。 所以,(1) 对我来说不是一个选项。

对于 Linux(尤其是 Ubuntu、Fedora 和其他顶级发行版),打包确实是分发应用程序的方式。下载-安装-运行是 Windows 的事情,它不是 Linux 上的人们安装软件的方式(好吧,Linux 新手可能......)

您还应该尝试接受发行版,这将随着时间的推移减轻您的负担。至少在 Ubuntu 上,实现这一目标的第一步是创建自己的 PPA (https://help.launchpad.net/Packaging/PPA)。

静态链接(2)将是不错的解决方案,但似乎有 没有 libopenssl、libcrypto 和其他的静态二进制发行版 libcurl 附带的传递依赖项。

这通常是一件非常非常不好的事情。静态链接或只是将库与您的应用程序捆绑在一起会使更新它的负担落在您身上,如果您不更新它们,就会产生影响。所以,我不推荐这种方法。更多详情请看这里:http://www.dwheeler.com/blog/2012/04/03/#insecure-libraries

这是 Fedora 的政策:http://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries

那么,问题来了——我错过了什么吗?有没有少 在 linux 世界中做我想做的事的痛苦方式(具体来说是 Ubuntu) 疼痛减轻?欢迎提出任何建议。

这里真的有两件事要做:

  1. 打包:理想情况下,这将是 Ubuntu/Debian 的 deb 和 Fedora/Suse 的 rpm。另一种流行的替代方法是使用自动工具(autoconf/automake),以便用户可以使用所需的先决条件构建您的应用程序。最后一个选项是只提供一个 Makefile 和一个 README 并期望您的用户做正确的事情。
  2. 发行版:理想情况下,这是与发行版存储库一起使用的。 Ubuntu PPA 是一个很好的起点。另一种方法是在您自己的网站上托管二进制文件/包。

大多数流行的应用程序都为流行的 Linux 发行版提供 .deb/.rpm 以及带有自动工具的 .tar.gz,以便在具有不同打包系统的发行版上构建。

最后,让我问你这个问题:你的重点是让你提供你的应用程序变得不那么痛苦,还是让你的用户获得你的应用程序变得不那么痛苦?

【讨论】:

  • 感谢您的大力支持。关于 libcurl 和 Ubuntu 版本:这是因为我尝试仅与 libcurl 静态链接(而不是传递 deps)。结果:其中一些 dep 不存在于静态链接 libcurl 想要的版本中。
  • 关于静态构建:是的,我已经深入挖掘了一点,现在我看到这是适合 Windows 的东西,但不是我应该在 linux 上遵循的方式。我现在正在研究如何在我的工具链中打包 deb 包,所以这很有可能成为我的最终解决方案。
  • 关于最后一个问题:实际上 - 我正在寻找妥协。这个工具很有可能每个世纪更新一次,所以其他开发者(也许不是我)支持这个应该尽可能容易。另一方面 - 这个工具应该尽可能简单和轻便,所以用户体验也很重要(我可能会更喜欢软件包,但我还没有看到很多非开发 Linux 用户在野外,这就是为什么我对包装有疑问)。
【解决方案2】:

还有第三种选择:

根据平台创建适合您需要的某种存档并包含您需要的 .so/.dll 文件。 ZIP 存档应该适用于 Linux 和 Windows。

然后在您的 Linux 安装的包装脚本中使用 LD_LIBRARY_PATH(它允许您将 .so 文件放在某个特殊的位置,通常在 libs 目录中)。据我所知,Windows 使用 CWD 作为查找二进制文件所需的 .dll 文件的第一个位置,因此您只需将它们放在与二进制文件相同的目录中即可。

使用这种方法,你可以保持你的“分布”很小,并且不需要静态链接或任何其他特殊处理。

只需确保分析 .so/.dll 文件的实际依赖链,以免在目标环境中加载某些意外库时感到惊讶。

【讨论】:

  • windows 的包装批处理文件也可以工作,它需要这样的东西:pastebin.com/eqfgNUwa
  • 嗯。是的,这似乎是一个选择。但是,看起来有点脆弱,仍然需要一些努力。我仍然有疑问,但我想我会尝试进行静态构建,如果事情变得糟糕,我会回退到这个。谢谢。
【解决方案3】:

你考虑过使用 qt 吗?你根本就不会有这些问题,而且它们对 ssl 和 http 有强大的 rmeasy 支持

【讨论】:

  • 是的,我已经考虑过了,但它会使应用程序比我负担得起的重得多。 Qt 只为 QtCore 添加了约 50mb,不知道为 QtNetwork 增加了多少。更不用说由于他们的许可政策,我无法将所有内容静态链接到一个胖 exe 中。
  • 那不是真的。您可以在一个 exe 中链接。此外,您不需要部署 dll,包管理器可以为您处理。如果需要,dll 也可以更小。如果需要,我可以为您提供静态构建 qt 或构建小型、可用的 qt 库的帮助
  • 另外,似乎没有开箱即用的 HTTPS 支持。至少一目了然。
  • 据我所知,这应该与 open ssl 结合使用。
  • 好吧,我在物理上确实可以与 Qt 静态链接,但是......如果我想抱怨他们的许可证(我确实这样做了),这将花费我一些钱,而且没有适用于 windows 的包管理器,加上包管理器不是我在问题帖子中提到的选项。
【解决方案4】:

所以你问“有没有一种不那么痛苦的方法。”我喜欢其他答案,尤其是 Naveen 的答案。所以你有两个解决方案

  1. 在操作系统中使用 .so 文件(共享库)并向您的用户推荐他们使用“至少版本 x”。这几乎可以解决所有问题。

  2. 将非共享(静态)库(.a 文件)与您的应用程序捆绑在一起,或者将共享库(.so 文件)与您的应用程序捆绑在一起。

使用 ./configure 脚本从源代码构建静态 .a 文件非常简单。您可以轻松获得 .so 文件,但您需要相当技巧才能将它们与您的应用程序捆绑在一起。 .so 文件可以打补丁;他们里面有路径,说明应该从哪里加载依赖项。因此,捆绑 .so 文件并非不可能,甚至可能是避免为一系列依赖项构建 .a 文件的手动步骤的简便方法——如果您找到并使用脚本来重新定位 .so 文件。

你写:

理论上我可以尝试在 libcurl 后面手动构建所有库库,但这似乎会使维护变得更加复杂。

是的,它会的,因为您会想要安全补丁,对吧?所以最好的方法是#1——让用户安装他可以得到的最新版本,并负责确保他的系统安全。

当您遇到为无法使用解决方案 1 的客户进行定制工作的情况时,解决方案 2 很方便。在这里,您按计划提供软件的定期版本,包括最新的依赖项及其所有修复。小型软件通常会达到不再需要更改的程度。对于一小部分软件来说,这个解决方案不是一个好的解决方案,因为你的软件没有改变,但你仍然在定期发布,只是因为依赖项有更新。因此,除非您的客户确实需要,否则不要使用此解决方案。从长远来看,它会更贵。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 2015-06-27
    • 2011-09-03
    • 2023-03-31
    • 2019-04-09
    • 2018-08-03
    • 2011-07-26
    相关资源
    最近更新 更多