我有一堆静态库,它们是相互依赖的。
由于依赖关系,在为我的目标链接这些库时遇到了问题。
作为一种解决方法,我从所有库中创建了一个存档文件。

静态库之一具有构造函数和析构函数,合并的归档文件也是如此(使用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;
}

输出为:
construct
main
destruct

它也可以与全局变量一起使用,您可以从主程序中的源文件中触摸该全局变量:
/* 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;
}

10-06 05:15
查看更多