因为这就是GNU链接器使用的链接算法的工作方式(至少在链接静态库时)。链接器是一个单通道链接器,一旦看到它们就不会重新访问库。
库是目标文件的集合(归档)。使用该-l
选项添加库时,链接程序不会无条件地从库中获取所有目标文件。它仅采用当前需要的那些目标文件,即解析一些当前未解析(待定)符号的文件。之后,链接器完全忘记了该库。
当链接器处理输入的目标文件时,链接器会不断维护挂起的符号列表,从左到右一个接一个。在处理每个目标文件时,一些符号被解析并从列表中删除,其他新发现的未解析符号被添加到列表中。
因此,如果您通过使用包含了一些库-l
,则链接程序将使用该库来解析尽可能多的当前挂起的符号,然后完全忽略该库。如果以后突然发现它现在需要该库中的一些其他目标文件,则链接器将不会“返回”该库以检索那些其他目标文件。已经为时已晚。
由于这个原因,在链接器命令行的后期使用-l
选项始终是一个好主意,这样,当链接器到达该链接器时,它就可以可靠地确定所需的对象文件和不需要的对象文件。将选项作为链接器的第一个参数放置通常根本没有任何意义:在开始时,挂起的符号列表为空(或更准确地说,由单个符号组成),这意味着链接器不会从中获取任何内容图书馆。-l
-l
main
在你的情况,你的目标文件example.o
包含对符号的引用ud_init
,ud_set_input_file
等接头应首先接收目标文件。它将这些符号添加到未决符号列表中。之后,您可以使用-l
选项添加库:-ludis86
。链接器将搜索您的库并从中获取所有可解析那些未决符号的内容。
如果将-ludis86
选项首先放在命令行中,则链接器将有效地忽略您的库,因为在开始时它并不知道将需要它ud_init
,ud_set_input_file
等等。稍后,在处理example.o
时它将发现这些符号并将它们添加到挂起的符号清单。但是这些符号将一直无法解析到最后,因为它们-ludis86
已经被处理(有效地被忽略了)。
有时,当两个(或多个)库以循环方式互相引用时,一个库甚至可能需要对-l
同一库使用两次该选项,以使链接程序有两次机会从该库中检索必要的目标文件。