動態庫的鏈接和鏈接選項-L,-rpath-link,-rpath


  有時候在閱讀開源的庫的源碼時,可能會需要寫個demo進行調試分析,這樣會更直觀。我們會需要去鏈接經過源碼編譯出來的動態庫,而這個動態庫一般都是沒有make install的,也就是庫未安裝到系統默認搜索路徑,在鏈接的時候會在makefile里面指定庫的鏈接搜索路徑:-Lpath -lmylib,編譯順利通過,但是運行的時候提示找不到這個庫,又不想去修改系統動態庫搜索路徑,這個時候:-Wl,-rpath就起作用了。

  用法:

gcc demo.c -o demo -Lsopath -lmyso -Wl,-rpath=sopath

  其中 sopath為動態庫搜索路徑,libmyso.so為動態庫。-L -l都是很熟悉的鏈接選項了,-Wl,-rpath通過man gcc

 -Wl,option
           Pass option as an option to the linker.  If option contains commas, it is split into multiple options at the commas.  You can use this syntax to pass an argument to the
           option.  For example, -Wl,-Map,output.map passes -Map output.map to the linker.  When using the GNU linker, you can also get the same effect with -Wl,-Map=output.map.

  -Wl選項:傳遞的option作為連接器的一個option。多個option以逗號分隔。

  也就是說-Wl為gcc的選項,但是rpath是ld的選項,繼續man ld:

       -rpath=dir
           Add a directory to the runtime library search path.  This is used when linking an ELF executable with shared objects.  All -rpath arguments are concatenated and passed to
           the runtime linker, which uses them to locate shared objects at runtime.  The -rpath option is also used when locating shared objects which are needed by shared objects
           explicitly included in the link; see the description of the -rpath-link option.  If -rpath is not used when linking an ELF executable, the contents of the environment
           variable "LD_RUN_PATH" will be used if it is defined.

           The -rpath option may also be used on SunOS.  By default, on SunOS, the linker will form a runtime search patch out of all the -L options it is given.  If a -rpath option is
           used, the runtime search path will be formed exclusively using the -rpath options, ignoring the -L options.  This can be useful when using gcc, which adds many -L options
           which may be on NFS mounted file systems.

           For compatibility with other ELF linkers, if the -R option is followed by a directory name, rather than a file name, it is treated as the -rpath option.

   rpath指定一個運行動時態庫搜索路徑,另一種指定runtime library search path的方法是環境變量LD_RUN_PATH,這種方法的缺點是會影響其他程序。

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

更詳細的介紹:https://my.oschina.net/shelllife/blog/115958

鏈接動態庫

如何程序在連接時使用了共享庫,就必須在運行的時候能夠找到共享庫的位置。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》)。

不過LD_LIBRARY_PATH的設定作用是全局的,過多的使用可能會影響到其他應用程序的運行,所以多用在調試。(LD_LIBRARY_PATH的缺陷和使用准則,可以參考《Why LD_LIBRARY_PATH is bad》 )。通常情況下推薦還是使用gcc的-R或-rpath選項來在編譯時就指定庫的查找路徑,並且該庫的路徑信息保存在可執行文件中,運行時它會直接到該路徑查找庫,避免了使用LD_LIBRARY_PATH環境變量查找。

鏈接選項和路徑

現代連接器在處理動態庫時將鏈接時路徑(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指定查找路徑。

鏈接器ld的選項有 -L,-rpath 和 -rpath-link,看了下 man ld,大致是這個意思:

-L: “鏈接”的時候,去找的目錄,也就是所有的 -lFOO 選項里的庫,都會先從 -L 指定的目錄去找,然后是默認的地方。編譯時的-L選項並不影響環境變量LD_LIBRARY_PATH,-L只是指定了程序編譯連接時庫的路徑,並不影響程序執行時庫的路徑,系統還是會到默認路徑下查找該程序所需要的庫,如果找不到,還是會報錯,類似cannot open shared object file。

-rpath-link:這個也是用於“鏈接”的時候的,例如你顯示指定的需要 FOO.so,但是 FOO.so 本身是需要 BAR.so 的,后者你並沒有指定,而是 FOO.so 引用到它,這個時候,會先從 -rpath-link 給的路徑里找。

-rpath: “運行”的時候,去找的目錄。運行的時候,要找 .so 文件,會從這個選項里指定的地方去找。對於交叉編譯,交叉編譯鏈接器需已經配置 --with-sysroot 選項才能起作用。也就是說,-rpath指定的路徑會被記錄在生成的可執行程序中,用於運行時查找需要加載的動態庫。-rpath-link 則只用於鏈接時查找。

鏈接搜索順序

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

       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,我曾多次弄錯),以區別不是編譯器的選項。

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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM