[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
Re: linking with -Wl,-rpath and $(prefix)
2 thoughts on “[Linux] 在 gcc 中使用 rpath/rpath-link 指定 shared library 搜尋路徑”
Thanks for your sharing
You are welcome~