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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用未定义的引用构建库归档相关的知识,希望对你有一定的参考价值。

我的一位同事昨天告诉我,构建libfoo.a并不需要定义它的所有功能,只要它们构建一个链接到它的可执行文件并且定义了缺少的引用即可。

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

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

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

答案

是的,这一切都是完全正确的。你似乎知道libfoo.a是一个ar档案。 ar是GNU通用归档器。将文档,图片和/或音乐文件夹的内容存档为对象文件的集合非常乐意。

外部符号解析是链接:它是链接的核心业务,链接仅由链接器完成。如果ar应该解析归档中目标文件的外部符号引用,那么ar(如链接器)将需要命令选项来指定要在其中搜索符号定义的外部库,以及这些库中的目录。要搜索图书馆。它没有。

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

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

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

您的问题的措辞表明您可能会有“存档”的印象 - 例如创建libfoo.a - 是可以通过GCC前端(gccg++gfortran等)调用的进程之一,如编译和链接。但事实并非如此。这些前端仅调用(一个或多个)预处理器,编译器,汇编器和链接器。归档是将对象文件传递给链接器的辅助便利,并且使用ar直接创建:

    ar cr libfoo.a file.o...

完成后,libfoo.a中未定义的引用正是file.o ...中未定义的引用。

以上是关于使用未定义的引用构建库归档的主要内容,如果未能解决你的问题,请参考以下文章

yaml-cpp 未定义的 CMake 引用

LIBSSH2和dso_dlfcn.c:...对'dlopen'的未定义引用

我的代码中的C ++未定义引用错误?

Angular 6 库:在 CI 管道中构建库以创建 lib 版本

使用 Proguard 构建库时找不到 aapt_rules.txt

STM32-构建库函数雏形