GCC在链接过程中,对参数中的库的顺序是有要求的,参数右侧的库会先于左侧的库加载,也就是说参数的解析是从右往左的。
假设库B依赖与库A,则链接的时候要写为:
gcc -o bin -lB -lA
如果写为:
gcc -o bin -lA -lB
则在B中引用的A中的内容就会无法链接通过。
如果你的库在链接时安排的顺序是:foo.o -lz bar.o。那么gcc的链接器先搜索库foo,然后是z库,然后是bar库。
这样就带来一个问题,如果库bar调用了库z里面的函数,但是链接器是先搜索的库z,这时候并没有发现库bar调用库z啊,所以就不会把库z中的这部分函数体挑出来进行链接。
而是只把库z中,被foo库调用的函数体挑出来。
一句话,越是被别人调用的越底层的库,就越放在后面;越是调用别人的越上层的库,就越放在前面。
为什么要指定顺序呢?
答:不依命令行的顺序的话就得重复扫描目标文件,我猜可能是重复扫描库文件的开销比较大所以必须在命令行指定正确的顺序
例子
今天在编译的时候遇到一个gcc编译链接库顺序的问题,描述如下:
$ gcc elements.c -o par -L/usr/lib -lparsifal
编译通过,但是如下编译时出错
$ gcc -L/usr/lib -lparsifal elements.c -o par
/tmp/ccO82iYg.o: In function `main':
elements.c:(.text+0xcb): undefined reference to `XMLParser_Create'
elements.c:(.text+0x143): undefined reference to `XMLParser_Parse'
elements.c:(.text+0x187): undefined reference to `XMLParser_Free'
collect2: ld 返回 1
两者不同指出就是链接库指定的顺序不同。
将多个.o文件链接成可执行文件的时候。如果链接的顺序不对,会产生错误。
《An introduction of gcc》里面有下面一段话:
On Unix-like systems, the traditional behavior of compilers and linkers
is to search for external functions from left to right in the object files
specified on the command line. This means that the object file which
contains the definition of a function should appear after any files which
call that function.
意思:传统的编译器和链接器在搜索 external functions 会从命令行 左到右去搜,这意味着,越是底层的库或者.o ,应该放到最后
但是也说了:
Most current compilers and linkers will search all object files, regardless
of order, but since not all compilers do this it is best to follow the
convention of ordering object files from left to right.
大多数编译器会全搜,但是不保证,所以最好按照标准来,越是被别人调用的越底层的库,就越放在后面;越是调用别人的越上层的库,就越放在前面