我正在清理一个腐烂的源代码树,我尝试将每个可执行文件和每个共享库仅与它们直接使用的库链接。
为了做到这一点,我ldd -u- r
二进制输出,并从makefile中删除报告的库。
例如:
$ ldd -u -r ./libA.so
Unused direct dependencies:
/usr/local/lib/libB.so
/usr/local/lib/libC.so
/lib/tls/libpthread.so.0
$ sed -i'' -e 's/-lB//' -e 's/-lC//' Makefile
嗯,当然libpthread
确实需要(并且无论如何都隐含在-pthread
中),但ldd
报告的其他库可以安全删除。
对我的优化有影响吗?它完全安全吗?
答案 0 :(得分:6)
这是安全的*,除非发生一件事(谢天谢地,在你的控制之下)。
如果应用程序使用dlsym(RTLD_DEFAULT,...)
加载其他符号,它将在当前加载的共享库中搜索相应的符号(函数)。如果它的意图是从你要删除的其中一个库中加载符号(和没有先前的dlopen()
调用),应用程序将找不到它,并且可能行为不端。
但请注意,dlsym()
很少使用(并且您可以检查它是否通过ldd使用),而且如果没有事先调用dlopen()
,它甚至更少使用它,所以几乎在所有情况下,您都可以安全地删除未使它将显着提高应用程序的可移植性。
* by“safe”我的意思是“如果没有构建时错误,可能会工作”。删除库的构建时间后果太容易检测到,无法解释它们。
答案 1 :(得分:2)
我能想到的一个含义是,可能存在仅由可执行文件使用的隐式依赖项,但是在库中指定。例如。
$ cat a.cc
int fa(){return 42;}
$ gcc -shared a.cc -o liba.so -ltermcap
$ cat main.cc
#include <stdio.h>
#include <stdlib.h>
#include <termcap.h>
int main() {
tgetent(0,getenv("TERM"));
printf("terminal is %d columns\n",tgetnum("co"));
}
$ gcc main.cc -o main # we didn't mention -ltermcap
/tmp/ccercfhS.o(.text+0x27): In function `main':
: undefined reference to `tgetent'
collect2: ld returned 1 exit status
$ # we mentioned -ltermcap by using -la
$ # if we'll remove -ltermcap from liba the project won't compile
$ gcc main.cc -o main -L. -la
$ LD_LIBRARY_PATH=. ./main
terminal is 237 columns
然而,这并不是一个错误的错误,因为它总是会被您提前检测和修复,而不是由客户来检测。
无论如何,您应该include what you use因此,main.cc
与termcap
直接关联是非常好的。
答案 2 :(得分:1)
如果我是你,我会使用strace进行一两次试运行
strace -e open myprog&gt; strace.out 2&gt;&amp; 1
然后检查strace输出以查看实际打开的库。这意味着任何不返回-1的open()调用。
答案 3 :(得分:0)
对我来说,似乎还有另外一个暗示,就是ldd将显示所有未找到的未使用的库(它们可能在构建时就已经存在,所以这里没有错误)。
所以否,依靠ldd -u
的结果并不安全!
(在Ubuntu Ubuntu 18.04.2下使用ldd 2.27和在Devuan ascii下使用ldd 2.24进行了测试)