使用glibc和libstdc++进行静态链接

21

我正在编写一款跨平台的应用程序,该程序不兼容GNU GPL许可证。目前我面临的主要问题是该应用程序与glibc和libstdc++动态链接,而几乎每次库的新版本更新都不向后兼容,因此我的应用程序会出现随机崩溃。

为了解决这个问题,我分发已经在几个不同的系统上(使用不同的C/C++运行时版本)编译过的应用程序二进制文件。但我想避免这样做。所以我的问题是,在考虑许可证和其他一切情况的前提下,我能否静态链接glibc和libstdc++?这样做会导致rtld出现问题吗?


1
glibc和libstdc++的维护者在保持向后二进制兼容性方面做了很多工作。主要版本会通过设计来打破它,但这种情况并不经常发生。您可能可以通过在不太现代的系统上构建二进制文件或使用Linux基金会的一些LSB工具(请参见此处;这些工具是免费的;是的,我曾为他们工作,所以我有偏见)来解决问题。 - P Shved
4个回答

20

你不需要这样做。

将你链接程序所需的原始库复制到应用程序文件夹中的一个目录(例如../lib)中。

比如:

my_app_install_path

  1. .bin
  2. lib
  3. documentation

将你的应用程序重命名为类似app.bin的名称。编写一个小的Shell脚本,它将环境变量LD_LIBRARY_PATH设置为库路径(如果有任何前置条件,则将其连接起来)。现在,ld应该能够找到你链接的动态库,而你不需要将它们静态地编译到可执行文件中。

请记住遵守LGPL许可证,将给定的归属信息添加到库中,并在文档中指出源代码可以下载的位置。


@Vitor:我认为这是最好的解决方案!无论如何,我都会将所有第三方依赖项(即zlib、libssh、openssl、yada yada...)作为包的共享库进行分发。我对用户唯一的要求是他们的系统上已安装标准的C/C++运行时。如果你所说的可行,那么我已经有了基础设施:该应用程序基本上是一个服务,因此所有脚本都已经就位! - themoondothshine
1
@themoondothshine,我建议你针对LSB版本进行目标定位。QtCreator就是这样发布的。Google Chrome也是如此。如果我没记错的话,Skipe也是这样的。我认为在Linux上发布闭源软件没有其他方法。 - Vitor Py
@Vitor:谢谢!这解决了我所有的疑问!!我一定会链接到库的LSB版本。 - themoondothshine
@Vitor:能再问你一个问题吗?那么,您将哪些文件与二进制文件一起打包?这是我认为应该采取的方法:使用ldd确定应用程序的依赖项并打包所有列出的文件。这是标准方法,对吧? - themoondothshine
只需要发布不属于您目标的LSB版本的全部内容即可 - 您可以编写一些脚本来解析ldd结果。一些东西永远不应该被发布,比如X11库。使用明确的lsb依赖项打包rpm或deb即可。 - Vitor Py
显示剩余2条评论

9

glibc是LGPL协议下的。根据LGPL 2.1第6节,您可以分发链接到该库的程序,前提是您遵守五个选项中的其中一个。第一个选项是提供库的源代码以及您自己程序的目标代码(源代码是可选的,不是必需的),以便可以重新链接到该库。或者您可以提供同样的书面要约。您自己的代码不必遵循LGPL协议,也不必发布源代码。

libstdc++是在GPL下,但有一个主要例外。您基本上可以选择任意许可证进行分发,而无需为您自己的代码或libstdc ++提供源代码。唯一的条件是正常编译,不得使用专有修改或插件来编译GCC。

我不是律师,如果您需要真正的法律建议,请考虑咨询律师。


5
指定选项-static-libgcc给链接器,如果系统上有可用的C库静态版本,则链接器将链接到该静态版本。否则它会被忽略。

10
你还需要添加 -static-libstdc++,请参考这篇文章进行操作。 - ACyclic
11
这是一个完全错误的答案:“-static-libgcc”与系统C库毫无关系 - Employed Russian
1
@themoondothshine,你应该认真地修复这个答案。正如Employed Russian所指出的那样,libgcc != libc(无论libc == glibc与否)。libgcc是一个运行时库,用于支持编译器生成的代码。在这里阅读有关它的信息:https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html。 - 0xC0000022L
您可以使用objdump -T [二进制文件路径]来查看是否动态加载了libstdc++.so。对于Golang程序员,在导入"C"之前,您可以添加#cgo linux LDFLAGS: -static - bronze man

-1

我必须质疑你对这些可怜的库函数在做什么?

我也有一些跨平台软件。它在各种Linux系统上都能正常运行。使用你想要支持的最旧版本的软件进行构建。glibc和libstdc++库非常向后兼容。

我曾在CentOS 4上构建并在RHEL 6 beta上运行,没有问题。 我可以在稳定的Debian上构建并在测试中运行。

现在,如果我尝试在旧的Debian上构建并在CentOS 5.4上运行,有时候会遇到一些库的问题。这通常是由于不同的发行版配置选择造成的,比如选择线程或非线程。


让我来告诉你到底发生了什么:我曾经在CentOS 3.9上编译我的二进制文件(使用的是旧版本的glibc——2.3.x左右)。现在,在CentOS 5.4上,这个二进制文件开始崩溃,并且核心转储没有任何指向。最终,我去找了CentOS的开发人员,他们惊讶地发现该应用程序在CentOS 5.4上工作了将近一个月而没有出现任何问题。他们建议我使用Fedora的MockBuild系统,但我决定选择在多平台上进行本机编译。因此,与库函数相关的问题并不是很大,主要是由于向后兼容性。 - themoondothshine
1
这不是真的。最近我们有一位客户在运行基于glibc-2.7的系统,导致所有构建在glibc-2.1X上的C++程序无法运行, libstdc++.so.X中缺少一些符号(至少是iostream),此外,CentOS是基于RedHat的,两者都没有提供最新的共享库(不像其他发行版),所以这并不能完全说服我。 - daisy

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