LD:如果静态库中的任何符号被引用,--export-dynamic 是否意味着--whole-archive?

LD: does --export-dynamic imply --whole-archive for a static lib if any of it's symbols are referenced?

我的主要可执行文件 link 带有静态库,其符号需要可用于通过 dlopen() 加载的动态库。我知道我需要使用 -Wl,--export-dynamic,--whole-archive 标志才能使其正常工作。但是,在 link 命令上指定了许多库,有些可能未使用,而且我在通过当前构建基础结构中的 cmake 选择性地将 --whole-archive 应用到所需的库时遇到了困难。我所看到的是,如果只使用 -Wl,--export-dynamic 并且可执行文件调用感兴趣的静态库中的函数,那么整个库都会被包含进来,达到为它指定 --whole-archive 的相同效果,这正是我需要的。我可以依靠这种行为隐式地对符号被可执行文件引用的库施加 --whole-archive 吗?

What I'm seeing is that if only -Wl,--export-dynamic is used and the executable calls a function in the static library of interest, then the whole library gets included to the same effect of specifying --whole-archive for it, which is exactly what I need.

这不应该发生,您很可能误解了所见。

示例:

// foo.c
int foo() { return 42; }

// bar.c
int bar() { return 24; }

// main.c
int main() { return foo() - 42; }

gcc -w -c foo.c bar.c main.c
ar ruv libfoobar.a foo.o bar.o

gcc -Wl,--export-dynamic main.o -L. -lfoobar

nm a.out | egrep ' (foo|bar)'
000000000000113c T foo

如您所见,整个 libfoobar.a 包含在可执行文件中。对比:

gcc -Wl,--export-dynamic main.o -L. -Wl,--whole-archive -lfoobar -Wl,--no-whole-archive

nm a.out | egrep ' (foo|bar)'
0000000000001147 T bar
000000000000113c T foo

更新:

if I add a function foo1() to foo.c it is pulled in, but it also happens regardless if --export-dynamic is supplied.

这是预料之中的:linker 不会“拆分”单个 .o 文件——您要么得到全部,要么一无所获。

您可以通过在编译时使用 -ffunction-sections(和 -fdata-sections 作为一个好的措施)和在 link 时使用 -Wl,--gc-sections 来更改此行为。

成本增加 .o 大小和更长的 link 时间。好处是可执行文件更小。