linux下的静态库依赖

背景

linux的静态库.a和动态库.so的区别很大,静态库基本上只是一系列.o文件的集合加上符号表,没有链接过程,不能依赖链接其他的静态库或者动态库。如果静态库中用到了其他的库,需要这个静态库的使用者在最终的链接阶段清楚所有使用到的库,然后一一链接。

如果静态库依赖的库很多的话,而且依赖的关系很复杂,那么对于最终的使用者来说绝对是一场噩梦。

方案

linux下的静态库其实就是一系列.o文件的集合加上符号表。那么如果把它所依赖的静态库里的.o全部提取出来,然后再一起打包,更新符号表,是不是最终的使用者就可以不用管这些依赖了呢?
答案是的确可以,优点就是使用者不用去关心一堆静态库依赖,缺点是静态库的编写者需要花费更多的精力,并且静态库的体积会增大。

那么静态库依赖的动态库怎么办呢?
没有办法,静态库上没有链接信息,也不可能把动态库包含在里面,所以静态库如果真的依赖其他库,最好都依赖静态库。

打包

那么怎样将一个静态库打包到另一个静态库里呢?
静态库打包工具ar提供了-q选项来追加.o文件,理论上把所有依赖的静态库解开后打包是可行的,但是这样很难使用脚本来自动化打包,接下来我们使用一种很少见的方式来直接将.a添加到另一个.a中。
ar有一个选项-M,可以执行一种ar脚本,这种脚本的资料非常少,在man ar中都没有介绍。我们接下来就使用这种脚本来将一个静态库添加到另一个静态库中。

CREATE libstatic.a
SAVE
END

这个脚本的作用是创建一个空的名为libstatic.a的库,以上脚本保存为ar.mac
执行ar -M < ar.mac,可以看到这里是使用了重定向输入来执行脚本的。

ar -q libstatic.a s1.o
ar -q libstatic.a s2.o
ar -q libstatic.a s3.o

然后在shell中执行上面的命令,将静态库自己的.o文件添加到库中。

OPEN libstatic.a
ADDLIB libstatic123.a
SAVE
END

这个脚本的作用是打开库文件然后添加另一个依赖库文件。
将脚本保存后同样使用ar -M执行。

这样就完成了将一个库添加到另一个库中,此时可以使用ar -t命令查看一下库里面的内容,可以看到依赖库的.o文件都被包含进去了。