kan*_*nna 9 attributes gcc constructor static-linking
我有一堆静态库,它们是相互依赖的.由于依赖性,我在为目标链接这些库时遇到了问题.作为一种解决方法,我从所有库中创建了一个归档文件.
其中一个静态库具有构造函数和析构函数,因此组合存档(使用nm和objdump检查存档)但是当我使用组合存档作为目标时,最终二进制文件不包含构造函数和析构函数.
我也尝试过--whole-archive但是这个选项对我来说似乎不起作用(二进制大小没有增加).
什么可能出错的想法.谢谢
链接器只加载它必须的模块(即你实际隐式或显式引用的内容),除非你强制它.
这既是好事,也是不幸的.它使链接过程更快,并防止代码膨胀.它通常也不会引起问题,因为通常您会以某种方式引用所需的所有模块,并且不需要您不引用的模块.一般.
但它也是导致此静默失败的原因:链接器从不加载包含构造函数/析构函数的模块,甚至从不查看它.那是因为你从未真正调用过这些函数.
您可以通过显式链接与包含构造函数/析构函数的源对应的目标文件来强制链接器包含该模块.
换句话说,如果构造函数/析构函数在foo.c,添加-l/path/to/foo.o到链接器的选项,或者只是将foo.o命令行传递给链接器(作为额外的参数).
在任何一种情况下,通过这样做,您明确告诉链接器考虑这个模块,这样做将使它找到构造函数并正确调用它们.
另一种方法(不需要你使用命令行)可能会将一个变量或一个函数(不一定做任何事情)放入与构造函数/析构函数相同的源文件中,并从任何源文件中调用该文件.主程序.
这也将强制链接器加载包含模块(它将在其中找到构造函数).
更新:
我测试了替代方案,它工作正常:
/* libcode.c */
void enable_constructors() { /* do nothing */ }
void __attribute__ ((constructor)) con() { __builtin_puts("construct"); }
void __attribute__ ((destructor)) des() { __builtin_puts("destruct"); }
/* main.c */
extern void enable_constructors();
int main()
{
enable_constructors();
__builtin_puts("main");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
construct
main
destruct
Run Code Online (Sandbox Code Playgroud)
它还适用于您从主程序中的源文件触摸的全局变量:
/* libcode.c */
int enable_constructors; /* not used for anything */
void __attribute__ ((constructor)) cons() { __builtin_puts("construct"); }
void __attribute__ ((destructor)) des() { __builtin_puts("destruct"); }
/* main.c */
extern int enable_constructors;
int main()
{
++enable_constructors; /* touch the other module */
__builtin_puts("main");
return 0;
}
Run Code Online (Sandbox Code Playgroud)