我需要使用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
来运行程序。更多问题:
我是否绝对需要新的2.18
动态链接器来运行glibc-2.18
的程序?标准链接器不能这样做吗? (这样可以避免我必须设置并不断更新2.18
动态链接器的路径。)
如果我使用2.18
动态链接器编译但没有--rpath
,则该程序不起作用。为什么呢?
我是否应该在编译命令中使用-L/path/to/glibc-2.18/lib
(除--rpath
和--dynamic-linker
之外)?
答案 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
本身(以及其他罕见情况下)。在以这种方式调用它时,您可能也无法调试它。