为什么 gcc 中“-l"选项的顺序很重要? [英] Why does the order of '-l' option in gcc matter?

查看:35
本文介绍了为什么 gcc 中“-l"选项的顺序很重要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编译一个使用 udis86 库的程序.实际上,我正在使用图书馆的 用户手册 中给出的示例程序.但是编译的时候报错.我得到的错误是:

I am trying to compile a program which uses udis86 library. Actually I am using an example program given in the user-manual of the library. But while compiling, it gives error. The errors I get are:

example.c:(.text+0x7): undefined reference to 'ud_init'
example.c:(.text+0x7): undefined reference to 'ud_set_input_file'
.
.
example.c:(.text+0x7): undefined reference to 'ud_insn_asm'

我使用的命令是:

$ gcc -ludis86 example.c -o example 

按照用户手册中的说明.

as instructed in the user-manual.

显然,链接器无法链接 libudis 库.但是,如果我将命令更改为:

Clearly, linker is not able to link libudis library. But if I change my command to:

$ gcc example.c -ludis86 -o example 

它开始工作.那么请有人解释第一个命令有什么问题吗?

It starts working. So can please someone explain what is the problem with the first command?

推荐答案

因为 GNU 链接器使用的链接算法就是这样工作的(至少在链接静态库时是这样).链接器是单程链接器,一旦被看到就不会重新访问库.

Because that's how the linking algorithm used by GNU linker works (a least when it comes to linking static libraries). The linker is a single pass linker and it does not revisit libraries once they have been seen.

库是目标文件的集合(存档).当您使用 -l 选项添加库时,链接器不会无条件地从库中获取所有 目标文件.它只需要那些当前需要的目标文件,即解析一些当前未解析(待处理)符号的文件.之后,链接器完全忘记了那个库.

A library is a collection (an archive) of object files. When you add a library using the -l option, the linker does not unconditionally take all object files from the library. It only takes those object files that are currently needed, i.e. files that resolve some currently unresolved (pending) symbols. After that, the linker completely forgets about that library.

挂起符号列表由链接器在链接器处理输入目标文件时从左到右一个接一个地持续维护.当它处理每个目标文件时,一些符号被解析并从列表中删除,其他新发现的未解析符号被添加到列表中.

The list of pending symbols is continuously maintained by the linker as the linker processes input object files, one after another from left to right. As it processes each object file, some symbols get resolved and removed from the list, other newly discovered unresolved symbols get added to the list.

因此,如果您使用 -l 包含某个库,链接器将使用该库来解析尽可能多的当前挂起的符号,然后完全忘记该库.如果它稍后突然发现它现在需要来自该库的一些附加目标文件,则链接器将不会返回"该库以检索这些附加目标文件.已经太晚了.

So, if you included some library by using -l, the linker uses that library to resolve as many currently pending symbols as it can, and then completely forgets about that library. If it later suddenly discovers that it now needs some additional object file(s) from that library, the linker will not "return" to that library to retrieve those additional object files. It is already too late.

出于这个原因,在链接器的命令行中使用 -l 选项 late 总是一个好主意,这样当链接器到达那个 -l 它可以可靠地确定哪些目标文件需要哪些不需要.将 -l 选项作为链接器的第一个参数通常没有任何意义:一开始挂起的符号列表是空的(或者,更准确地说,由单个符号 main),这意味着链接器根本不会从库中获取任何东西.

For this reason, it is always a good idea to use -l option late in the linker's command line, so that by the time the linker gets to that -l it can reliably determine which object files it needs and which it doesn't need. Placing the -l option as the very first parameter to the linker generally makes no sense at all: at the very beginning the list of pending symbols is empty (or, more precisely, consists of single symbol main), meaning that the linker will not take anything from the library at all.

在您的情况下,您的目标文件 example.o 包含对符号 ud_initud_set_input_file 等的引用.链接器应接收该目标文件第一的.它将这些符号添加到挂起符号列表中.之后,您可以使用 -l 选项添加您的库:-ludis86.链接器将搜索您的库,并从中获取解决这些挂起符号的所有内容.

In your case, your object file example.o contains references to symbols ud_init, ud_set_input_file etc. The linker should receive that object file first. It will add these symbols to the list of pending symbols. After that you can use -l option to add the your library: -ludis86. The linker will search your library and take everything from it that resolves those pending symbols.

如果您将 -ludis86 选项放在命令行的首位,链接器将有效地忽略您的库,因为一开始它不知道它需要ud_initud_set_input_file 等.稍后在处理example.o 时,它会发现这些符号并将它们添加到待处理符号列表中.但是这些符号到最后都不会被解析,因为 -ludis86 已经被处理了(并且实际上被忽略了).

If you place the -ludis86 option first in the command line, the linker will effectively ignore your library, since at the beginning it does not know that it will need ud_init, ud_set_input_file etc. Later, when processing example.o it will discover these symbols and add them to the pending symbol list. But these symbols will remain unresolved to the end, since -ludis86 was already processed (and effectively ignored).

有时,当两个(或多个)库以循环方式相互引用时,甚至可能需要对同一个库使用两次 -l 选项,以给链接器两次检索的机会来自该库的必要目标文件.

Sometimes, when two (or more) libraries refer to each other in circular fashion, one might even need to use the -l option twice with the same library, to give linker two chances to retrieve the necessary object files from that library.

这篇关于为什么 gcc 中“-l"选项的顺序很重要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆