背景及解释
在编译 pytorch 时,注意到参数 -Wl,–no-as-needed,便查询这两个指令的具体意义:
--as-needed
Only set DT_NEEDED for shared libraries if used.
--no-as-needed
Always set DT_NEEDED for shared libraries.
可以看出,
- –as-needed,只有在使用到动态库的符号时,才将动态库打上 DT_NEEDED 的标签。
- –no-as-needed,只要在命令行中链接,就将动态库打上 DT_NEEDED 的标签,用于在编译时不需要,但是在执行时需要的情况。
示例
使用到动态库符号
// main.cpp
#include <stdio.h>
extern int add(int, int);
int main()
{
int a = 1, b = 2;
printf("%d\n", add(a, b));
return 0;
}
// helper.cpp
int add(int a, int b) { return a + b; }
将 helper.cpp 编译成动态库
g++ -c -fPIC helper.cpp
g++ -shared -o libhelper.so helper.o
使用 该动态库
g++ main.cpp -L. -lhelper
然后使用 readelf 查看 dynamic section, 可以看到 libhelper.so 被标记为 NEEDED,这时因为 main.cpp 中使用到了动态库中的 add 函数。
$ readelf -d a.out
0x0000000000000001 (NEEDED) Shared library: [libhelper.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
未使用到动态库的符号
// main.cpp
int main()
{
return 0;
}
如果去掉对 add 函数的使用,再次按照上述流程进行处理的时候, 这时候就发现已经没有了 libhelper.so 库了。
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
但是如果使用 no-as-needed 参数, 可以发现即使没有使用到libhelper.so,该库也会被打上 NEEDED 的标签。
$ g++ main.cpp -L. -Wl,--no-as-needed -lhelper
$ readelf -d a.out
0x0000000000000001 (NEEDED) Shared library: [libhelper.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
实际问题
如这个帖子C++ 链接一个不需要的库(–no-as-needed)所描述的,如果程序没有使用到 libtorch 的接口,且不使用 --no-as-needed 参数链接 libtorch.so,就会在运行时出现找不到接口的问题。
参考: