如何在现有的libstdc ++中使用替换glibc?

时间:2013-12-12 03:21:41

标签: linux gcc shared-libraries glibc libstdc++

我需要使用glibc(2.18)的自编译版本,比系统上的默认版本(2.15)更新。我可以编译和链接一个C ++程序,但是当我尝试运行它时,我收到有关libstdc++.so.6的错误。 (C程序似乎工作得很好。)我是否需要针对较新的gcc重新编译glibc才能使其正常工作?为什么? (更新:我想出了这一部分,但我在底部还有一些其他问题。)

以下是C ++程序示例:

#include <iostream>
int main()
{
    std::cout << "ok\n";
    return 0;
}

关注this answer,我用以下代码编译:

g++ -Wl,--rpath=/path/to/glibc-2.18/lib -Wl,--dynamic-linker=/path/to/glibc-2.18/lib/ld-2.18.so a.cpp

它编译时没有错误,然后ldd说:

$ ldd a.out 
    linux-vdso.so.1 =>  (0x00007fff421fe000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f3b96e7f000)
    libc.so.6 => /path/to/glibc-2.18/lib/libc.so.6 (0x00007f3b96ad1000)
    libm.so.6 => /path/to/glibc-2.18/lib/libm.so.6 (0x00007f3b967cf000)
    /path/to/glibc-2.18/lib/ld-2.18.so => /lib64/ld-linux-x86-64.so.2 (0x00007f3b9719d000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3b965b9000)

但是当我尝试运行它时:

$ ./a.out 
./a.out: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

这很令人困惑,因为看起来ldd找到libstdc++.so.6就好了(具体版本为libstdc++.so.6.0.16)。

更新:问题似乎(不确定)新的2.18动态链接器正在使用自己的库路径,该路径仅包含/path/to/glibc-2.18/lib的子文件夹。我通过添加此新路径,然后是标准路径(/lib', '/usr/lib等)到/path/to/glibc-2.18/etc/ld.so.conf并运行/path/to/glibc-2.18/sbin/ldconfig来运行程序。更多问题:

  1. 我是否绝对需要新的2.18动态链接器来运行glibc-2.18的程序?标准链接器不能这样做吗? (这样可以避免我必须设置并不断更新2.18动态链接器的路径。)

  2. 如果我使用2.18动态链接器编译但没有--rpath,则该程序不起作用。为什么呢?

  3. 我是否应该在编译命令中使用-L/path/to/glibc-2.18/lib(除--rpath--dynamic-linker之外)?

1 个答案:

答案 0 :(得分:2)

  

我是否绝对需要新的2.18动态链接器来运行glibc-2.18程序?

是的(好吧,差不多。见脚注)。

  

这将避免我必须设置并不断更新2.18动态链接器的路径。

一种常见的技术是创建一个g++ shell包装器,例如g++glibc2.18,并封装在那里添加必要的链接参数。然后一个简单的make CXX=g++glibc2.18会做正确的事。

  

标准链接器不能这样做吗?

没有。有关说明,请参阅this answer

  

如果我使用2.18动态链接器编译但没有--rpath,则该程序不起作用。为什么呢?

看到相同的答案。

  

我是否应该在编译命令中使用-L / path / to / glibc-2.18 / lib(除了--rpath和--dynamic-linker)?

是,如果要使用glibc-2.18中存在但系统库中不存在的符号。否则,没有。

脚注:

作为替代方案,您可以在没有特殊标志的情况下构建程序,然后使用“显式加载程序调用”来实际运行它:/path/to/glibc-2.18/lib/ld-2.18.so /path/to/a.out

注意:这并不总是有效:如果程序喜欢重新exec本身(以及其他罕见情况下)。在以这种方式调用它时,您可能也无法调试它。