如果链接到未使用的库,则可执行文件的构建方式是否不同?

Tre*_*key 10 c++ shared-libraries static-libraries c++11

除了更长的编译时间,链接未使用的库是否有任何缺点?

例如,程序的可执行文件是否有任何差异,编译方式有两种:

g++ -o main main.cpp
g++ -o main main.cpp -llib1 -llib2 -llib3 -lmore
Run Code Online (Sandbox Code Playgroud)

*实际上不需要库文件来构建main.

我认为它没有区别,因为文件大小相同,但我要求确认.

Die*_*Epp 14

这取决于.

  1. 如果liblib1.a,liblib2.aliblib3.a是静态库,并且没有使用它们的符号,那么就没有区别了.

  2. 如果liblib1.so,liblib2.so或是liblib3.so共享库,则无论是否使用它们,它们都将在运行时加载.您可以使用链接器标志--as-needed来更改此行为,建议使用此标志.

要检查二进制文件在运行时直接加载哪些共享库,可以在ELF系统上使用readelf.

$ cat main.c
int main()
{
    return 0;
}
$ gcc main.c
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
$ gcc -lpng main.c
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libpng12.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

您可以在我的系统上看到-lpng链接libpng12.so.0,无论是否实际使用了符号.该--as-needed连接器参数修复了这个:

$ gcc -Wl,--as-needed -lpng main.c
$ readelf -d a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

笔记

  1. --as-needed标志必须被指定以前的库.它只会影响它后面出现的库.所以gcc -lpng -Wl,--as-needed不起作用.

  2. ldd命令不仅列出了二进制文件直接链接的库,还列出了所有间接依赖项.这可能会根据这些库的编译方式而改变.只会readelf向您显示您的直接依赖关系,并且只ldd显示间接依赖关系.