gcc命令行-llibrary的查找顺序

linux下面的动态库和静态库和windows平台还是略有不同的。

可以参考前面写的《gcc命令行静态库链接顺序》,大致的对应关系是:.dll<>.so,.lib<>.a,.obj<>.o。

objdumpnm工具可以用来查看这些文件的信息。

.lib有的是纯静态库,有的是.dll的介绍人(甚至可以直接从现有的dll用msvc的工具生成这种.lib,参考附注);但是.a文件我目前发现只有静态库一种。

尽管如此,如果/usr/lib/libz.a和/usr/lib/libz.so都存在的话,gcc yourcode.c -lz的话,生成的a.out,可以用ldd验证,还是直接依赖了libz.so,这算是一个优化吧。

同时,如果只有/usr/lib/libz.a,相同的命令行,ldd a.out就会发现没有了这个依赖,libz.a被纯粹地静态链接进了a.out。

 

然后是顺序的问题,这分为两个部分,运行时的共享库动态加载的搜索顺序,以及gcc -llibrary的搜索顺序。

对于前者,man ld.so一目了然。不过值得一提的是,把LD_LIBRARY_PATH放到bash的profile之类的地方定义,很多发行版已经会自动屏蔽掉了,因为这会引发很多负面的效应。

注:还有个坑,就是开启用-Wl,-rpath=/usr/local/lib/,-enable-new-dtags开启DT_RUNPATH功能的时候,这个路径只对当前的镜像有用。例如我用-lglog结合上述选项链接出exe,但是如果glog.so依赖gflags,即便也位于/usr/local/lib/,那么运行时一样会提示加载不到gflags.so,解决办法就是把-lgflags也放到exe的链接命令里。

对于后者,man gcc中很含混,我总结大概是这样。gcc yourcode.c -lz的话,就会去/lib和/usr/lib下面去找libz.a,然后根据有没有libz.so来使用静态链接或者动态链接,有没有其他目录我不清楚,文档中没有说明。

这两个目录的局限是,如果没有libz.a,有没有libz.so都没用。

值得一提的是ldconfig管理的目录跟这个没有关系(它只管理运行时的搜索顺序,参考man ld.so)。

LIBRARY_PATH变量和-L可以用来扩充这个搜索范围,同时也破除了上面的限制,哪怕只有libz.so,用这两个方法也能成功链接成动态加载的。

但是如果说,你没有libz.a,也没有libz.so,只有libz.1.0.0,那么你除了使用LIBRARY_PATH或者-L参数之外,还要制作一个libz.so的软链接,否则-lz也无法成功链接到libz.1.0.1。

 

附注-.a和.o的互相转换:

因为.a是.o的archive,所以.a可以转换成.so(当然,因为.a中的.o一般不是用-IPC选项编译出来的,所以在某些平台可能有问题);但是因为.so不像.a是个archive,所以很难从中提取到.o,所以.so目测没有方法转换成.a。

你可能感兴趣的:(library)