2016-04-06 26 views
0

运用this great answer关于GCC链接顺序的例子,我试过如下:为什么gcc链接程序与.a文件和.o文件的行为不同?

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文件(以相同的顺序)有效吗?

+3

如果库从左到右未解析符号,则会忽略它们。 .o文件不会被忽略。 –

+0

@HansPassant:这背后的基本原理是什么?最后,无论如何,只有需要的部分才会保留在最终的二进制文件中,对吗?有没有办法使库的行为与对象文件相同,除了从档案中提取文件并直接与它们链接? – Masseman

+0

这很主观。总的来说,这是工具制造商和程序员之间的永恒战斗。工具构建者喜欢使他们的工具运行速度快,并且不占用大量内存。他们通常会赢。我使用的链接程序不会执行此操作,它会通过.lib文件进行两次传递。但它有一个1-800支持电话号码。 –

回答

1

至于连接方面,静态库和在连接序列中的目标文件 之间的区别是: -

  • 一个目标文件就是被挂,只是因为它是一个目标文件,不管它是否提供可执行文件需要的任何符号的定义。如果您不希望链接对象 文件,请不要将它提及链接器。

  • 静态库是将被从 文库中提取,如果需要,其中需要在一个库中的对象文件链接对象文件的存档 当且仅当它提供了一个定义至少有一个未定义的符号,即连接器已经在对象文件或库中观察到的符号出现之前在 中的连接序列。

+0

这很有道理。因此,虽然库可能只是对象文件的存档(正如经常描述的那样),但通过使用链接器,我们隐含地告诉链接器我们只希望它从中选择有用的对象文件。 – Masseman

+0

@Masseman确实如此。尽管链接的目标文件(即使是来自库)也可能会定义符号,而不是必需的符号以及符号。如果代码量很大,则可以通过[编译器选项和链接器选项的组合 ](http://stackoverflow.com/q/6687630/1362568)消除此类冗余, –

相关问题