我创建了一个简单的静态库libvec.a
从简单的AR工具addv.o
和multo.o
。 对象文件addv.o
包含1个函数符号( addvec
)和multo.o
包含1个函数( multvec
)。 我还写入一个简单的程序,以测试它( driver.c
这增加了2个向量,并使用addvec
从库函数;也已列入vector.h
定义函数原型)。 然后,我用它编译
gcc -static driver.o ./libvec.a
并且一切正常。 但起初我试图用编译它
gcc -static ./libvec.a driver.o
我得到了一个错误:
undefined reference to 'addvec'
我不知道为什么,当我第一次指定的库我得到一个错误? 如果顺序有关系吗?
前库,期间始终链接的目标文件。 至少直到你足够了解发生了什么事情没有需要问的问题摆在首位。
麻烦的是,链接器扫描库,并且它正在寻找main()
它没有找到它,所以它不拉任何出库。 然后,它会扫描driver.o
,发现什么正在寻找,但不是分别在东西libvec.a
(它已经忘记了,因为他们是不相关)。 因此,从功能上libvec.a
不满意引用-和连接失败。
需要注意的是静态库或共享库链接时,作品的前库的目标文件“。
现在,这完全是有道理的,从计算机系统:程序员的角度来看书。
在符号解析阶段,链接器扫描重定位目标文件和档案左至右在同一顺序它们出现的编译器驱动程序的命令行上。 (驱动程序自动转换命令行到.o文件上的任何.c文件。)在此扫描期间,所述接头保持的将合并以形成可执行的,未解析的符号的集合U重定位目标文件的一组E(即,符号引用,但尚未定义),和已经在前面的输入文件被定义符号的一组d。 最初,E,U和d是空的。
在命令行上的每个输入文件f,链接器确定如果f是一个对象文件或归档。 如果f是一个目标文件,链接器增加了F到E,更新U和d以反映符号定义和f中引用,以及到下一个输入文件进行。
如果f是一个档案,链接器试图匹配以U抵抗由归档的成员定义的符号的未解析的符号。 如果某些归档成员,米,定义了解析以U的参考符号,则m被添加到E,并且所述接头的更新U和d以反映m中的符号定义和引用。 达到该过程迭代在归档中的成员对象的文件,直到一固定点,其中U和d不再变化。 在这一点上,不包含在E以外的任何成员对象的文件被简单地丢弃和接头进行到下一个输入文件。
如果U是当非空接头完成扫描在命令行上输入文件,它打印出错误并终止。 否则,合并和重新定位在E中的目标文件建立输出可执行文件。
不幸的是,这种算法可以导致一些莫名其妙的链接时错误,因为库和目标文件的命令行上的顺序是显著。 如果定义了一个符号库中出现引用该符号的目标文件之前,在命令行中,则引用就不会被解决和链接将失败。