如何完全静态构建应用程序并包含所有依赖项(如libgcc等)?

7
我目前正在尝试将我所有应用程序的依赖项编译为静态库。我的动机如下:
  1. 不依赖于任何操作系统提供的库,以获得完全可重现的代码库
  2. 避免由动态链接引起的在其他系统上部署时的问题
  3. 避免在链接不同版本的库时发生运行时冲突
  4. 能够交叉编译到其他操作系统
然而,正如我最初所担心的那样,我很快就陷入了困境。我目前卡在了OpenCV上,我相信还会有更多问题。然而,我的主要问题是:
  1. 是否可能构建完全静态构建的应用程序(例如libc、ligcc等)?
  2. 是否可能将所有库静态链接,但将主要组件(libgcc等)动态链接?
  3. 如果不行,是否可能链接静态构建的库(例如OpenCV),但通过动态链接(zlib、libc等)满足其依赖关系?
  4. 我在互联网上进行了研究,但找不到涵盖链接内部的全面指南(静态链接 vs. 动态链接)。您知道好书/教程吗?gcc的书籍能否让我更进一步?
  5. 这是一个非常愚蠢的想法吗?

1
  1. 是的;3. 您需要将所有依赖项构建为静态库,静态链接C++运行时,并确保您的应用程序调用的系统API具有合理的可移植性;4. 是的(除非您可以接受处理0.5GB的可执行文件),但您始终可以说“这就是谷歌在Go语言中所做的”。
- user7860670
1
您必须注意许可证问题:虽然库可能授权动态链接,但静态链接可能会“污染”您的代码。 - OznOg
@VTT 谢谢,我添加了另一个问题是否可能将所有库静态链接,但动态链接主要组件(libgcc等)?这样做可以保持应用程序大小合理吗? - user823255
1个回答

5
我的动机如下:
1. 不依赖于任何操作系统提供的库,以便拥有完全可重复的代码库。 2. 避免由动态链接引起的在其他系统上部署时出现问题。 3. 避免与不同版本的库链接时发生运行时冲突。 4. 能够为其他操作系统进行交叉编译。
你的动机是完全错误的。
对于第一点,你不需要一个完全静态的二进制文件。只需使用GNU链接器提供的--sysroot设施针对一组版本控制的库进行链接即可。
对于第二点,你的动机是误导性的。
在Linux上,如果目标系统上安装的libc与程序构建时使用的(静态)libc不同,则完全静态的二进制文件可能会以神秘的方式崩溃。也就是说,在Linux上,与动态链接相比,完全静态的二进制文件实际上更不具备可移植性。在Linux上,应该永远不要静态链接libc.a。
这一点单独就应该让你放弃这种方法(至少对于任何基于GLIBC的系统)。
对于第三点,在程序构建时不要链接不同版本的库,就不会出现冲突。
对于第四点,与第一点相同的解决方案就可以解决问题。

太棒了,谢谢。我想第一种方法是我应该仔细研究的。 - user823255
1
你能提供更多细节说明为什么不同版本的libc(静态与系统)会导致崩溃吗?它们之间的交互是什么?谢谢。 - benathon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接