建構系統、函式庫與相依性

共享函式庫搜尋路徑

當你的程式在執行期需要 libutil.so 時,動態連結器得真的在磁碟某處找到那個檔案。共享函式庫搜尋路徑就是它為了找到它而依序查看的目錄清單——像一位圖書館員,按固定順序檢查一組書架,直到那本書出現為止。若函式庫不在任何一個書架上,程式就無法啟動。

在 Linux 上,動態連結器依序查詢幾個來源:烤進可執行檔本身的任何目錄(rpath/runpath),接著是 LD_LIBRARY_PATH 環境變數所列的目錄,再來是一份標準系統目錄的快取清單(由 ldconfig 從 /etc/ld.so.conf 建出,涵蓋 /usr/lib 與 /lib 等地方)。Windows 與 macOS 有各自的搜尋規則,但概念相同:一個有明確順序的查找地點集合。請注意這與建構期的函式庫路徑(-L 旗標)是分開的:-L 告訴連結器在建構時去哪找函式庫,卻對程式之後執行時找到它毫無幫助。

為什麼重要:「在我機器上行、在你機器上不行」這類函式庫問題裡,有極大一部分其實是搜尋路徑問題——函式庫存在,只是不在連結器會檢查的書架上。知道順序,你就能有意地修正它:把函式庫裝到標準目錄並執行 ldconfig、為快速測試設定 LD_LIBRARY_PATH,或把 rpath 烤進二進位檔。LD_LIBRARY_PATH 尤其適合做實驗,但作為永久解法很糟,而隨意覆寫它甚至可能成為安全風險。

程式在執行期找不到它的函式庫: $ ./app error: libutil.so: cannot open shared object file 測試時的快速修法: $ LD_LIBRARY_PATH=. ./app # 也到目前目錄找

搜尋路徑決定動態連結器去哪找;設定 LD_LIBRARY_PATH 會把一個目錄加進那份清單。

執行期搜尋路徑與建構期的 -L 函式庫路徑不是同一件事:-L 只在建構時幫助連結器,而執行期搜尋路徑(rpath、LD_LIBRARY_PATH、ldconfig 快取)才是程式真正執行時用來找到函式庫的依據。

又称
LD_LIBRARY_PATHruntime search pathrpath執行期搜尋路徑