为什么我必须在链接器行的末尾传递库

Why do I have to pass libraries in the end of linker line?

本文关键字:链接 为什么      更新时间:2023-10-16

这样的命令会起作用:

(LD) $(LDFLAGS) -o reip.app newlib/crt0.o reip.o renetif.o fs.o httpd.o liblwip.a newlib/libc.a

但是,如果我把*.a放在*.o文件之前,它将无法从库中找到函数。

我搜索了一些旧项目,在makefiles中发现了这样的行:

$(CC)  $(LIBS) -o $(TARGET) JukeboxMain.o JukeboxPlayer.o ...

这也不起作用,直到我把$(LIBS)移到行的末尾。但我记得很久以前它对我有用。有人能回答一下发生了什么变化以及为什么它不再起作用吗?)附言:我不太喜欢玩编译器、链接器和其他工具——我更喜欢创建一些东西;)

我无法回答您为什么认为它以前可能有效。但我可以告诉你为什么它在一般情况下不起作用。大多数POSIX风格的链接器,包括在GNU/Linux和其他平台上使用的GNU binutilsld,都是单程链接器

这意味着它们会将命令行中列出的元素从头到尾遍历一次,并且不会返回。当链接器启动时,它基本上是在寻找一个符号main。在执行命令行时,链接器找到的任何对象文件(foo.o)都会添加到可执行文件中。该对象提供了一个已定义的符号列表和一个未定义的列表(其他对象需要)。

当链接器访问静态库(libfoo.a)时,它会查看该库中的对象文件,如果某个对象包含链接器需要的任何符号,它会将该对象添加到可执行文件中。如果它不包含链接器所需的任何符号,则将跳过该对象

在命令行的末尾,如果需要任何符号但未找到,则链接将失败。

因此,您可以看到,为了确保在一次遍历中找到所有内容,库中需要符号的东西必须在提供这些符号的库之前,否则,当链接器在一次访问中访问库时,它将不知道需要这些库,并将跳过它们。

相关文章: