理解 GCC 如何尋找頭文件(編譯期)與庫文件(鏈接期/運行期)是解決「找不到頭文件」「鏈接失敗」「運行時找不到動態庫」的關鍵。本文基於 RedHat/Fedora + GCC 4.5 環境,系統梳理搜尋順序、環境變數、編譯選項與實戰排查技巧。
範例:gcc -iquote /bar/foo -I/usr/include/sys *.c
搜尋順序:
查看實際路徑:gcc -v -E - < /dev/null 2>&1 | grep "include" -A 20
鏈接器(ld)本身無預設路徑,全部由 GCC 透過 `-L`、`-rpath` 等傳遞。
注意:實測 GCC 會自動加入 `/usr/local/lib/`,但這在運行期可能找不到,導致「鏈接通、運行失敗」。
gcc -Wl,-rpath,/usr/local/lib # 等價於 ld -rpath /usr/local/lib
gcc -Wl,-rpath-link,/opt/lib
僅動態鏈接程式涉及,由動態鏈接器(`ld.so`/`ld-linux.so`)處理。
# 查看可執行檔內嵌 rpath
readelf -d a.out | grep -i rpath
# 查看/更新快取
ldconfig -p # 列出所有快取庫
ldconfig -v # 重建快取並顯示過程
sudo ldconfig # 更新快取(需 root)
| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| 編譯錯誤:fatal error: xxx.h | 頭文件路徑缺失 | 加 `-I/path/to/include` 或確認 pkg-config |
| 鏈接錯誤:undefined reference | 庫路徑/庫名稱錯誤 | 加 `-L/path -lname`,確認 .so/.a 存在 |
| 運行錯誤:error while loading shared libraries | 動態庫運行期找不到 | 加 `-Wl,-rpath,/path` 或 `LD_LIBRARY_PATH` 或 `ldconfig` |
| 多版本庫衝突 | 搜尋順序導致載入錯誤版本 | 明確指定 `-rpath`、調整 `ld.so.conf` 優先級 |