一、linux 下 動態庫搜索路徑優先順序
- 編譯目標代碼時指定的動態庫搜索路徑;
- 環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑;
- 配置文件/etc/ld.so.conf中指定的動態庫搜索路徑;配置後要運行 ldconfig命令才能生效
- 默認的動態庫搜索路徑/lib;
- 默認的動態庫搜索路徑/usr/lib;
1是最優先的, 使用gcc -Wl,--rpath -Wl,${LIB_DIR1} ./app 指定了搜索路徑
注:當elf 可執行程序運行時,會在LD_LIBRARY_PATH 動態庫的查找路徑 查找,當找到A庫時加載,如果其他的文件中存在相同的庫函數,若兩個庫函數不一致,則有可能導致出現undefined symbol。
解決辦法: 排查LD_LIBRARY_PATH 的值下的文件中是否存在相同的庫文件。
二、linux Makefile
- -Xlinker --unresolved-symbols=ignore-in-shared-libs 編譯動態鏈接庫的時候最好加上 來檢查一下。這樣如果是自己的疏忽在 .c 源文件裏面忘記的 某函數的定義,編譯的時候就可以提示錯誤了
- -WL,-rpath= 指定編譯的可執行文件首先搜尋的庫依賴的文件路徑
- -Wl,--version-script=Makefile.symbol 編譯動態鏈接庫時 選擇導出的符號,未導出的符號,運行時將會報undefined symbol
- -Wl,-soname -Wl選項告訴編譯器將後面的參數傳遞給鏈接器。 -soname則指定了動態庫的soname(簡單共享名,Short for shared object name) 有一個程序ap1,以及一個庫libtest.so.1
比如 ,ap1啓動的時候需要libxxx.so.1
如果鏈接的時候直接把libxxx.so.1傳給了ap1,那麼將來庫升級爲libtest.so.2的時候,ap1仍然只能使用 libxxx.so.1的代碼,並不能得到升級的好處。而如果指定了soname爲libxxx.so,那麼ap1啓動的時候將查找的就是 libxxx.so,而不是其在被鏈接時實際使用的庫libxxx.so.1這個文件名。