make之makefile 十 函式庫檔案
一、簡單的靜態庫書寫編譯和測試
檔案目錄如下所示:
.
├── Makefile
├── MakefileTest
├── include.c
├── include.h
└── main.c
0 directories, 5 files
其中main.c函式裡面會呼叫include.c裡面的函式,所以此時的Makefile檔案內容如下:
#this is a makefile demo Main:=main Include:=include Libs:=libinclude.a Libd:=libinclude.so .PHONY:all all: gcc -o $(Main) $(Main).c $(Libs) .PHONY:lib lib: gcc -c $(Include).c ar rcs $(Libs) $(Include).o .PHONY:clean clean: rm -rf *.o *.a *.so
在該目錄資料夾下執行
#make lib
執行後將include.c生成靜態庫檔案libinclude.a
然後再執行
#make all
將會生成可執行檔案main,生成過程中靜態呼叫了libinclude.a靜態庫
二、以下是示例介紹
示例1、建立並使用靜態庫
第一步:編輯原始檔,test.h test.c main.c。其中main.c檔案中包含main函式,作為程式入口;test.c中包含main函式中需要用到的函式。
vi test.h test.c main.c
第二步:將test.c編譯成目標檔案。
gcc -c test.c
如果test.c無誤,就會得到test.o這個目標檔案。
第三步:由.o檔案建立靜態庫。
ar rcs libtest.a test.o
第四步:在程式中使用靜態庫。
gcc -o main main.c -L. -ltest
因為是靜態編譯,生成的執行檔案可以獨立於.a檔案執行。
第五步:執行。
./main
示例2:建立並使用動態庫
第一步:編輯原始檔,test.h test.c main.c。其中main.c檔案中包含main函式,作為程式入口;test.c中包含main函式中需要用到的函式。
vi test.h test.c main.c
第二步:將test.c編譯成目標檔案。
gcc -c test.c
前面兩步與建立靜態庫一致。
第三步:由.o檔案建立動態庫檔案。
gcc -shared -fPIC -o libtest.so test.o
第四步:在程式中使用動態庫。
gcc -o main main.c -L. -ltest
當靜態庫和動態庫同名時, gcc命令將優先使用動態庫。
第五步:執行。
LD_LIBRARY_PATH=. ./main
示例3:檢視靜態庫中的檔案
[[email protected] lib]# ar -t libhycu.a
base64.c.o
binbuf.c.o
cache.c.o
chunk.c.o
codec_a.c.o
...
xort.c.o
[[email protected] lib]#
[[email protected] lib]# ar -tv libhycu.a
rw-r--r-- 0/0 7220 Jul 29 19:18 2011 base64.c.o
rw-r--r-- 0/0 2752 Jul 29 19:18 2011 binbuf.c.o
rw-r--r-- 0/0 19768 Jul 29 19:18 2011 cache.c.o
...
rw-r--r-- 0/0 4580 Jul 29 19:18 2011 xort.c.o
[[email protected] lib]#
[[email protected] lib]# nm -s libhycu.a | less
Archive index:
Base64Enc in base64.c.o
GetBase64Value in base64.c.o
Base64Dec in base64.c.o
encode64 in base64.c.o
decode64 in base64.c.o
check64 in base64.c.o
test64 in base64.c.o
...
chunk_alloc in chunk.c.o
三、接下來下面時介紹靜態函式庫檔案:
建立靜態庫.a檔案。用C/C++開發程式時經常用到,但我很少單獨在命令列中使用ar命令,一般寫在makefile中,有時也會在shell腳 本中用到。
常用引數
格式:ar rcs libxxx.a xx1.o xx2.o
引數r:在庫中插入模組(替換)。當插入的模組名已經在庫中存在,則替換同名的模組。如果若干模組中有一個模組在庫中不存在,ar顯示一個錯誤訊息,並不替換其他同名模組。預設的情況下,新的成員增加在庫的結尾處,可以使用其他任選項來改變增加的位置。【1】
引數c:建立一個庫。不管庫是否存在,都將建立。
引數s:建立目標檔案索引,這在建立較大的庫時能加快時間。(補充:如果不需要建立索引,可改成大寫S引數;如果。a檔案缺少索引,可以使用ranlib命令新增)
格式:ar t libxxx.a
顯示庫檔案中有哪些目標檔案,只顯示名稱。
格式:ar tv libxxx.a
顯示庫檔案中有哪些目標檔案,顯示檔名、時間、大小等詳細資訊。
格式:nm -s libxxx.a
顯示庫檔案中的索引表。
格式:ranlib libxxx.a
為庫檔案建立索引表。函式庫檔案也就是針對Object檔案(程式編譯的中間檔案)的打包檔案。在Unix下,通常是由命令"ar"來完成打包工作。
1、函式庫檔案的成員
一個函式庫檔案由多個檔案組成。你能夠以例如以下格式指定函式庫檔案及其組成:
archive(member)
這個不是一個命令,而是一個目標和依賴的定義。一般來說,這樣的使用方法基本上就是為了"ar"命令來服務的。如:
foolib(hack.o) : hack.o
ar cr foolib hack.o
假設要指定多個member,那就以空格分開,如:
foolib(hack.o kludge.o)
其等效於:
foolib(hack.o) foolib(kludge.o)
你還能夠使用Shell的檔案萬用字元來定義,如:
foolib(*.o)
2、更新靜態庫
靜態庫.a檔案都是由.o檔案組成的,如果想更新靜態庫的話需要使用以下命令即可:
ar r libinclude.a include.o
libinclude.a是需要更新的靜態庫, include.o是屬於靜態庫裡面的.o檔案,ar r命令就是更新靜態庫的.o檔案的命令
執行上面的命令後,靜態庫檔案的內容就是更新過後的最新內容了。
3、函式庫檔案的字尾規則
你能夠使用"字尾規則"和"隱含規則"來生成函式庫打包檔案,如:
.c.a:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r [email protected] $*.o
$(RM) $*.o
其等效於:
(%.o) : %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r [email protected] $*.o
$(RM) $*.o
4、注意事項
在進行函式庫打包檔案生成時,請小心使用make的並行機制("-j"引數)。假設多個ar命令在同一時間執行在同一個函式庫打包檔案上,就非常有可能損壞這個函式庫檔案。所以,在make未來的版本號中,應該提供一種機制來避免並行操作發生在函式打包檔案上。
但就眼下而言,你還是應該不要儘量不要使用"-j"引數。