比如静态库a的实现依赖于静态库b(单向依赖,互相依赖的情况不讨论),main函数的实现只依赖于静态库a,则在生成应用程序时必须将两个库都链接进来,并且两者的前后顺序不能颠倒,如:

 Gcc –o main main.c –a –b

即依赖者(a)必须放在被依赖者(b)的前面。

 

如果将b和a位置互换,即:

Gcc –o main main.c –b –a

会在a里面报错——找不到b中的接口。

个人认为,编译器在链接时如果遇到未定义的符号,会往后面的库里面找。在main中遇到a中的接口时,编译器一直往后找,找到库a,然后将a中的内容链接进来,这时遇到b中定义的接口,再往后找。但是后面已经没有库可供查找了,因此报错——在a中找不到b的接口。

 

如果改成下面这种形式就不会报错了:

Gcc –o main main.c –b –a –b

因此,如果两个库实现不合理,里面出现相互依赖的情况时,往往就会出现这种bab,baba……甚至更严重的情况。

 

如果搞不清依赖顺序,也有偷懒的方法,带来的是效率上的开销,如下:

Gcc –o main main.c –Xlinker “-(” –b –a –Xlinker “-)”

发现,上面的命令也编过了,这就得参考下面两点了:

-Xlinker option

把选项option传递给连接器.可以用他传递系统特定的连接选项, GNU CC无法识别这些选项.

如果需要传递携带参数的选项,你必须使用两次`-Xlinker',一次传递选项,另一次传递他的参数. 例如,如果传递`-assert definitions',你必须写成`-Xlinker -assert -Xlinker definitions',而不能写成`-Xlinker "-assert definitions"',因为这样会把整个 字符串当做一个参数传递,显然这不是连接器期待的.

`-( ARCHIVES -)'

`--start-group ARCHIVES --end-group'

ARCHIVES应当是一个关于档案文件的列表. 它们可以是显式的文件名,或者'-l'选项.

这些指定的档案文件会被多遍搜索,直到没有新的无定义引用被创建. 通常,一个档案文件只会被搜索一

次. 但如果这个档案文件中的一个符号需要被用来解析一个档案中的目标引用到的无定义的符号,而这个

符号在命令行上的后面某个档案文件中出现, 连接器不能解析这个引用. 把这些档案文件分组后,它们都

可被反复搜索直到所有可能的引用都被解析了为止.

使用这个选项有一个很大的运行开销. 只有在无法避免在多个档案文件中使用循环引用时才用它.

 

这已经介绍的很清楚了,原来的一趟查找变成了反复地查找,自然就不再需要考虑顺序了。