怎么用手機(jī)做網(wǎng)站編輯推廣網(wǎng)站要注意什么
Linux——靜態(tài)庫(kù)
- 靜態(tài)庫(kù)
- 分析一下
- ar指令生成靜態(tài)庫(kù)
- 靜態(tài)庫(kù)的使用
- 第三方庫(kù)
- 優(yōu)化一下
- gcc -I(大寫(xiě)的i) -L -l(小寫(xiě)的l),頭文件搜索路徑,庫(kù)文件搜索路徑,連接庫(kù)
今天我們來(lái)學(xué)習(xí)靜態(tài)庫(kù)的基本知識(shí)。
靜態(tài)庫(kù)
在了解靜態(tài)庫(kù)之前,我們首先來(lái)回憶一下gcc的三個(gè)編譯選項(xiàng):
gcc -E 生成.i 文件 預(yù)處理
gcc -S 生成.s文件 編譯
gcc -c 生成.o 文件 匯編
如果大家有點(diǎn)陌生,大家可以點(diǎn)擊這里復(fù)習(xí)一下:
https://blog.csdn.net/qq_67693066/article/details/132868367
生成.o文件之后,我們就要進(jìn)行連接,讓我們的程序跑起來(lái)。我們今天的主要的部分主要集中在.o文件上。
我們首先模擬一個(gè)簡(jiǎn)單的加減場(chǎng)景,編寫(xiě)一個(gè)程序完成加減,包含完整的頭文件和.c文件:
其中我們的Test.c是程序運(yùn)行的入口,Add和Sub的頭文件和.c文件為我們的Test.c服務(wù)。
然后我們編寫(xiě)Makefile:
這里注意一下 %.o : %c這個(gè)叫做模式規(guī)則,這段代碼簡(jiǎn)單來(lái)說(shuō)就是將后綴為.c的文件依次生成.o文件,我們將Test.c入口編寫(xiě)好:
之后make一下:
看到我們已經(jīng)成功生成了Test可執(zhí)行文件,我們運(yùn)行一下來(lái)看看:
分析一下
我們回到Makefile:
我們知道Test這個(gè)執(zhí)行文件依賴于Add.o,Sub.o 和 Test.c生成,我們?cè)賮?lái)想想,Test.c是我們人為寫(xiě)的程序的入口,意思就是,如果別人寫(xiě)一個(gè)程序的入口,只要他可以拿到Add.o 和Sub.o 就可以運(yùn)行程序。那為什么我不把Add.o和Sub.o打包?如果別人要用這個(gè)程序,我直接把這個(gè)包發(fā)給他就可以用了,這不是很方便嘛。這個(gè)包我們稱為靜態(tài)庫(kù),這個(gè)頭文件,就是庫(kù)的使用說(shuō)明書(shū)。
靜態(tài)庫(kù)(Static Library)是一種包含預(yù)編譯目標(biāo)文件的集合的歸檔文件,它在鏈接時(shí)被整體復(fù)制到可執(zhí)行文件中。靜態(tài)庫(kù)的目的是為了提供代碼重用和模塊化,使得在編譯時(shí)將所有需要的代碼和數(shù)據(jù)都鏈接到最終的可執(zhí)行文件中。
靜態(tài)庫(kù)的文件通常具有 .a(在Unix/Linux系統(tǒng)中)或 .lib(在Windows系統(tǒng)中)的文件擴(kuò)展名。它包含了一組預(yù)編譯的目標(biāo)文件(通常是 .o 文件),這些目標(biāo)文件是通過(guò)編譯源代碼而生成的。
主要優(yōu)點(diǎn)和特點(diǎn)包括:
獨(dú)立性: 靜態(tài)庫(kù)包含所有代碼和數(shù)據(jù),因此它是獨(dú)立于其他庫(kù)的,不依賴于運(yùn)行時(shí)環(huán)境。
鏈接時(shí)靜態(tài)綁定: 靜態(tài)庫(kù)在鏈接時(shí)會(huì)被完全復(fù)制到可執(zhí)行文件中,因此在運(yùn)行時(shí)不需要外部的庫(kù)文件。
性能: 由于在鏈接時(shí)已經(jīng)將代碼和數(shù)據(jù)整合到可執(zhí)行文件中,因此執(zhí)行時(shí)的性能可能會(huì)更好。
ar指令生成靜態(tài)庫(kù)
我們知道了原理之后,我們可以用指令生成靜態(tài)庫(kù),我們?cè)贛akefile中:
靜態(tài)庫(kù)的使用
我們現(xiàn)在有了靜態(tài)庫(kù),我們現(xiàn)在重新建一個(gè)文件,來(lái)模擬其他程序員拿到庫(kù)的情況。
我們新建一個(gè)Test_2的文件夾,把main函數(shù)寫(xiě)好:
如果我們此時(shí)直接編譯:
這個(gè)時(shí)候會(huì)報(bào)錯(cuò),說(shuō)沒(méi)有頭文件,此時(shí)我們要把頭文件搬到這個(gè)目錄下,順便把靜態(tài)庫(kù)也搬過(guò)來(lái):
這個(gè)時(shí)候我們?cè)賮?lái)編譯:
此時(shí)沒(méi)有報(bào)沒(méi)有頭文件的錯(cuò)誤了,但是編譯器還是不知道怎么做,報(bào)了鏈接錯(cuò)誤。但是我們不是已經(jīng)把庫(kù)拷貝過(guò)來(lái)了嗎?按理來(lái)說(shuō)應(yīng)該可以呀?
第三方庫(kù)
其實(shí)我們自己寫(xiě)的庫(kù)為第三方庫(kù),編譯器一般不認(rèn)識(shí),如果我們要運(yùn)行程序,我們需要告訴編譯器到哪里去連接這個(gè)第三方庫(kù):
gcc Test.c -L(后面跟這個(gè)第三方庫(kù)的路徑) -l(第三方庫(kù)的名稱)
這里注意下,這個(gè)第三方庫(kù)的名稱是去掉前綴和后綴的,比如libmymath.a去掉前綴lib去掉后綴.a,這個(gè)庫(kù)的名字應(yīng)該為mymath。
我們來(lái)試試:
優(yōu)化一下
剛剛我們執(zhí)行程序時(shí),還要把我們的頭文件一個(gè)一個(gè)搬下來(lái),這個(gè)屬實(shí)不咋方便,我們可以優(yōu)化一下:
我們打開(kāi)Makefile:
我們把頭文件也打包一下,我們測(cè)試一下:
我們有了庫(kù),我們可以壓縮這個(gè)庫(kù):
這個(gè)時(shí)候,mymath_lib.tgz就可以拿到網(wǎng)上讓別人下載了。不過(guò),假設(shè)我是其他的程序員,拿到了其他人寫(xiě)的庫(kù),這個(gè)時(shí)候我該如何使用這個(gè)庫(kù)呢?
我們有一個(gè)include目錄,這里是專門(mén)存放頭文件的:
還有一個(gè)lib64,是專門(mén)存放動(dòng)靜態(tài)庫(kù)的:
我們要做的其實(shí)很簡(jiǎn)單,就是把對(duì)應(yīng)的頭文件和庫(kù)安裝到相應(yīng)的目錄下就可以了。這個(gè)過(guò)程我們稱為安裝開(kāi)發(fā)環(huán)境。
gcc -I(大寫(xiě)的i) -L -l(小寫(xiě)的l),頭文件搜索路徑,庫(kù)文件搜索路徑,連接庫(kù)
我們gcc一般搜索頭文件,會(huì)從全局的/usr/include搜索,然后會(huì)從當(dāng)前路徑尋找。其實(shí)我們可以帶 -I(大寫(xiě)的i),建議編譯器也從這里找頭文件: