首先,我发现了这个类似的问题如何制作一个便携式 Linux 应用程序?但它并没有真正解决我的问题,更多的是关于如何编译以使应用程序可移植,我已经知道如何去做(至少我认为我知道),而不是关于部署,正如我将在下面解释的那样。
这就是我的情况。我们受雇为客户解决某个问题,因此我们将开发一个闭源应用程序,并打算将其出售给他们。然而,我们还没有得到任何关于它应该能够在哪里运行的细节,我的意思是什么发行版、内核版本或任何真正的东西。该任务相当简单,不依赖于任何低级驱动程序或任何使其可移植性变得复杂的东西。然而,我们确实依赖于几个第三方库,以下是依赖项的简单方案:
app --+-- libA
| +-- lib1
+-- libB --+-- lib2
+-- lib3
其中 libA、B 和 lib1、2、3 都是具有合适许可证(LGPL、ASL 和 BSD)的开源项目。编译后,我们程序的共享依赖项变成了libA、libB、lib1、lib2、lib3和一堆系统库,例如libc、libm、libz、libstdc++、libpthread等。一切都是动态链接的。
现在,由于我们没有目标发行版,我们希望使其独立于任何打包系统(如 .deb 等)。直接依赖项(libA 和 libB)并不常见,因此显而易见的选择是将它们与我们的应用程序一起提供。 lib1,2,3 实际上更常见(即其中之一是 libpng),尽管仍然不确定它们是否会安装在目标系统中。我们决定将它们全部包含在最终的软件包中。
我们不知道如何处理系统库。我们应该如何处理这个问题?我们是否只是假设他们将拥有正确的图书馆并祈祷最好的结果?在这种情况下,当其中一个库发生变化并且我们的应用程序停止工作时,一两年后会发生什么?
我们是否应该将所有这些(libstdc++、glibc 等)与我们的软件一起分发?这感觉不对,我认为这可能违反了其中的许可条款。我知道我过去使用过一些程序,它们实际上携带了[至少]其中一些库的自己的副本,它实际上引起了我的注意,因为它是比我系统中的版本旧的版本,并且交换它们使一切都停止了工作(我偶然发现的)。
通常如何处理这种情况?
答案1
在 Linux 上实现可移植二进制可执行文件的严格正确方法是反对Linux 标准库和它的详细规格。 LSB 旨在通过指定特定的库版本(或与这些版本的兼容性)来产生跨兼容发行版的二进制兼容性。 LSB(或至少是过去的版本)被形式化为ISO/IEC 23360。如果您构建的程序仅链接到 LSB 库(及其本身附带的库),那么它将在所有这些系统之间进行移植。
LSB 指定了软件包的 RPM 格式,因此您只需要生成一个(严格地)。如果您放弃与包管理器的集成,一个 tarball 也足够了。
关于您的一些具体观点:
我们是否只是假设他们会有正确的图书馆并祈祷得到最好的结果?
一个相当简单的 LSB 兼容程序可能会按原样在许多系统上运行,所以您可以这样做。
除此之外,一些发行版尝试提供 LSB 合规性,包括 RHEL 和 SUSE。其他一些人通过特定的包来提供它,该包会引入适当的依赖项。例如,Debian 有一套lsb
它会引入lsb-core
其他几个,进而引入适当的依赖项。目标系统可能需要安装这样的软件包才能运行您的软件。
LSB 不再像以前那样流行,而且许多系统的正式兼容性也有所减弱,但实际上它可以在相当广泛的范围内移植运行。即使一些确实渴望合规性的系统也会错过一些更模糊的点,但对于常见的目的来说,这通常并不重要(并且相同的程序可能会在以下系统上运行)不尝试符合LSB)。
在这种情况下,当其中一个库发生变化并且我们的应用程序停止工作时,一两年后会发生什么?
当您的应用程序停止工作时,您的应用程序将停止工作。这是一个业务流程问题。
我们是否应该将所有这些(libstdc++、glibc 等)与我们的软件一起分发?
可能不会。特别是对于 libc,在系统上同时使用多个版本时可能会出现运行时兼容性问题。然而,还有其他 libc 实现可能更适合捆绑。
虽然大多数库都可以成功捆绑,但供应库通常是一个维护和安全问题,因此我建议尽可能避免这样做。如果在库中发现错误或安全缺陷,则在系统上的一个位置更新它(发行版将解决该问题)比跟踪每个副本(并从您那里获取替换包!)更容易、更可靠。
作为更实际的步骤,也许可以询问您的客户希望它在哪里运行。你可能过于热情了。
答案2
在实践中你需要做一些适用于最常见的 Linux 发行版(和版本)的二进制包(例如,.deb
对于 Debian 和 Ubuntu、 Fedora)。.rpm
显然,您需要为 Fedora 和 Ubuntu 制作不同的软件包,并且可能需要为 Debian Jessie 和 Ubuntu 16.04 制作不同的软件包。然而,有时Ubuntu 的软件包可能会安装在某些(特定的)Debian 上,反之亦然。
然而,我们还没有得到任何关于它应该能够在哪里运行的具体信息,我的意思是哪个发行版、内核版本或其他任何东西。
您需要与您的客户讨论。
在这种情况下,当其中一个库发生变化并且我们的应用程序停止工作时,一两年后会发生什么?
您需要构建并发布二进制包的更新变体,并且您将为此花费精力(和金钱)。
您可能想要静态链接(如果技术上和法律上可行)某些库(请记住 LGPL 许可证建议动态链接,或者能够在客户端计算机上静态重新链接)。例如,libstdc++
对版本比对版本更敏感,libc
因此您可以静态libstdc++
和动态链接libc
。事实上YMMV。
请注意,有一些给定系统库的版本在实践中可能工作也可能不工作。有些库以特定的方式使用系统资源,因此细节非常重要。
附言。也许您应该与您的客户进行更多讨论并提出制作免费软件(开源)。有些客户可能更喜欢这样。