1. 程式人生 > >make之makefile 十 函式庫檔案

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"引數。