使用未定义的引用构建库存档

Mel*_*vin 2 linker gcc archive

我的一位同事昨天告诉我,构建 libfoo.a 并不需要定义它的所有函数,只要您正在构建一个链接到它的可执行文件并且定义了缺失的引用就可以了。

他说档案只是带有索引的目标文件的集合,并且由于目标文件可以使用未定义的引用来构建,因此档案也可以..

这是真的 ?如果是这样,这是否意味着引用解析仅在链接阶段执行(即从不在编译或归档阶段)?

非常感谢..顺便说一下,编译器是gcc,语言是c/c++

Mik*_*han 5

是的,所有这些都是完全正确的。你似乎知道这libfoo.a 是一个ar档案。ar是 GNU 通用归档器。将您的 Documents、Pictures 和/或 Music 文件夹的内容存档为目标文件的集合是一件非常愉快的事情。

外部符号解析是链接:是链接的核心业务,链接只由链接器完成。如果ar要解析存档中目标文件的外部符号引用,则ar与链接器一样,需要命令选项来指定要在其中搜索符号定义的外部库,以及这些库所在的目录被搜索。它没有。

一个 ar档案可以用作接头输入文件。在这种情况下,链接器将在存档中搜索任何目标文件,这些目标文件为从已经消耗的目标文件中产生的未解析符号引用提供定义。它根本不关心存档中有哪些其他类型的文件,有或没有目标文件。如果它发现任何定义了未解析引用的目标文件,它就会从档案中提取它们并将它们添加到链接中,就好像它们已经在命令行中单独指定并且根本没有提到档案一样。因此,存档在链接中的唯一作用是作为一个目标文件包,链接器可以从中选择需要继续执行的目标文件。

如果我们知道提供链接器的正确包,我们就可以避免确切知道链接需要其中的哪些目标文件的困难。这就是静态库的用处。原则上,任何存档格式都可能被采用 ( .tar, .gz...) 但它ar是该领域的第一个,没有负担不需要的功能(目录序列化、压缩 ...),并且是历史的选择。LIB顺便说一下,Microsoft格式与ar格式。

对于链接器服务中的这一角色,GNUar专门针对目标文件的存在进行了一些处理。该s选项 - 这是一个默认的,可覆盖的 S- 将一个虚假的“文件”添加到存档中,其中包含一个空文件名和数据,链接器能够从存档中的任何目标文件定义的全局符号中将其作为查找表读取到这些目标文件的名称和位置。以前(以及在 的非 GNU 变体中ar),通过运行单独的程序来应用此组合,ranlib存档的,以便链接器可以访问它。注入 ranlib 表使链接器能够从存档中挑选它需要的目标文件。引入的任何未定义的引用这些目标文件供链接器照常从随后使用的目标文件或库中解析。

你的问题的措辞暗示,你是的印象是“归档”下-例如,创建libfoo.a-是一个过程,可以被调用,像编译和链接,通过GCC前端(gccg++gfortran等),其实并非如此. 这些前端仅调用(一个或多个)预处理器、编译器、汇编器和链接器。存档是将目标文件传递给链接器的辅助便利,可以通过以下命令直接创建ar

    ar cr libfoo.a file.o...
Run Code Online (Sandbox Code Playgroud)

完成此操作后,其中的未定义引用libfoo.a正是 中的未定义引用file.o ...