動態庫的連接和連接選項-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.

相關文章
相關標籤/搜索