动态库的连接和连接选项-L,-rpath-link,-rpath

https://my.oschina.net/shelllife/blog/115958linux

连接动态库

如何程序在链接时使用了共享库,就必须在运行的时候可以找到共享库的位置。linux的可执行程序在执行的时候默认是先搜索/lib和/usr/lib这两个目录,而后按照/etc/ld.so.conf里面的配置搜索绝对路径。同时,Linux也提供了环境变量LD_LIBRARY_PATH供用户选择使用,用户能够经过设定它来查找除默认路径以外的其余路径,如查找/work/lib路径,你能够在/etc/rc.d/rc.local或其余系统启动后便可执行到的脚本添加以下语句:LD_LIBRARY_PATH =/work/lib:$(LD_LIBRARY_PATH)。而且LD_LIBRARY_PATH路径优先于系统默认路径以前查找(详细参考《使用LD_LIBRARY_PATH》)。shell

不过LD_LIBRARY_PATH的设定做用是全局的,过多的使用可能会影响到其余应用程序的运行,因此多用在调试。(LD_LIBRARY_PATH的缺陷和使用准则,能够参考《Why LD_LIBRARY_PATH is bad》 )。一般状况下推荐仍是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,而且该库的路径信息保存在可执行文件中,运行时它会直接到该路径查找库,避免了使用LD_LIBRARY_PATH环境变量查找。app

连接选项和路径

现代链接器在处理动态库时将连接时路径(Link-time path)和运行时路径(Run-time path)分开,用户能够经过-L指定链接时库的路径,经过-R(或-rpath)指定程序运行时库的路径,大大提升了库应用的灵活性。好比咱们作嵌入式移植时#arm-linux-gcc $(CFLAGS) –o target –L/work/lib/zlib/ -llibz-1.2.3 (work/lib/zlib下是交叉编译好的zlib库),将target编译好后咱们只要把zlib库拷贝到开发板的系统默认路径下便可。或者经过-rpath(或-R )、LD_LIBRARY_PATH指定查找路径。ui

连接器ld的选项有 -L,-rpath 和 -rpath-link,看了下 man ld,大体是这个意思:this

-L: “连接”的时候,去找的目录,也就是全部的 -lFOO 选项里的库,都会先从 -L 指定的目录去找,而后是默认的地方。编译时的-L选项并不影响环境变量LD_LIBRARY_PATH,-L只是指定了程序编译链接时库的路径,并不影响程序执行时库的路径,系统仍是会到默认路径下查找该程序所须要的库,若是找不到,仍是会报错,相似cannot open shared object file。spa

-rpath-link:这个也是用于“连接”的时候的,例如你显示指定的须要 FOO.so,可是 FOO.so 自己是须要 BAR.so 的,后者你并无指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。.net

-rpath: “运行”的时候,去找的目录。运行的时候,要找 .so 文件,会从这个选项里指定的地方去找。对于交叉编译,交叉编译连接器需已经配置 --with-sysroot 选项才能起做用。也就是说,-rpath指定的路径会被记录在生成的可执行程序中,用于运行时查找须要加载的动态库。-rpath-link 则只用于连接时查找。调试

连接搜索顺序

直接man ld。The linker uses the following search paths to locate required shared libraries:code

1. Any directories specified by -rpath-link options. 2. Any directories specified by -rpath options. The difference between -rpath and -rpath-link is that directories specified by -rpath options are included in the executable and used at runtime, whereas the -rpath-link option is only effective at link time. Searching -rpath in this way is only supported by native linkers and cross linkers which have been configured with the --with-sysroot option. 3. On an ELF system, for native linkers, if the -rpath and -rpath-link options were not used, search the contents of the environment variable "LD_RUN_PATH". 4. On SunOS, if the -rpath option was not used, search any directories specified using -L options. 5. For a native linker, the search the contents of the environment variable "LD_LIBRARY_PATH". 6. For a native ELF linker, the directories in "DT_RUNPATH" or "DT_RPATH" of a shared library are searched for shared libraries needed by it. The "DT_RPATH" entries are ignored if "DT_RUNPATH" entries exist. 7. The default directories, normally /lib and /usr/lib. 8. For a native linker on an ELF system, if the file /etc/ld.so.conf exists, the list of directories found in that file. If the required shared library is not found, the linker will issue a warning and continue with the link. 

gcc和连接选项的使用

在gcc中使用ld连接选项时,须要在选项前面加上前缀-Wl(是字母l,不是1,我曾屡次弄错),以区别不是编译器的选项。orm

if the linker is being invoked indirectly, via a compiler driver (e.g. gcc) then all the linker command line options should be prefixed by -Wl, (or whatever is appropriate for the particular compiler driver) like this:

<!-- lang: shell --> gcc -Wl,--start-group foo.o bar.o -Wl,--end-group 

This is important, because otherwise the compiler driver program may silently drop the linker options, resulting in a bad link.

相关文章
相关标签/搜索