【问题标题】:Linking Statically with glibc and libstdc++使用 glibc 和 libstdc++ 静态链接
【发布时间】:2010-07-09 15:36:08
【问题描述】:

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

作为一种解决方法,我分发在几个不同系统上编译的应用程序的二进制文件(具有不同的 C/C++ 运行时版本)。但我不想这样做。所以我的问题是,牢记许可和一切,我可以静态链接 glibc 和 libstdc++ 吗?另外,这会导致 rtld 出现问题吗?

【问题讨论】:

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

标签: c++ linux gcc


【解决方案1】:

你不需要。

将链接到的原始库复制到应用程序文件夹中的目录(本例中为../lib)。

喜欢:

my_app_install_path

  1. .bin
  2. 文档

将您的应用重命名为 app.bin 之类的名称。将您的应用程序替换为一个将环境变量 LD_LIBRARY_PATH 设置为库路径的小 shell 脚本(并连接以前的 LD_LIBRARY_PATH 内容,如果有的话)。现在 ld 应该能够找到您链接的动态库,并且您不需要将它们静态编译为可执行文件。

记住要遵守 LGPL,将给定的属性添加到库中并指向可以下载源代码的文档。

【讨论】:

  • @Vitor:我认为这是最好的解决方案!无论如何,我将所有第三方依赖项(即 zlib、libssh、openssl、yada yada ...)作为共享库与包一起分发。我对用户的唯一要求是他们的系统上安装了标准的 C/C++ 运行时。如果你说的有效,我已经有了基础设施:应用程序基本上是一个服务,所以所有的脚本都已经到位了!!
  • @Vitor:我还有一个问题:新版本的 RTLD 是否能够动态加载所有库,即使它们是在非常旧的系统上编译的?也就是说,如果我将 libstdc++ 和 glibc 与我的应用一起提供,我就不必担心 ld 会导致运行时问题,对吧?
  • @themoondothshine 从来没有遇到过 ld 无法加载所有库的问题。在过去的 3 年里,我一直在这样做,以在 Linux 上发布一个闭源 GIS 包。
  • @themoondothshine 另外,我建议您针对 LSB 版本。 QtCreator 以这种方式发布。谷歌浏览器也是如此。如果我没记错的话,Skipe 也是。我认为在 Linux 上发布封闭源代码没有其他方法。
  • @Vitor:谢谢!解决了我所有的疑惑!!肯定会链接到库的 LSB 版本。
【解决方案2】:

glibc 在 LGPL 下。在LGPL 2.1 的第 6 节下,您可以分发链接到库的程序,前提是您符合五个选项之一。首先是提供库的源代码,以及您自己程序的目标代码(源是可选的,不是必需的),以便它可以与库重新链接。您也可以提供相同的书面报价。您自己的代码不必在 LGPL 下,也不必发布源代码。

libstdc++ 在 GPL 下,但带有 major exception。您基本上可以根据您选择的许可证进行分发,而无需提供您自己的代码或 libstdc++ 的源代码。唯一的条件是你可以正常编译,没有例如GCC 的专有修改或插件。

IANAL,如果您需要真正的法律建议,您应该考虑咨询一位。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 你还需要-static-libstdc++,见explanation
    • 这是一个完全虚假的答案:-static-libgcc 与系统 C 库无关
    • @themoondothshine 你应该认真修复这个答案。正如受雇的俄罗斯人libgcc != libc 所指出的那样(无论是否说libc == glibc)。 libgcc 是一个支持编译器生成代码的运行时库。阅读它here
    • 您可以使用objdump -T [binary path] 来查看它是否动态加载libstdc++.so。对于golang程序员,你可以在import "C"之前添加#cgo linux LDFLAGS: -static
    【解决方案4】:

    我必须质疑你对糟糕的库函数做了什么?

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

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

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

    【讨论】:

    • 让我告诉你到底发生了什么:我曾经在 CentOS 3.9 上编译我的二进制文件(使用旧版本的 glibc -- 2.3.something)。现在,这个二进制文件在 CentOS 5.4 上开始崩溃,核心转储没有指向任何地方。我终于找到了 CentOS 的开发人员,他们对这个应用程序在 CentOS 5.4 上运行了将近一个月而没有发生任何事故感到惊讶。他们建议我使用 Fedora 的 MockBuild 系统,但我决定在多个平台上进行本地编译。所以我对库函数所做的并不是向后兼容的问题。
    • 这不是真的。最近我们有一个客户在运行基于 glibc-2.7 的系统,导致所有针对 glibc-2.1X 构建的 C++ 程序都无法运行,libstdc++.so.X 中缺少一些符号(至少 iostream),此外 CentOS 是基于 RedHat 的,并且两者都发货没有那么最新的共享库(不像其他发行版),所以它并不能说服我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多