如何在 GCC 中组织程序的自定义构建?假设我们有以下一组独立的源文件:
Vec2.c
Vec3.c
Mat3.c
, 收藏在图书馆libMegaSuperMath.a
。树桩很清楚,通过链接这样的库,我们将其所有内容包含在最终的可执行模块中(或者我们不包含它?)。
如果使用此类库的程序不需要它的某些组件,如何组织选择性链接?GCC 会删除未使用的结构、函数和数据吗?为此需要哪些优化标志?在这种情况下,将库的各个“类”构建到目标文件中,并基于所需的“类”构建汇编指令是否可以接受?像这样的东西:
Vec2.o
Vec3.o
Mat3.o
和
cc NewUberTurboProgramm.c Vec2.o Mat3.o -o Run.exe
不,图书馆不是无条件和完全链接的。库是目标文件的存档,仅从中获取“必需的”目标文件。
在“经典”库链接算法中,从库中获取那些并且只有那些当前需要的目标文件。链接器从左到右依次查看链接的组件,因为它们是在链接器的命令行上指定的。在此查找期间,它维护一个当前未找到/未解析符号的列表(一开始,此列表仅包含一个符号
main
或其等价物)。在从左到右的处理过程中,从命令行遇到的下一个库开始,只取那些允许某些当前不允许的字符的目标文件。因此,从库中删除代码直到目标文件。因此,您的陈述“通过链接这样的库,我们将其所有内容包含在最终的可执行模块中”是不正确的。
由此也得出结论,最好在链接器命令行末尾的某个位置指定库 - 当链接器已经知道未解析符号的整个列表并因此将从库中获取它需要的所有内容时。如果您过早在命令行上指定库,那么可能会导致链接器没有从中获取所需的一切,因为那时它还不知道所需的一切。特别是,如果您在命令行上将库指定为第一个库,则根本不会从中获取任何内容(除非库提供了
main
.在链接器命令行上直接指示单个目标文件时,情况就不同了:一个明确指定的目标文件总是无条件地整体链接到程序,不管它当时是否“需要”。
在传统的“经典”链接器中,实现函数精确链接的唯一方法是将每个函数放在其自己的单独目标文件中。但是许多现代编译器和链接器已经支持函数精确链接,而无需在文件中单独传播函数。在 GCC 中,这是通过 LTO - 链接时间优化来完成的。