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

时间:2014-02-18 12:46:21

标签: c++ c linker makefile

这样的命令会起作用:

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

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

我搜索了一些旧项目,并在makefile文件中找到了这些:

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

在我将$(LIBS)移到行尾之前不起作用。但我记得很久以前这对我很有用。有人可以回答改变了什么,为什么它不再起作用了) 附:我不喜欢使用编译器,链接器和其他工具 - 我更喜欢创建一些东西;)

1 个答案:

答案 0 :(得分:5)

我无法回答你为什么认为它之前可能有效。但我可以告诉你为什么它一般不起作用。大多数POSIX样式的链接器,包括GNU / Linux上使用的GNU binutils ld和其他链接器,是单通道链接器

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

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

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

所以,你可以看到,为了确保在一次传递中找到所有内容,需要来自库的符号的东西必须在提供这些符号的库之前,或者当链接器在单次传递中命中库,它将不知道库是否需要并将跳过它们。