G++ 4.9.2 和 8.2.0 - 最终二进制文件与默认 lib 路径搜索 ./../lib 目录的依赖关系(隐式 RPATH 问题)

G++ 4.9.2 and 8.2.0 - final binary's dependency with default lib path searching ./../lib directory (implicit RPATH issue)

我在从前者升级到后者时遇到了 4.9.2 G++ 和 Linux 上的 8.2.0 G++ 生成的二进制文件之间的奇怪差异。我能够将其缩小到下面最小化的片段

//main.cpp
int main(){}
//emptylib.cpp
#!/bin/sh
#to build and verify output
rm -rf bin lib *.o

gcc_bin=/path/to/gcc_4.9.2/bin
#gcc_bin=/path/to/gcc_8.2.0/bin

${gcc_bin}/g++ -B${gcc_bin} -c main.cpp
${gcc_bin}/g++ -B${gcc_bin} -c emptylib.cpp
${gcc_bin}/g++ -B${gcc_bin} -shared emptylib.o -o libemptylib.so
${gcc_bin}/g++ -B${gcc_bin} main.o -o main -L. -lemptylib

mkdir bin
mkdir lib
mv libemptylib.so lib/
mv main bin/

ldd bin/main

结果有点 st运行ge,因为我没有提供 -rpath=../lib,但都是一样的,我最终得到的是 4.9.2 编译器驱动程序(在ldd):

libemptylib.so => /path/to/bin/../lib/libemptylib.so

和 8.2.0

libemptylib.so => not found

如我所料,库没有解析。我还没有看到任何暗示在任何版本中搜索 ../lib 的文档,但我不希望这是任何版本的行为。这是 4.9.2 或更早版本中的错误,还是一开始就不应该发生的事情?

附带说明一下,8.2.0 和 4.9.2 在其 bin 目录中没有 ld(尽管我将 -B 放在代码片段中),所以两个编译器驱动程序都使用 /usr/bin/ld(我已经验证了很多)并单独根据编译器驱动程序产生不同的结果。

更新:

根据要求,我在两个二进制文件上 运行 readelf -d bin/main,我确实收到了不同的 rpath 输出。 GCC 4.9.2 给了我:

0x000000000000000f (RPATH)    Library rpath: [$ORIGIN:$ORIGIN/../lib64:$ORIGIN/../lib:/path/to/gcc_libs/lib64:/path/to/gcc_libs/lib:/path/to/gcc_4.9.2/lib64:/path/to/gcc_4.9.2/lib]

8.2.0 没有那个

0x0000000000000001 (NEEDED)   Shared Library: [libemptylib.so]

所以我想我对发生的事情有了答案。那么它是如何在 4.9.2 中出现在我的二进制文件中的,为什么它在两个版本之间发生了变化,而现在在 8.2.0 中却没有?

I did receive different output for rpath. rpath: [$ORIGIN:$ORIGIN/../lib64:$ORIGIN/../lib:/path/to/gcc_libs/lib64:/path/to/gcc_libs/lib:/path/to/gcc_4.9.2/lib64:/path/to/gcc_4.9.2/lib]

所以区别在于 GCC 4.9.2 与 8.2.0 的配置方式。

我猜 8.2 来自您的发行版(或者至少配置了默认安装路径),而 4.9 配置为安装到 /path/to/gcc_4.9.2

这解释了为什么 4.9 为 64 位版本添加 -rpath/path/to/gcc_4.9.2/lib64。但是,它没有解释 /path/to/gcc_4.9.2/lib$ORIGIN(后者不应该是 64 位构建的一部分)的来源。

配置 GCC 使其 准确地 放置必要的东西,不多也不少,这有点黑魔法。如果 4.9 在这方面有一些错误,我不会感到惊讶。