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

Fre*_*red 5 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;
}
Run Code Online (Sandbox Code Playgroud)

该应用程序是这样构建的:

g++ -lbz2 -o test.bin main.cpp
Run Code Online (Sandbox Code Playgroud)

我的构建系统在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的Bugzilla数据库显示这种行为不是一个bug,而是一个功能.我真的不需要libbz2.so.1.0,我会满意只是简单地链接libbz2.so.1,但我还没弄清楚如何.

我之前看到过类似的问题,但是接受的答案(你可以在链接器命令行上传递实际的.so文件而不是-l)似乎不起作用.我尝试使用以下命令构建:

g++ /lib/libbz2.so.1 -o test.bin main.cpp
Run Code Online (Sandbox Code Playgroud)

但是,ldd仍然提到应用程序依赖libbz2.so.1.0,即使我将全名传递给g ++.

现在,问题是,是否有一种方法可以让Ubuntu构建应用程序以使其仅依赖libbz2.so.1而不依赖于libbz2.so.1.0

谢谢.

Pee*_*oot 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).


Dir*_*tel 3

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

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

  • 好吧,我应该说得更准确。LGPL 禁止静态链接到专有应用程序。对于寻找完整答案的人来说,如果您想与*某些*库静态链接并与*某些*其他库动态链接,请执行以下操作: g++ -Wl,-Bstatic -lbz2 -Wl,-Bdynamic -lotherlib - o test.bin main.cpp (3认同)