Linux 编译运行查找头文件和库的顺序
linux中在使用gcc進(jìn)行編譯時(shí),可能會(huì)出現(xiàn)找不到相應(yīng)庫或頭文件的情況,往往讓人十分頭疼。因此,此文描述了庫和頭文件的查找順序和一些注意事項(xiàng),希望能幫助大家在出錯(cuò)時(shí)能夠快速定位和解決。
頭文件
gcc在編譯時(shí)按照如下順序?qū)ふ宜枰念^文件:
1.先搜索當(dāng)前目錄(?這里注意,只有用#include "headfile.h"時(shí)才會(huì)搜索當(dāng)前目錄?)
2.接著搜索-I指定的目錄
3.然后找gcc的環(huán)境變量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
4.再找內(nèi)定目錄:?/usr/include,?/usr/local/include
5.最后找gcc的一系列自帶目錄,如:
庫文件
gcc在編譯時(shí)按照如下順序?qū)ふ宜枰膸煳募?#xff1a;
1.gcc會(huì)去找-L指定的目錄
2.再找gcc的環(huán)境變量LIBRARY_PATH
3.再找內(nèi)定目錄
- /lib和/lib64
- /usr/lib 和/usr/lib64
- /usr/local/lib和/usr/local/lib64
這是當(dāng)初compile gcc時(shí)寫在程序內(nèi)的
這里有兩個(gè)問題:
1.默認(rèn)情況下,gcc編譯時(shí)只會(huì)查找相應(yīng)的頭文件,而不會(huì)連接具體的lib。也就是說只要include設(shè)置完全,就可以編譯通過。它沒有進(jìn)一步檢查include中的類和函數(shù)有沒有實(shí)現(xiàn),而是在運(yùn)行時(shí)才開始查找。所以就會(huì)經(jīng)常發(fā)生編譯可以通過,但運(yùn)行時(shí)卻無法運(yùn)行,因?yàn)樵谶\(yùn)行時(shí)它找不到相關(guān)類或者函數(shù)的實(shí)現(xiàn)。
這時(shí),使用-Wl,--no-undefined參數(shù),如果使用了include文件,連接器卻找不到相應(yīng)的實(shí)現(xiàn),就會(huì)產(chǎn)生錯(cuò)誤提示。
2.編譯時(shí)默認(rèn)不查找當(dāng)前目錄,需要使用-L ./指定,例如
運(yùn)行時(shí)動(dòng)態(tài)庫的搜索路徑
動(dòng)態(tài)庫的搜索路徑搜索的先后順序是:
1.編譯目標(biāo)代碼時(shí)指定的動(dòng)態(tài)庫搜索路徑;這是通過gcc的參數(shù)-Wl,-rpath=指定。當(dāng)指定多個(gè)動(dòng)態(tài)庫搜索路徑時(shí),路徑之間用冒號(hào):分隔
2.環(huán)境變量LD_LIBRARY_PATH指定的動(dòng)態(tài)庫搜索路徑
3.配置文件/etc/ld.so.conf中指定的動(dòng)態(tài)庫搜索路徑
4.默認(rèn)的動(dòng)態(tài)庫搜索路徑/lib,?/usr/lib
注意:
1.動(dòng)態(tài)庫搜尋路徑并不包括當(dāng)前目錄,所以當(dāng)即使可執(zhí)行文件和其所需的so文件在同一文件夾,也會(huì)出現(xiàn)找不到問題
2.一般不推薦直接修改環(huán)境變量,而是修改/etc/ld.so.conf,將相應(yīng)的路徑添加上,然后ldconfig一下就好
3.ldconfig做的這些東西都與運(yùn)行程序時(shí)有關(guān),跟編譯時(shí)一點(diǎn)關(guān)系都沒有,編譯的時(shí)候還是該加-L就得加,不要混淆了
4.往/lib和/usr/lib里面lib,是不用修改/etc/ld.so.conf的,但是完了之后要調(diào)一下ldconfig(很重要),不然這個(gè)lib會(huì)找不到。而往其他目錄加lib,需要修改/etc/ld.so.conf,并且要ldconfig一下。
5.如果確實(shí)需要改環(huán)境變量,則有以下幾種情況:
- 臨時(shí)修改(關(guān)閉shell后失效):若是權(quán)限不夠(無法更改/etc/ld.so.conf)或只是想臨時(shí)改一下環(huán)境變量用于測(cè)試,則可以使用export,就是export一個(gè)全局變量LD_LIBRARY_PATH,然后運(yùn)行程序的時(shí)候就會(huì)去這個(gè)目錄中找lib。如:命令行執(zhí)行:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/abc/lib
一般來講這只是一種臨時(shí)的解決方案,在沒有權(quán)限或臨時(shí)需要的時(shí)候使用。
-
修改作用于當(dāng)前用戶:在.bashrc中設(shè)置或者在./bash_profile設(shè)置,這對(duì)當(dāng)前用戶生效。記得source ~/.bashrc或source ~/.bash_profile
-
修改作用于所有用戶:在/etc/profile中設(shè)置或在/etc/profile.d/中創(chuàng)建一個(gè)自定義的shell(**.sh)腳本,一般推薦使用后者。原因如下:
It's NOT a good idea to change this file unless you know what you are doing. It's much better to create a custom.sh shell script in?/etc/profile.d/?to make custom changes to your environment, as this will prevent the need for merging in future updates.
翻譯即:除非您知道自己在做什么,否則更改此文件不是一個(gè)好主意。 最好在/etc/profile.d/中創(chuàng)建一個(gè)自定義的shell(**.sh)腳本,以對(duì)您的環(huán)境進(jìn)行自定義更改,因?yàn)檫@樣可以避免在將來的更新中合并。
- 最后是關(guān)于環(huán)境變量的寫法:
如:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/abc/lib
或者這樣寫:export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/home/user/abc/lib"
要用:隔開,注意要加上$LD_LIBRARY_PATH,避免之前存在的路徑失效,在前則先搜索,在后則后搜索
?
總結(jié)
以上是生活随笔為你收集整理的Linux 编译运行查找头文件和库的顺序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 存储层mysql总结
- 下一篇: Linux下内存问题检测神器 valgr