代码之家  ›  专栏  ›  技术社区  ›  Fred

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

  •  5
  • Fred  · 技术社区  · 15 年前

    我现在的处境是:

    我想在Linux上发布一个可以在几个发行版上运行的二进制应用程序(不是所有发行版,只是目前的主要发行版很重要,为了讨论这个问题,让我们集中讨论Ubuntu和Fedora)。有问题的应用程序链接到 libbz2 它的一些工作。一个简单的“你好世界”将说明这种情况:

    /* 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 . 只有费多拉 libbz2.so.1 libbz2.so.1.0.4 ,但不是 LBBZ2,SO 1 .

    Red Hat's Bugzilla database 显示此行为不是错误,而是功能。我真的不需要 LBBZ2,SO 1 我会很满意仅仅连接到 LBBZ2,SO 1 但是我还没弄清楚怎么做。

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

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

    然而,ldd仍然提到应用程序依赖于 LBBZ2,SO 1 即使我把全名传给了G++。

    现在,问题是,在Ubuntu上有没有一种方法来构建应用程序,使它只依赖于 LBBZ2,SO 1 而不是 LBBZ2,SO 1 ?

    谢谢。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Dirk is no longer here    15 年前

    为什么不静态链接呢?

    我以前在Ubuntu上的构建和Rhel上的部署中都做过这样的工作,使用静态构建也很好。

        2
  •  5
  •   Peeter Joot    15 年前

    这里有一些背景来解释链接的内容。在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联系在一起的感觉,但是因为它的奏鸣曲在二进制中很重要,你的依赖仍然是libbz2.so.1。

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

    除了静态的诡计(可以用有趣的方式破坏事物),没有一个简单的方法可以摆脱混乱(理想情况下,库可以像glibc那样进行很好的符号版本控制,并且从不或很少更改其奏鸣曲)。