【问题标题】:Why does the gcc linker behave differently with .a files and .o files?为什么 gcc 链接器对 .a 文件和 .o 文件的行为不同?
【发布时间】:2016-04-06 21:29:56
【问题描述】:

使用this great answer 中关于 gcc 中链接顺序的示例,我尝试了以下操作:

echo 'extern int b; int a = b;' > b.cpp
g++ -c b.cpp -o b.o
ar cr libb.a b.o

echo 'int b;' > d.cpp
g++ -c d.cpp -o d.o
ar cr libd.a d.o

echo 'extern int a; int main() { return a; }' > a.cpp

g++ a.cpp -o a1 d.o b.o # Works
g++ a.cpp -o a2 libd.a libb.a # Fails

如果.a 文件只是一个包含一个或多个.o 文件的存档文件,那么如何与lib*.a 文件链接(按错误顺序,如原始答案中所述)失败,但使用.o 文件直接(以相同顺序)有效吗?

【问题讨论】:

  • Llibraries 如果不解析符号,从左到右将被忽略。 .o 文件不会被忽略。
  • @HansPassant:这背后的基本原理是什么?最后,无论如何,只有需要的部分保留在最终的二进制文件中,对吗?除了从存档中提取文件并直接链接它们之外,有没有办法使库的行为与目标文件的行为相同?
  • 这很主观。总的来说,这是工具制造商和程序员之间的永恒之战。工具制造者喜欢让他们的工具运行得很快,而且不占用大量内存。他们通常会赢。我使用的链接器不这样做,它通过 .lib 文件进行两次传递。但它有一个 1-800 的支持电话号码。
  • “使行为……相同”是什么意思?目标文件的每个部分都链接到最终的可执行文件中。使用图书馆这样做几乎违背了拥有图书馆的目的。想象一下去你当地的图书馆,要一本《战争与和平》,然后不得不带着图书馆里的每一本书回家。
  • 我的印象是链接器在构建最终二进制文件时只保留使用过的部分,但是通过进一步的测试,我看到我列出的每个 .o 实际上是如何被添加的。我的印象很可能是基于链接器忽略了未使用的 libraries 的事实。 gcc 链接器实际上忽略了库中未使用的 .o 文件,而不仅仅是整个库,我对吗?

标签: c++ gcc linker


【解决方案1】:

就链接器而言,静态库和目标文件的区别 在链接顺序是:-

  • 一个目标文件被链接,仅仅因为它是一个目标文件,不管它是否提供 可执行文件需要的任何符号的定义。如果你不想要一个对象 要链接的文件,不要向链接器提及。

  • 静态库是要从 库和链接如果需要,其中库中的目标文件是必需的 当且仅当它提供了至少一个迄今未定义的定义 链接器在目标文件或库中观察到的符号较早 连锁顺序。

【讨论】:

  • 这很有意义。因此,虽然一个库可能只是一个目标文件的存档(正如它经常被描述的那样),但通过使用一个用于链接,我们隐含地告诉链接器我们希望它只从中选择有用的目标文件。
  • @Masseman 确实如此。尽管链接的目标文件(即使来自库)也可能定义不需要的符号以及需要的符号。如果代码大小非常宝贵,您可以通过combination of compiler options and linker options 消除这种冗余
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-29
  • 2017-12-14
  • 1970-01-01
  • 2010-12-23
  • 1970-01-01
相关资源
最近更新 更多