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 在这方面有一些错误,我不会感到惊讶。
我在从前者升级到后者时遇到了 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 在这方面有一些错误,我不会感到惊讶。