[Linux] 在 gcc 中使用 rpath/rpath-link 指定 shared library 搜尋路徑

[Linux] 在 gcc 中使用 rpath/rpath-link 指定 shared library 搜尋路徑

專案裡用到一個 C 的 shared library,姑且稱它為 T.so 好了,

這個 T.so 用到了 lib7zip 和 p7zip 的 shared library,

因此要載入 T.so 的話有點麻煩,得先把 lib7zip 和 p7zip 的目錄都先加到 LD_LIBRARY_PATH,

把執行檔叫起來,這樣執行檔去載入 T.so 的話才不會出現找不到 shared library 的錯誤…

 

老實說上面這樣很麻煩,不過我們也就一直先暫且這樣,

但今天我在加一個新功能時,發現得把 T.so 再拆出一個 L.so,這下事情更麻煩了,

要用 T.so 的話,除了 lib7zip/p7zip 以外,還得把 L.so 的目錄也加到 LD_LIBRARY_PATH,

這也就算了,假設這麼做的話,別人呼叫我們的程式還得先設定 LD_LIBRARY_PATH,

這是不可能被接受的,太難用了… Orz

 

找了一下,幸好找到了 gcc 的 linker/loader 選項,可以指定要尋找 shared library 的目錄位置~

首先是在編譯期間 (link-time),如果在編譯 A 的時候會需要 B.so,

那可以加 -rpath-link 的選項指定 B.so 的目錄,例如:

Worker: Worker.cpp libworker.so
$(CC) $(CPPFLAGS) -Wl,-rpath-link=. -o $@ $^

 

注意在 gcc 裡面,-rpath-link 是要交給 linker 用的選項,因此要先加上 -Wl 選項,

gcc 才知道這是要給 linker 用的,不然 gcc 會抱怨不認識 -rpath-link 這個選項~

不過用 -Wl 這個選項有些地方要注意,它是用逗號 “,” 來代表空白,

也就是說 -Wl,-rpath-link=abc 在交給 linker 之後,linker 會用 -rpath-link=abc 來執行,

因此也可以寫成 -Wl,-rpath-link,abc,因為這樣 linker 會用 -rpath-link abc 來執行~

 

另外一個選項是 -rpath,用來指定執行期間 (run-time) 搜尋 shared library 的目錄~

在 -rpath-link 裡指定 “.” (當前目錄) 還算正常,因為我們可以控制現在的工作目錄,

但是在 -rpath 裡指定 “.” 就有點奇怪,因為你不知道別人會在哪個目錄執行你的程式…

但是很有可能你很確定某某 shared library 一定會放在執行檔的某某相對位置,

這時候我們可以用 $ORIGIN 這個字來代表執行檔的路徑~

(不是編譯時執行檔的所在位置,而是執行時執行檔的所在位置)

 

舉例來說,我們的 Worker 執行檔在執行時,會需要找到 libworker.so 和 lib7zip 和 p7zip,

而我知道 libworker.so 會跟 Worker 放在一起,

lib7zip.so 會在跟 Worker 目錄同層的 lib 目錄,7z.so 會在跟 Worker 目錄同層的 p7zip 目錄,

這時我就可以用 -rpath 選項同時指定 $ORIGIN, $ORIGIN/../lib, $ORIGIN/../p7zip 三個目錄~

Worker: Worker.cpp libworker.so
$(CC) $(CPPFLAGS) -Wl,-rpath-link=. \
-Wl,-rpath='$$ORIGIN:$$ORIGIN/../lib:$$ORIGIN/../p7zip' -o $@ $^

 

上面的寫法有兩點要注意,第一個是因為 Makefile 裡的 $ 會被當成 Makefile 的變數,

因此我們要用 $$ 來代表一個 $~

而不幸的 $ 同時也是代表 Linux shell 的變數,因此我們得用單引號 ” 括起來,

免得 shell 幫我們把 $ORIGIN 替換掉了~

 

使用了 -rpath-link 和 -rpath 選項之後,

就可以比較輕鬆地處理 shared library 之間的 dependency 問題了,

只要確保程式會放在特定的目錄結構下的話 (不用寫死絕對路徑,只要是相對路徑即可),

就可以用這一招來解決囉~^^/

 

stackoverflow: Difference between relative path and using $ORIGIN as RPATH

ld: Command Line Options

Re: linking with -Wl,-rpath and $(prefix)

(本頁面已被瀏覽過 14,048 次)

2 thoughts on “[Linux] 在 gcc 中使用 rpath/rpath-link 指定 shared library 搜尋路徑

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料