以下是我现在的情况:
我想在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.1
和libbz2.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
?
感谢。
答案 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上部署,使用静态构建可以正常工作。