【问题标题】:Linking an application to libbz2.so.1 rather than libbz2.so.1.0将应用程序链接到 libbz2.so.1 而不是 libbz2.so.1.0
【发布时间】:2009-12-02 20:14:05
【问题描述】:

这是我目前的情况:

我想在 Linux 上分发一个可以在多个发行版上运行的二进制应用程序(不是所有发行版,目前只是主要的问题,为了便于讨论,让我们关注 Ubuntu 和 Fedora)。有问题的应用程序链接到libbz2 以进行某些工作。一个简单的“Hello World”将说明情况:

/* main.cpp */
#include <iostream>

int main(int argc, char* argv[])
{
  std::cout << "Hello World!\n";
  return 0;
}

应用程序是这样构建的:

g++ -lbz2 -o test.bin main.cpp

我的构建系统在 Ubuntu 上。当我对生成的二进制文件执行 ldd 检查时,它会将 libbz2.so.1.0 列为运行时依赖项。当我将此应用程序带到 Fedora 机器上时,该应用程序无法运行,并且 ldd 显示它找不到 libbz2.so.1.0。 Fedora 只有libbz2.so.1libbz2.so.1.0.4,但没有libbz2.so.1.0

Red Hat's Bugzilla database 表明这种行为不是错误,而是一个特性。我真的不需要libbz2.so.1.0,只要链接到libbz2.so.1 我就会很满意,但我还没有弄清楚如何。

我见过similar question asked here previously,但接受的答案(您可以在链接器命令行上传递实际的 .so 文件而不是 -l)似乎不起作用。我尝试使用以下命令进行构建:

g++ /lib/libbz2.so.1 -o test.bin main.cpp

但是,ldd 仍然提到该应用程序依赖于libbz2.so.1.0,尽管我将全名传递给了 g++。

现在的问题是,在 Ubuntu 上是否有办法构建应用程序以使其仅依赖于 libbz2.so.1 而不是 libbz2.so.1.0

谢谢。

【问题讨论】:

    标签: c++ c linux g++


    【解决方案1】:

    这里有一些背景知识来解释链接的内容。在 ELF 平台上,您传递的 -L 和 -l 标志仅在链接时定位二进制文​​件。如果链接器链接器确定需要一个库,它会在该二进制文件中生成对 SONAME 的引用,而不管它被调用什么。例如:

    $ objdump -p /lib64/libbz2.so.1 | grep SONAME SONAME libbz2.so.1

    因此,无论 libbz2 被命名为什么,它都会显示为依赖项。再举一个例子,做一些完全被击垮的事情:

    $ ln -s /lib64/libbz2.so.1 libblah.so $ g++ t.C -L。 -l 废话

    您显然已经链接到 libblah,但因为它在该二进制文件中的 SONAME 很重要,您的依赖项仍然是这个 libbz2.so.1

    $ ldd a.out | grep bz2 libbz2.so.1 => /lib64/libbz2.so.1 (0x00002b3d1a000000)

    除了 -static 诡计(它可以以有趣的方式破坏事物)之外,没有简单的方法可以摆脱混乱(理想情况下,该库会像 glibc 那样进行良好的符号版本控制,并且从不或很少更改其 SONAME)。

    【讨论】:

    • 用 cp /lib64/libbz2.so.1 libblah.so 代替 ln 甚至可以成为一个更强大的例子(如果有人认为 ld 以某种方式将名称追溯到 libbz2.so.1
    【解决方案2】:

    为什么不直接静态链接呢?

    我过去曾在 Ubuntu 上构建并在 RHEL 上进行部署,使用静态构建效果很好。

    【讨论】:

    • facepalm ...因为那太明显了。出于某种原因,我理所当然地认为 bzip2 将获得许可 LGPL,它禁止静态链接,但它似乎是 BSD,它允许它......然后是静态链接。谢谢。
    • 没有汗水。但是为什么你认为 LGPL 对你的链接方式有什么要说的呢?您可以使用带有 LGPL 和 GPL 代码的静态或动态链接——您的限制是您如何分发您的应用程序等,以及您是否必须提供源代码。这完全独立于您的构建过程。
    • 好吧,我应该更准确些。 LGPL 禁止静态链接到专有应用程序。至于寻找完整答案的人,如果您想与 some 库静态链接并与 some 其他库动态链接,请按以下步骤操作:g++ -Wl,-Bstatic -lbz2 -Wl,-Bdynamic -lotherlib -o test.bin main.cpp
    猜你喜欢
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2018-08-21
    相关资源
    最近更新 更多