gcc在链接时通常用到的链接选项“-l”和“-L”分别用来指明需要链接的动态库名字及搜索路径,但是当使用的“-l”选项指定的库还有另外的依赖关系时,“-L”选项的参数无法提供对依赖库路径的包含。
假设我们有如下文件和自定义库文件:
./main.c
./lib/libtest.so
./lib/libtest2.so
其中 main.c依赖libtest.so
libtest.so又依赖libtest2.so
当我们如下编译链接时:
gcc -o test main.o -ltest -L./lib
编译器按照如下顺序寻找库文件:
- 首先会去找-L指定的参数目录
- 再找gcc的环境变量LIBRARY_PATH指定的参数
- 再找内定默认目录 /lib:/usr/lib: /usr/local/lib
在以上目录中找到需要的库文件之后,编译器将找到库文件的信息传递给链接器进行链接。
接着在调用链接器时,由于libtest.so又依赖libtest2.so,所以链接器接着去寻找libtest2.so文件,寻找顺序如下:
- 所有由'-rpath-link'选项指定的搜索路径
- 所有由'-rpath'指定的搜索路径
- 如果'-rpath'和'rpath-link'选项没有被使用, 会搜索环境变量'LD_RUN_PATH'的内容(它也只对本地连接器起作用)
- 对于一个本地连接器,环境变量'LD_LIBRARY_PATH'的内容被搜索.
- 对于一个本地ELF连接器,共享库中的`DT_RUNPATH'和`DT_RPATH'操作符会被需要它的共享库搜索. 如果'DT_RUNPATH' 存在了, 那'DT_RPATH'就会被忽略.
- 缺省目录, 常规的,如'/lib'和'/usr/lib'.
- 对于ELF系统上的本地连接器, 如果文件'/etc/ld.so.conf'存在, 这个文件中有的目录会被搜索.
如果需要的共享库没有被找到, 那连接器会发出一条警告信息
ld: warning: libtest2.so need by libtest.so not found (try using -rpath or -rpath-link)
说明链接器链接时,并未找到libtest.so需要的lianlibtest2.so文件。
这就说明链接器链接时寻找依赖库的路径里不包含“-L"指定的路径,“-L”只是单纯的增加一个寻找指定库文件的路径。
显然如果指定的库文件还依赖另外的库文件(例如libtest2.so),“-L"已经完成使命,则不会在寻找-L指定的目录。
ld --help 也可以看到关于“-L”的解释
-L DIRECTORY, --library-path DIRECTORY
Add DIRECTORY to library search path
遇到这种情况,有几种方法
- 在环境变量LD_LIBRARY_PATH中添加搜索路径(不建议使用,因为是全局变量)
- 在/etc/ld.so.conf'.d/目录中增加conf文件(ldconfig)
- 根据链接器警告提示,使用'-rpath'跟'-rpath_link'
- 其他(我不知道的....)
这里学习一下'-rpath'跟'-rpath_link'的用法,
ld --help中关于-rpath和-rpath-link的解释是:
-rpath PATH Set runtime shared library search path
-rpath-link PATH Set link time shared library search path
即在连接时,链接器需要依赖库时还会去搜索-rpath-link指定的路径。
-rpath为设置程序运行时搜索依赖库的路径,可以设置相对路径。
编译器中使用-rpath和-rpath-link 的格式如下:
gcc -Wl,rpath=/home/test:../lib:/usr/lib64
-Wl(小写L),<选项> 将逗号分隔的 <选项> 传递给链接器
不使用-Wl 编译器无法识别-rpath等选项。
-rpath和-rpath-link可以指定多个目录,目录与目录之间用冒号分割
参考:http://blog.csdn.net/youhaipeng/article/details/8213702
参考:http://www.laogu.com/wz_2754.htm