ld链接库的顺序

2020-07-31

这次讲讲ld链接库,没想到吧,链接库时的顺序很重要,而为了让顺序不辣么重要,所有了解–start-group很重要。

-( ARCHIVES -)'–start-group ARCHIVES –end-group’

ARCHIVES 应当是一个关于档案文件的列表. 它们可以是显式的文件名,或者’-l’选项。这些指定的档案文件会被多遍搜索,直到没有新的无定义引用被创建。

通常,一个档案文件只会被搜索一次。 但如果这个档案文件中的一个符号需要被用来解析一个档案中的目标引用到的无定义的符号,而这个符号在命令行上的后面某个档案文件中出现, 连接器不能解析这个引用。把这些档案文件分组后,它们都可被反复搜索直到所有可能的引用都被解析了为止。

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

这是在工具链接的其它中:

1

这是在工具链接的库中:

2

这是指定放在makefile中,并且在—start-group外面,顺序为-lsecond –lstatic,其中second中的函数引用,定义在static中:

3

这是指定放在makefile中,并且在—start-group外面,顺序为-lstatic -lsecond:

4

由此可见,–start-group ARCHIVES –end-group,的确起到了多个档案文件中使用循环引用时,保证正确。如果不用它,那么链接的顺序一定是:先链接调用该函数的库,再链接定义该函数的库。

另外,链接库的方式我知道有两种:

  1. 直接使用绝对路径下的文件。比如:

    F:/workspace/6.1.3.2/platform/workspace/libsecond.a。

  2. 使用-l参数,比如-lsecond。

如果ld加了参数-non-static,那么默认的-lsecond,会优先搜索second.so,如果找不到会再搜索second.a。

另外,我考虑掉了一种情况,即在两个库中拥有同样的函数,那么这样的话,如果需要用到接口时,ld会去链接,哪个库放前面,就先找哪个库中的函数。此时,不管在—start-group里,或者不在,都不重要了,在前面的库的函数将优先被引用。

这里有个重点是需要注意的:

那就是,链接的最小单元一般是文件,*.o。那么,如果a.o和b.o同时存在test1(),a.o和b.o存在于不同的库,那么ld会去链接,哪个库放前面,就先找哪个库中的函数。

但是!如果a.o和b.o同时存在test1(),但是a.o有test2(),b.o有test3(),结果这两个接口函数都会被系统使用,那么a.o和b.o就会被同时链接进去。这就是为何会报多重定义的错误。