静态库的制作和使用
? ? ? ? Linux下的靜態(tài)庫(kù)為lib*.a格式的二進(jìn)制文件(目標(biāo)文件),對(duì)應(yīng)于Windows下的.lib格式的文件。
(1)命名規(guī)則
? ? ? ? lib+庫(kù)名字+ .a?? libMytest.a ,則庫(kù)名字為mytest。下面以具體的代碼為例介紹如何制作靜態(tài)庫(kù)。
//main.c #include <stdio.h> #include "head.h" int main(void) {int sum = add(2, 24);printf("sum = %d\n", sum);return 0; }//head.h #ifndef __HEAD_H_ #define __HEAD_H_ int add(int , int); int sub(int , int); int mul(int , int); int div(int , int); #endif//add.c int add(int a, int b) {int result = a + b;return result; }//div.c int div(int a, int b) {int result = a / b;return result; }//mul.c int mul(int a, int b) {int result = a * b;return result; }//sub.c int sub(int a, int b) {int result = a - b;return result; }? ? ? ? 以上有5段代碼:main.c、head.h、add.c、div.c、mul.c和sub.c。要求將add.c、div.c、mul.c和sub.c制作成庫(kù)文件提供給客服使用,這4個(gè)文件都是關(guān)于頭文件head.h中函數(shù)的詳細(xì)實(shí)現(xiàn),因此為了不想讓客服知道函數(shù)實(shí)現(xiàn)的細(xì)節(jié)和方法,不能將源碼提供給客服,而是以庫(kù)文件(二進(jìn)制文件)的形式提供給客服使用即可。至于如何使用,庫(kù)文件已經(jīng)將函數(shù)接口留在了頭文件head.h中,即4個(gè)函數(shù)聲明。用戶看了頭文件就知道如何使用庫(kù)文件了,即如何使用函數(shù)。因此最后只需要將main.c、head.h和庫(kù)文件給客服即可。(因此,一般庫(kù)文件與相對(duì)應(yīng)的頭文件是同一個(gè)人來(lái)完成的)
? ? ? ? 先強(qiáng)調(diào)一下gcc的一個(gè)使用。-c參數(shù)是用來(lái)生成目標(biāo)文件.o的,但是不鏈接。如: gcc -c zsx.s -o zsx.o? ? gcc -c zsx.c -o zsx.o? ? 對(duì)于上面4個(gè).c文件,若工作目錄中只有這4個(gè).c文件,可以用*.c表示這四個(gè)文件:? gcc -c *.c? ? 則會(huì)生成4個(gè).o文件:add.o? div.o? mul.o和sub.o(在不指出輸出文件名字時(shí),默認(rèn)是將.c文件的.c改為.o)?。?? gcc -c *.c? ?等價(jià)于對(duì)每一個(gè)單獨(dú)的.c文件進(jìn)行預(yù)處理、編譯、匯編后生成各自的 .o文件(檔案庫(kù)文件)。同理,對(duì)于gcc a.c b.c c.c d.c 最后生成一個(gè)a.out文件,其先對(duì)每一個(gè)源文件生成目標(biāo)文件,然后將這些目標(biāo)文件與需要的靜態(tài)庫(kù)文件鏈接形成可執(zhí)行文件,至于需要的動(dòng)態(tài)庫(kù)文件則是在程序運(yùn)行時(shí)才會(huì)加載進(jìn)去。? ? ??
(2)制作靜態(tài)庫(kù)
? ? ? ? 1)生成對(duì)應(yīng)的.o文件? 2)將生成的.o文件打包。 ar rcs + 靜態(tài)庫(kù)的名字(libmytest.a)+ 生成的所有的.o??
? ? ? ??一個(gè)頭文件(head.h,/mnt/hgfs/share/gcc/Calc/include)和四個(gè).c文件(add.c、div.c、mul.c、sub.c, /mnt/hgfs/share/gcc/Calc/src):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?[root@localhost src]# gcc -c *.c
[root@localhost src]# ls
add.c ?add.o ?div.c ?div.o ?mul.c ?mul.o ?sub.c ?sub.o
[root@localhost src]# ar rcs libMytest.a *.o
[root@localhost src]# ls
add.c ?add.o ?div.c ?div.o ?libMytest.a ?mul.c ?mul.o ?sub.c ?sub.o
此時(shí)已經(jīng)生成了靜態(tài)庫(kù)文件libMytest.a,該庫(kù)文件包含了4個(gè)庫(kù)函數(shù)add.o、div.o 、mul.o和sub.o。ar 工具不包含在gcc中,r --> 將文件插入靜態(tài)庫(kù)中;c --> 創(chuàng)建靜態(tài)庫(kù),不管庫(kù)是否存在(存在就不創(chuàng)建);s --> 寫入一個(gè)目標(biāo)文件索引到庫(kù)中,或者更新一個(gè)存在的目標(biāo)文件索引(即方便找到需要的庫(kù)函數(shù))。ar類似于命令,rcs是三個(gè)參數(shù)。
(3)使用靜態(tài)庫(kù)
? ? ? ? 將生成的libMytest.a庫(kù)文件和頭文件head.h發(fā)送給客服,客服就可以根據(jù)頭文件中的接口情況,來(lái)知道庫(kù)文件的功能 (具體怎么實(shí)現(xiàn)的他也不知道),從而客服就可以使用庫(kù)文件來(lái)完成自己的工作了(main.c):
[root@localhost Calc]# gcc -pedantic -pipe -Wall main.c -I include/ -L src/ -lMytest -o zsx? ? 也等價(jià)于:
[root@localhost Calc]# gcc -pedantic -pipe -Wall main.c -I include/ src/libMytest.a -o zsx
[root@localhost Calc]# ./zsx?
sum = 26
分析main.c可以知道,還另外有一個(gè)頭文件stdio.h,其對(duì)應(yīng)的是printf函數(shù)的聲明,其庫(kù)文件是printf函數(shù)實(shí)現(xiàn)的庫(kù)文件,該庫(kù)文件有C提供,它們是標(biāo)準(zhǔn)頭、庫(kù)文件,因此不需要指明路徑和名稱,且該庫(kù)函數(shù)為動(dòng)態(tài)庫(kù)函數(shù),當(dāng)程序在運(yùn)行過(guò)程中需要該庫(kù)函數(shù)時(shí),才會(huì)根據(jù)頭文件找到相應(yīng)的庫(kù)函數(shù)并加載進(jìn)入內(nèi)存空間。而,libMytest.a不一樣,為靜態(tài)庫(kù)文件,因此在載入內(nèi)存之前就已經(jīng)鏈接在了一起成為程序代碼的一部分。注意:main函數(shù)只是用了add函數(shù),因此在鏈接時(shí)只是鏈接了add.o庫(kù)函數(shù),并非鏈接了整個(gè)庫(kù)文件,只需要鏈接使用到的庫(kù)函數(shù)即可。 例如,一個(gè)庫(kù)文件libZsx.a包含了qw.o(其有a( )和b( )兩個(gè)函數(shù)的實(shí)現(xiàn))、qe.o(其有c( )和d( )兩個(gè)函數(shù)的實(shí)現(xiàn))和qr.o(其有e( )和f( )兩個(gè)函數(shù)的實(shí)現(xiàn))。當(dāng)mani函數(shù)只是用到a( )和d( )兩個(gè)函數(shù)時(shí),則最終在鏈接生成可執(zhí)行程序時(shí),只是會(huì)鏈接qw.o和qe.o兩個(gè)庫(kù)函數(shù),即main函數(shù)和這兩個(gè)庫(kù)函數(shù)都在代碼區(qū)。
? ? ? ? 庫(kù)函數(shù)與可執(zhí)行程序只是差最后一步,都具有前面是哪個(gè)階段,且各種規(guī)定都完全一樣,都是二進(jìn)制代碼。
? ? ? ? 調(diào)試通過(guò)之后,加上-O參數(shù),對(duì)代碼進(jìn)行優(yōu)化,可以減小最后可執(zhí)行文件的體積。
(3)靜態(tài)庫(kù)的優(yōu)缺點(diǎn)
nm命令可以查看靜態(tài)庫(kù)文件(.a)和最后生成的可執(zhí)行文件的詳細(xì)屬性。nm?ibMytest.a? 可以查看該靜態(tài)庫(kù)文件有哪些庫(kù)函數(shù)(.o文件)。? ?nm zsx 顯示的信息中有:
000000000040056c T add
0000000000400530 T main? //main函數(shù)在鏈接的時(shí)候加進(jìn)去的啟動(dòng)代碼
參數(shù)T代表add和main在代碼區(qū)。即參數(shù)T表示在代碼區(qū)的內(nèi)容。
靜態(tài)庫(kù)優(yōu)點(diǎn):1.發(fā)布程序的時(shí)候不需要提供對(duì)應(yīng)的庫(kù)(動(dòng)態(tài)庫(kù)需要);2.加載庫(kù)的速度快(庫(kù)函數(shù)就在代碼區(qū))。缺點(diǎn):庫(kù)被打包到代碼中,增加了代碼的體積;2.庫(kù)一旦發(fā)生了改變,需要對(duì)整個(gè)程序進(jìn)行重新編譯。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
- 上一篇: ubuntu的Home目录下有两个jav
- 下一篇: 动态库(共享库)的制作和使用