链接静态库时自定义目标段被丢弃问题咨询
问题原因分析
核心原因是静态库的链接筛选机制导致整个lib.o目标文件未被纳入最终链接:
- 静态库(
.a归档文件)的默认链接规则:链接器只会将静态库中能满足当前未定义符号引用的.o目标文件加载到最终二进制中,未被引用的静态库成员会被直接丢弃。 - 你代码里的
keep_somewhere是static修饰的静态变量,仅在lib.c编译单元内可见,不会导出外部符号,且主程序main.c没有引用lib.o中的任何符号,因此链接器判断lib.o完全没有用到,直接整个忽略,其中定义的mySection段自然不会出现在最终二进制里。 - 你用到的
__attribute__((used))仅作用于编译阶段:作用是告诉编译器不要因为该变量没有被当前编译单元内的代码引用就将其优化删除,这个属性完全无法干预链接器对静态库成员的筛选逻辑。你可以看到lib.o里确实保留了mySection,就是used属性生效的证明,但链接阶段没用到lib.o的话该属性自然不会生效。 - 直接链接
lib.o的场景是正常的:如果直接把.o目标文件作为参数传给编译器/链接器,链接器会无条件将所有传入的.o都纳入最终二进制,不会做筛选,因此main-simple里可以正常看到mySection段。
解决方案
可根据使用场景选择以下任意一种方案解决:
- 方案1:强制加载整个静态库
链接时添加--whole-archive参数强制加载静态库内所有目标文件,修改Makefile中main的编译命令为:
注意参数末尾要加main: lib.a main.c gcc -L. -Wl,--whole-archive -l:lib.a -Wl,--no-whole-archive main.c -o main--no-whole-archive恢复默认链接规则,避免把后续依赖的系统库也全量链入二进制。 - 方案2:触发lib.o的正常加载逻辑
移除keep_somewhere的static修饰,将其改为全局变量,然后在主程序中显式引用该变量,或者在链接时添加-Wl,--undefined=keep_somewhere参数强制生成对该符号的未定义引用,触发链接器主动加载lib.o。 - 方案3:通过链接脚本指定保留段
编写自定义链接脚本,显式指定将静态库中的mySection段合并到最终二进制中。
内容的提问来源于stack exchange,提问作者MarSik
相关产品推荐
相关产品推荐

