昨天在本身的CentOs7.1上寫makefile的時候,發如今一個C程序在編譯並連接一個已生成好的lib動態庫的時候出錯。連接命令大概是這樣的:html
[root@typecodes tcpmsg]# gcc -o hello main.c -lmyhello /usr/bin/ld: cannot find -lmyhello collect2: error: ld returned 1 exit status
自覺得在當前工程中設置好了環境變量 LD_LIBRARY_PATH
包含了工程中的lib庫路徑,而且還在 /etc/ld.so.conf/apphome.conf
中配置了lib庫的路徑。那麼在調用動態庫的時候,gcc就應該能自動去搜索該目錄。linux
很遺憾ld連接器報瞭如上的錯誤,可是若是在上面的gcc命令中添加上 -L /root/gcc_test/tcp_msg/lib/
參數,即明確動態庫的絕對路徑,是可以連接成功的。app
gg了好久gcc ld連接動態庫出錯的緣由,結果仍是沒找到理想的答案。後來猜測是否是在CentOs7中LD_LIBRARY_PATH不起做用的緣故,可是也不該該,由於本身用的GCC(version 4.8.3)跟操做系統不要緊。因而從新搜索了gcc LD_LIBRARY_PATH的做用,居然發現gcc在編譯連接時連接的動態庫跟 LIBRARY_PATH
有關而跟 LD_LIBRARY_PATH
不要緊!less
3 關於Linux gcc中的 LIBRARY_PATH
和 LD_LIBRARY_PATH
參數說明tcp
下面摘取了兩篇較權威的說明資料:ui
一、 GNU 上關於LIBRARY_PATH的說明:spa
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).
二、 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
的解釋更直白:code
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了。regexp
關於 LIBRARY_PATH
和 LD_LIBRARY_PATH
的關係,這裏本身再總結一下。
4.1 Linux gcc編譯連接時的動態庫搜索路徑
GCC編譯、連接生成可執行文件時,動態庫的搜索路徑順序以下(注意不會遞歸性地在其子目錄下搜索):
一、gcc編譯、連接命令中的-L選項; 二、gcc的環境變量的LIBRARY_PATH(多個路徑用冒號分割); 三、gcc默認動態庫目錄:/lib:/usr/lib:usr/lib64:/usr/local/lib。
4.2 執行二進制文件時的動態庫搜索路徑
連接生成二進制可執行文件後,在運行程序加載動態庫文件時,搜索的路徑順序以下:
一、編譯目標代碼時指定的動態庫搜索路徑:用選項-Wl,rpath和include指定的動態庫的搜索路徑,好比gcc -Wl,-rpath,include -L. -ldltest hello.c,在執行文件時會搜索路徑`./include`; 二、環境變量LD_LIBRARY_PATH(多個路徑用冒號分割); 三、在 /etc/ld.so.conf.d/ 目錄下的配置文件指定的動態庫絕對路徑(經過ldconfig生效,通常是非root用戶時使用); 四、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");