Linux gcc鏈接動態庫出錯:LIBRARY_PATH和LD_LIBRARY_PATH的區別


昨天在自己的CentOs7.1上寫makefile的時候,發現在一個C程序在編譯並鏈接一個已生成好的lib動態庫的時候出錯。鏈接命令大概是這樣的:

[root@typecodes tcpmsg]# gcc -o hello main.c -lmyhello /usr/bin/ld: cannot find -lmyhello collect2: error: ld returned 1 exit status 

1 gcc鏈接動態庫時的搜索路徑

自以為在當前工程中設置好了環境變量 LD_LIBRARY_PATH 包含了工程中的lib庫路徑,並且還在 /etc/ld.so.conf/apphome.conf 中配置了lib庫的路徑。那么在調用動態庫的時候,gcc就應該能自動去搜索該目錄。

很遺憾ld鏈接器報了如上的錯誤,但是如果在上面的gcc命令中添加上 -L /root/gcc_test/tcp_msg/lib/ 參數,即明確動態庫的絕對路徑,是能夠鏈接成功的。

2 Google上查找 /usr/bin/ld: cannot find -l* 的出錯原因

gg了很久gcc ld鏈接動態庫出錯的原因,結果還是沒找到理想的答案。后來猜想是不是在CentOs7中LD_LIBRARY_PATH不起作用的緣故,但是也不應該,因為自己用的GCC(version 4.8.3)跟操作系統沒關系。於是重新搜索了gcc LD_LIBRARY_PATH的作用,竟然發現gcc在編譯鏈接時鏈接的動態庫跟 LIBRARY_PATH 有關而跟 LD_LIBRARY_PATH 沒關系!

3 關於Linux gcc中的 LIBRARY_PATH 和 LD_LIBRARY_PATH 參數說明

下面摘取了兩篇較權威的說明資料:

1、 GNU 上關於LIBRARY_PATH的說明:

LIBRARY_PATH
The value of LIBRARY_PATH is a colon-separated list of directories, much like PATH. When configured as a native compiler, GCC tries the directories thus specified when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX. Linking using GCC also uses these directories when searching for ordinary libraries for the -l option (but directories specified with -L come first). 

2、 man7 上關於LD_LIBRARY_PATH的說明:

LD_LIBRARY_PATH
A colon-separated list of directories in which to search for ELF libraries at execution-time. Similar to the PATH environment variable. Ignored in set-user-ID and set-group-ID programs. 

后面發現 StackOverflow 上關於 LIBRARY_PATH 和 LD_LIBRARY_PATH 的解釋更直白:

LIBRARY_PATH is used by gcc before compilation to search for directories containing libraries that need to be linked to your program. LD_LIBRARY_PATH is used by your program to search for directories containing the libraries after it has been successfully compiled and linked. EDIT: As pointed below, your libraries can be static or shared. If it is static then the code is copied over into your program and you don't need to search for the library after your program is compiled and linked. If your library is shared then it needs to be dynamically linked to your program and that's when LD_LIBRARY_PATH comes into play. 

通過這三篇資料的說明,很快明白了 LIBRARY_PATH 和 LD_LIBRARY_PATH 的作用。於是,自己在項目配置文件中添加 export LIBRARY_PATH=${LIBRARY_PATH}:${APPHOME}/lib 。接着將這個配置文件加載到CentOs的環境變量中,這樣就在gcc編譯不用加 -L 參數生成目標文件CommuTcp了。

4 總結

關於 LIBRARY_PATH 和 LD_LIBRARY_PATH 的關系,這里自己再總結一下。

4.1 Linux gcc編譯鏈接時的動態庫搜索路徑

GCC編譯、鏈接生成可執行文件時,動態庫的搜索路徑順序如下(注意不會遞歸性地在其子目錄下搜索):

1、gcc編譯、鏈接命令中的-L選項; 2、gcc的環境變量的LIBRARY_PATH(多個路徑用冒號分割); 3、gcc默認動態庫目錄:/lib:/usr/lib:usr/lib64:/usr/local/lib。 

4.2 執行二進制文件時的動態庫搜索路徑

鏈接生成二進制可執行文件后,在運行程序加載動態庫文件時,搜索的路徑順序如下:

1、編譯目標代碼時指定的動態庫搜索路徑:用選項-Wl,rpath和include指定的動態庫的搜索路徑,比如gcc -Wl,-rpath,include -L. -ldltest hello.c,在執行文件時會搜索路徑`./include`; 2、環境變量LD_LIBRARY_PATH(多個路徑用冒號分割); 3、在 /etc/ld.so.conf.d/ 目錄下的配置文件指定的動態庫絕對路徑(通過ldconfig生效,一般是非root用戶時使用); 4、gcc默認動態庫目錄:/lib:/usr/lib:usr/lib64:/usr/local/lib等。 

其中,Linux GCC默認的動態庫搜索路徑可以通過 ld --verbose 命令查看:

[root@typecodes tcpmsg]# ld --verbose ............ SEARCH_DIR("/usr/x86_64-redhat-linux/lib64"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); ##### 64位系統 SEARCH_DIR("/usr/x86_64-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); 

 

轉自:http://typecodes.com/cseries/gcclderrlibrarypath.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM