将应用程序链接到libbz2.so.1而不是libbz2.so.1.0

时间:2009-12-02 20:14:05

标签: c++ c linux g++

以下是我现在的情况:

我想在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

感谢。

2 个答案:

答案 0 :(得分:5)

这里有一些背景来解释所链接的内容。在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 blah

你有链接到libblah的可能性,但因为它的二进制文件中的SONAME很重要,你的依赖仍然是这个libbz2.so.1

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

除了-static技巧(它可以以有趣的方式破坏事物)之外,没有简单的方法可以摆脱混乱(理想情况下,库可以像glibc一样进行很好的符号版本控制,从不或很少改变它的SONAME)。

答案 1 :(得分:3)

为什么不直接链接?

我过去已经在Ubuntu上构建并在RHEL上部署,使用静态构建可以正常工作。