计算机系统篇之链接(18):如何避免未使用的且直接依赖的共享库
Author: stormQ
Created: Wednesday, 13. January 2021 08:38PM
Last Modified: Tuesday, 23. February 2021 12:06PM
本文主要描述了未使用的且直接依赖的共享库是如何产生的,以及一种如何避免的方法。
step 1: 示例程序
hello.cpp:
int main()
{
return 0;
}
step 2: 生成“有未使用的且直接依赖的共享库”的可执行目标文件 hello
$ g++ -Wl,--no-as-needed -g -o hello hello.cpp
在笔者机器上,g++ 的版本信息如下:
$ g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
step 3: 查看“未使用的且直接依赖的共享库”
$ ldd -u hello
Unused direct dependencies:
/lib/x86_64-linux-gnu/libstdc++.so.6
/lib/x86_64-linux-gnu/libm.so.6
/lib/x86_64-linux-gnu/libgcc_s.so.1
在一些较低版本的 gcc/g++ 编译驱动器中,并没有默认使用链接器选项--as-needed
(该选项用于只链接需要的共享库)。所以,在生成可执行目标文件时,如果输入给链接器的共享库实际并不会使用(无论是系统共享库,还是第三方共享库),那么就会产生“未使用的且直接依赖的共享库”。
除此之外,在一些高版本的 gcc/g++ 编译驱动器中,如果禁用了默认的--as-needed
功能(即添加了-Wl,--no-as-needed
),也会产生“未使用的且直接依赖的共享库”。
至于如何判断 gcc/g++ 编译驱动器中是否默认提供--as-needed
功能,可以使用-v
选项查看编译的整个过程。
关于链接器选项--as-needed
的相关代码提交见:
gcc.c (init_gcc_specs): If HAVE_LD_AS_NEEDED, link with -lgcc --as-ne…
gcc.c (init_gcc_specs): Test USE_LD_AS_NEEDED, not HAVE_LD_AS_NEEDED.
至于如何避免未使用的且直接依赖的共享库,解决思路很直接:不将任何实际不使用的共享库作为链接器的输入。
对于第三方共享库,我们可以很简单地做到。然而,gcc/g++ 编译驱动器会默认将诸如libm.so
等系统共享库作为链接器的输入。我们可以通过链接器选项-nodefaultlibs
禁用这一行为。但,需要我们自己手动地添加需要的共享库,如下所示:
$ g++ -Wl,--no-as-needed -g -o hello hello.cpp -nodefaultlibs -lc
$ ldd ./hello
linux-vdso.so.1 (0x00007fff397d3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f70da02e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f70da23c000)
在使用-nodefaultlibs
选项后,查看“未使用的且直接依赖的共享库”:
$ ldd -u ./hello
$
从上面的结果可以看出,现在不存在“未使用的且直接依赖的共享库”了。
关于链接器选项-nodefaultlibs
的描述如下(截取自 《gcc 9.3 manual》):
Do not use the standard system libraries when linking. Only the libraries you
specify are passed to the linker, and options specifying linkage of the system
libraries, such as ‘-static-libgcc’ or ‘-shared-libgcc’, are ignored. The
standard startup files are used normally, unless ‘-nostartfiles’ is used.
其它相关的链接器选项:-nostartfiles
、-nolibc
和-nostdlib
,有兴趣的可以参考 GCC 手册。
下一篇:计算机系统篇之异常控制流(4):如何正确地让调用线程休眠一段时间