Jon Chesterf..
8
这个答案的优点将取决于您使用静态库的原因.如果允许链接器稍后删除未使用的对象,那么我几乎无法添加.如果它是为了组织的目的 - 最小化必须传递给链接应用程序的对象的数量 - 这种对Employed Russian的答案的扩展可能是有用的.
在编译时,可以使用以下命令设置编译单元中所有符号的可见性:
-fvisibility=hidden
-fvisibility=default
这意味着可以编译具有默认可见性的单个文件"interface.c"和具有隐藏可见性的大量实现文件,而无需注释源.然后,可重定位链接将生成单个目标文件,其中非api函数被"隐藏":
ld -r interface.o implementation0.o implementation1.o -o relocatable.o
现在可以对组合的目标文件进行objcopy:
objcopy --localize-hidden relocatable.o mylibrary.o
因此,我们有一个目标文件"library"或"module",它只公开预期的API.
上述策略与链接时间优化适度地相互作用.使用-flto编译并通过编译器将-r传递给链接器来执行可重定位链接:
gcc -fuse-linker-plugin -flto -nostdlib -Wl,-r {objects} -o relocatable.o
使用objcopy像以前一样本地化隐藏的符号,然后最后一次调用链接器来剥离本地符号以及它可以在post-lto对象中找到的任何其他死代码.遗憾的是,relocatable.o不太可能保留任何与lto相关的信息:
gcc -nostdlib -Wl,-r,--discard-all relocatable.o mylibrary.o
lto的当前实现在可重定位链接阶段期间似乎是活动的.使用lto,隐藏的=>本地符号被最终的可重定位链接剥离.没有lto,hidden => local符号在最终的可重定位链接中幸存下来.
lto的未来实现似乎可能通过可重定位链接阶段保留所需的元数据,但是目前可重定位链接的结果似乎是一个普通的旧目标文件.