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

C++ 为什么我必须在链接器行的末尾传递库?,c++,c,linker,makefile,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 但如果我将*.a放在*.o文件之前,它将无法从libs中找到函数 我搜索了一些旧项目,在makefiles中找到了如下行: $(CC) $(LIBS) -o $(TARGET) JukeboxMain.o JukeboxPlayer.o ... 在我将$(LIBS)移动到行的末尾

这样的命令将起作用:

(LD) $(LDFLAGS) -o reip.app newlib/crt0.o reip.o renetif.o fs.o httpd.o liblwip.a newlib/libc.a
但如果我将*.a放在*.o文件之前,它将无法从libs中找到函数

我搜索了一些旧项目,在makefiles中找到了如下行:

$(CC)  $(LIBS) -o $(TARGET) JukeboxMain.o JukeboxPlayer.o ...
在我将$(LIBS)移动到行的末尾之前,这也不起作用。但我记得很久以前它对我有用。有人能回答什么改变了以及为什么它不再工作了吗)
另外,我不太喜欢使用编译器、链接器和其他工具——我更喜欢创建一些东西;)

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

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

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

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


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

我无法回答您为什么认为它以前可能工作过。但我可以告诉你为什么它一般不起作用。大多数POSIX风格的链接器(包括GNU/Linux上使用的GNU binutils
ld
和其他链接器)都是单通道链接器

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

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

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


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

创建内容包括创建生成文件,这包括理解链接、预处理器和编译器quirks@EliasVanOotegem嗯,不一定是制作文件。至少不是直接的。一个CMake项目也可以。埃利亚斯-我不明白你在说什么。。并不总是需要Makefile。make只是一个简化构建过程的实用工具。要创建可执行文件,您需要编译器(包括预处理器)、链接器以及类似libc的东西。问题是为什么我应该将静态libs放在其他对象文件之前。是的,重复问题的答案对我的问题也是正确的。创建一些东西包括创建一个Makefile,这包括理解链接、预处理器和编译器quirks@EliasVanOotegem嗯,不一定是制作文件。至少不是直接的。一个CMake项目也可以。埃利亚斯-我不明白你在说什么。。并不总是需要Makefile。make只是一个简化构建过程的实用工具。要创建可执行文件,您需要编译器(包括预处理器)、链接器以及类似libc的东西。问题是为什么我应该将静态lib放在其他对象文件之前。是的,重复问题的答案对我的问题也是正确的。值得注意的(有趣的)事实:
-lpthread
——unix系统上的大多数多线程应用程序都需要它——遵循完全相同的规则。然而,
-pthread
being功能上等价的东西可以放在任何地方。这是因为
-lpthread
是一个简单的“查找名为
pthread
的库”,就像
-lfoo
一样。它没有特别的意义。但是
-pthread
是一个神奇的标志(不是针对链接器,而是针对编译器驱动程序),它告诉它执行启用线程所需的所有操作。这包括添加
-lpthread
(在末尾,应该是这样),但也包括编译过程中所需的任何内容(添加
-D_可重入
或任何内容)。由于不同的系统使用不同的选项,
-pthread
的开发目的是让它在任何地方都能“正常工作”。谢谢。这似乎是正确的答案)值得注意的(有趣的)事实:
-lpthread
——unix系统上的大多数多线程应用程序都需要它——遵循完全相同的规则。然而,
-pthread
being功能上等价的东西可以放在任何地方。这是因为
-lpthread
是一个简单的“查找名为
pthread
的库”,就像
-lfoo
一样。它没有什么特别的意义