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

Gcc 使用未定义的引用构建库存档,gcc,linker,archive,Gcc,Linker,Archive,我的一位同事昨天告诉我,构建libfoo.A并不需要定义它的所有函数,只要您正在构建一个链接到libfoo.A的可执行文件并定义缺少的引用,它们就会被定义 他说,档案只是一个有索引的目标文件的集合,既然目标文件可以用未定义的引用构建,档案也可以 这是真的吗?如果是这样,这是否意味着引用解析仅在链接阶段执行(即从不在编译或归档阶段执行) 非常感谢。。顺便说一下,编译器是gcc,语言是c/c++是的,所有这些都是完全正确的。您似乎知道libfoo.a 是一个ar存档。是GNU吗 通用档案员。将内容归

我的一位同事昨天告诉我,构建libfoo.A并不需要定义它的所有函数,只要您正在构建一个链接到libfoo.A的可执行文件并定义缺少的引用,它们就会被定义

他说,档案只是一个有索引的目标文件的集合,既然目标文件可以用未定义的引用构建,档案也可以

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


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

是的,所有这些都是完全正确的。您似乎知道
libfoo.a
是一个
ar
存档。是GNU吗 通用档案员。将内容归档也很高兴 将您的文档、图片和/或音乐文件夹的 档案

外部符号解析就是联动:它是联动的核心业务,并且联动 仅由链接器完成。如果假定
ar
解析归档中目标文件的外部符号引用,则
ar
, 与链接器一样,需要命令选项来指定中的外部库 要搜索哪些符号定义,以及其中的目录 那些图书馆需要搜索。没有

ar
存档可以用作链接器输入文件。在这种情况下,链接器将 在存档中搜索为未解析文件提供定义的任何对象文件 从已使用的对象文件中累积的符号引用。会的 根本不在乎存档中还有哪些其他类型的文件,包括或 没有对象文件。如果它找到任何定义未解析引用的对象文件,它将提取 将它们从存档中删除并添加到链接中,就像它们是单独存在的一样 在命令行和存档中指定,但根本没有提到。所以 链接中的存档是一包对象文件,链接器可以从中选择一个 它需要继续下去

如果我们知道提供链接器的合适包,我们就不必费劲去知道了 确切地说,链接将需要其中的哪些对象文件。这就是有用之处 静态库的定义。原则上,可能采用了任何归档格式(
.tar
.gz
…),但
ar
是第一种 该字段没有多余的功能(目录序列化、压缩…),是历史的选择。 顺便提一下,Microsoft
LIB
格式与
ar
格式相同

对于链接器服务中的这个角色,GNU
ar
有一点专门化 用于显示对象文件。
s
选项-默认设置,可由
S
-向存档中添加一个假“文件”,其中包含空文件名和 链接器能够作为查找表从存档中任何对象文件定义的全局符号中读取到 这些对象文件的名称和位置。从前 (在
ar
的非GNU变体中)通过运行单独的 程序,使链接器可以访问它。 ranlib表的注入使链接器能够从归档中选择它需要的对象文件。 与这些对象文件一起引入的任何未定义引用都是供链接器使用的 像往常一样,从随后使用的对象文件或库中解析

您问题的措辞表明,您可能有“归档”的印象- e、 g.创建
libfoo.a
-是可以调用的过程之一,比如编译 通过GCC前端(
GCC
g++
gfortran
等)进行链接,这不是 所以这些前端只调用(一个或多个)预处理器、编译器和汇编程序 和链接器。归档是传递对象文件的辅助便利 到链接器,并直接使用
ar
创建:

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

中未定义的引用,这是一个很好的答案。再补充一点,链接阶段的顺序与链接器从归档中选择的内容不同。如果您使用
g++-lmylib-oa.out main.o
而不是
g++main.o-lmylib-oa.out
,则会出现
未定义引用
错误,因为链接器在处理
main.o
之前会将符号信息扔掉。对于后者,由于main.o首先被解析,链接器知道在提供的
.a
/
.so
文件中查找什么符号。至少,阿法尤。