为什么在GCC中,库的链接顺序有时会导致错误?


当前回答

一个让我绊倒的小技巧:如果你以“gcc”或“g++”来调用链接器,那么使用“——start-group”和“——end-group”不会将这些选项传递给链接器——也不会标记错误。如果你的库顺序是错误的,它将失败的链接与未定义的符号。

你需要把它们写成"-Wl,——start-group"等来告诉GCC将参数传递给链接器。

其他回答

另一种方法是两次指定库列表:

gcc prog.o libA.a libB.a libA.a libB.a -o prog.x

这样做,您不必为正确的序列而烦恼,因为引用将在第二个块中解析。

我已经见过很多次了,我们的一些模块链接了超过100个我们的代码库加上系统和第三方库。

根据HP/Intel/GCC/SUN/SGI/IBM/等不同的连接器,你可以得到未解析的函数/变量等,在某些平台上,你必须列出库两次。

在大多数情况下,我们使用库、核心、平台、不同抽象层的结构化层次结构,但对于某些系统,您仍然必须使用link命令中的顺序。

一旦你找到了一个解决方案,那么下一个开发人员就不必再做了。

我以前的老师常说,“高内聚低耦合”,今天依然如此。

GNU ld链接器是所谓的智能链接器。它将跟踪之前静态库使用的函数,永久地从它的查找表中丢弃那些没有使用的函数。结果是,如果您过早地链接一个静态库,那么该库中的函数将不再对链接线上的静态库可用。

典型的UNIX链接器从左到右工作,因此将所有依赖的库放在左边,而满足这些依赖关系的库放在链接行的右边。您可能会发现一些库依赖于其他库,而同时其他库也依赖于它们。这就是事情变得复杂的地方。当涉及到循环引用时,修复您的代码!

下面是一个示例,可以清楚地说明涉及静态库时GCC是如何工作的。让我们假设我们有以下场景:

myprog。包含O的main()函数,依赖于libmysqlclient Libmysqlclient -静态的,对于这个例子来说(当然,你更喜欢共享库,因为Libmysqlclient非常大);在/usr/local/lib;并且依赖于来自libz的东西 libz(动态)

我们如何把它们联系起来?(注:使用gcc 4.3.4在Cygwin上编译的示例)

gcc -L/usr/local/lib -lmysqlclient myprog.o
# undefined reference to `_mysql_init'
# myprog depends on libmysqlclient
# so myprog has to come earlier on the command line

gcc myprog.o -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# we have to link with libz, too

gcc myprog.o -lz -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# libz is needed by libmysqlclient
# so it has to appear *after* it on the command line

gcc myprog.o -L/usr/local/lib -lmysqlclient -lz
# this works

你可以使用-Xlinker选项。

g++ -o foobar  -Xlinker -start-group  -Xlinker libA.a -Xlinker libB.a -Xlinker libC.a  -Xlinker -end-group 

几乎等于

g++ -o foobar  -Xlinker -start-group  -Xlinker libC.a -Xlinker libB.a -Xlinker libA.a  -Xlinker -end-group 

小心!

团队内部的顺序很重要! 这里有一个例子:调试库有一个调试例程,但是非调试例程 库有一个相同的弱版本。必须放置调试库 组中的FIRST,否则将解析为非调试版本。 您需要在组列表中的每个库之前加上-Xlinker