靜態(tài)庫文件也稱(chēng)為“文檔文件”,它是一些.o文件的集合。在Linux(Unix)中使用工具“ar”對它進(jìn)行維護管理。它所包含的成員(member)是若干.o文件。
一個(gè)靜態(tài)庫通常由多個(gè).o文件組成。這些成員(.o文件)可獨立的被作為一個(gè)規則的目標,庫成員作為目標時(shí)需要按照如下的格式來(lái)書(shū)寫(xiě):
ARCHIVE(MEMBER)
注意,這種書(shū)寫(xiě)方式只能出現在規則的目標和依賴(lài),不能出現在規則的命令行中!因為,絕大多數命令不能支持這種語(yǔ)法,命令不能直接對庫的成員進(jìn)行操作。這種表達式在規則的目標或者依賴(lài)中,它表示庫“ARCHIVE”的成員“MEMBER”。含有這種表達式的規則的命令行只能是“ar”命令或者其它可以對庫成員進(jìn)行操作的命令。例如:下邊這個(gè)規則用于創(chuàng )建庫“foolib”,并將“hack.o”成員加入到庫:
foolib(hack.o) : hack.o
ar cr foolib hack.o
實(shí)際上,這個(gè)規則實(shí)現了對庫的所有成員進(jìn)行了更新,其過(guò)程使用了隱含規則(創(chuàng )建需要的.o文件)。另外需要注意工具“ar”的用法(可參考ar的man手冊)。
如果在規則中需要同時(shí)指定庫的多個(gè)成員,可以將多個(gè)成員羅列在括號內,例如:
foolib(hack.o kludge.o)
它就等價(jià)于:
foolib(hack.o) foolib(kludge.o)
在描述庫的多個(gè)成員時(shí)也可以使用shell通配符。例如:“foolib(*.o)”,它代表庫文件“foolib”的所有.o成員。
上一節已經(jīng)講述了規則中形如“A(M)”目標的含義,它代表靜態(tài)庫“A”的成員“M”。make為這樣的一個(gè)目標搜索隱含規則時(shí),可重建“(M)”的隱含規則,同樣也被認為是可重建“A(M)”這個(gè)目標的隱含規則。
這就出現了一個(gè)特殊的模式規則,它的目標模式是“(%)”。這個(gè)特殊的規則被用來(lái)更新目標“A(M)”,規則將文件“M”拷貝到庫“A”中,如果之前在靜態(tài)庫文件“A”不存,則首先創(chuàng )建這個(gè)庫文件。例如:目標為“foo.a(bar.o)”的規則,執行時(shí)將完成:首先使用隱含規則生成其成員“bar.o”,之后將“bar.o”加入到庫“foo.a”中。那么“bar.o”就作為庫文件“foo.a”的一個(gè)成員(當然如果“foo.a”不存在,就會(huì )被創(chuàng )建。這個(gè)特殊規則的命令行一般都是“ar”命令)。
這個(gè)特殊的規則可以和其它隱含規則一起構成一個(gè)隱含規則鏈。因此我們可以直接在命令行中執行“make ‘foo.a(bar.o)’”(注意“foo.a(bar.o)”作為命令行選項,需要使用引號,否則shell會(huì )將“(”作為特殊字符處理),只要當前目錄下存在“bar.c”這個(gè)文件,就會(huì )執行如下命令:
cc -c bar.c -o bar.o
ar r foo.a bar.o
rm -f bar.o
我們可以看到文件“bar.o”是被作為中間過(guò)程文件來(lái)處理的。需要說(shuō)明的是,包含上述命令的規則,在規則的命令行中使用自動(dòng)化變量“$%”來(lái)代表庫成員“bar.o”。
在一個(gè)靜態(tài)庫(文檔文件)中,其所有的成員名是不包含目錄描述的。就是說(shuō)對于靜態(tài)庫,當使用“nm”命令查看其成員時(shí),能夠獲得的信息只是靜態(tài)庫所包含的成員名字(一系列.o文件,文件名中并沒(méi)有包含目錄)。但我們在Makefile中,采用“A(M)”格式的目標,書(shū)寫(xiě)建立(重建或者更新)靜態(tài)庫的規則時(shí),可以指定為庫它的成員指定路徑。就是說(shuō)在描述它的成員時(shí),可以使用包含路徑的文件名。例如一個(gè)規則的目標可以這樣書(shū)寫(xiě)“foo.a(dir/file.o)”,在這個(gè)規則被執行時(shí)可能會(huì )執行如下的命令:
ar r foo.a dir/file.o
和上邊的例子類(lèi)似,它將指定目錄下的.o文件加入到庫中,此文件(“dir/file.o”)被作為靜態(tài)庫的一個(gè)成員。對于類(lèi)似這樣的目標,重建它的隱含規則的命令行中可能就需要使用自動(dòng)化變量“%D”和“%F”。
本小節的內容相對簡(jiǎn)單。前邊提到過(guò),靜態(tài)庫文件需要使用“ar”來(lái)創(chuàng )建和維護。當給靜態(tài)庫增建一個(gè)成員時(shí)(加入一個(gè).o文件到靜態(tài)庫中),“ar”可直接將需要增加的.o文件簡(jiǎn)單的追加到靜態(tài)庫的末尾。之后當我們使用這個(gè)庫進(jìn)行連接生成可執行文件時(shí),鏈接程序“ld”卻提示錯誤,這可能是:主程序使用了之前加入到庫中的.o文件中定義的一個(gè)函數或者全局變量,但連接程序無(wú)法找到這個(gè)函數或者變量。
這個(gè)問(wèn)題的原因是:之前我們將編譯完成的.o文件直接加入到了庫的末尾,卻并沒(méi)有更新庫的有效符號表。連接程序進(jìn)行連接時(shí),在靜態(tài)庫的符號索引表中無(wú)法定位剛才加入的.o文件中定義的函數或者變量。這就需要在完成庫成員追加以后讓加入的所有.o文件中定義的函數(變量)有效,完成這個(gè)工作需要使用另外一個(gè)工具“ranlib”來(lái)對靜態(tài)庫的符號索引表進(jìn)行更新。
我們所使用到的靜態(tài)庫(文檔文件)中,存在這樣一個(gè)特殊的成員,它的名字是“__.SYMDEF”。它包含了靜態(tài)庫中所有成員所定義的有效符號(函數名、變量名)。因此,當為庫增加了一個(gè)成員時(shí),相應的就需要更新成員“__.SYMDEF”,否則所增加的成員中定義的所有的符號將無(wú)法被連接程序定位。完成更新的命令是:
ranlib ARCHIVEFILE
通常在Makefile中我們可以這樣來(lái)實(shí)現:
libfoo.a: libfoo.a(x.o) libfoo.a(y.o) ...
ranlib libfoo.a
它所實(shí)現的是在更新靜態(tài)庫成員“x.o”和“y.o”之后,對靜態(tài)庫的成員“__.SYMDEF”進(jìn)行更新(更新庫的符號索引表)。
如果我們使用GNU ar工具來(lái)維護、管理靜態(tài)庫,我們就不需要考慮這一步。GNU ar本身已經(jīng)提供了在更新庫的同時(shí)更新符號索引表的功能(這是默認行為,也可以通過(guò)命令行選項控制ar的具體行為??蓞⒖?/span> GNU ar工具的man手冊)。
在make靜態(tài)庫(文檔文件)時(shí),特別需要注意:make的并行執行(執行make時(shí)使用“-j”選項)給更新靜態(tài)庫帶來(lái)的影響。因為在同一時(shí)刻,當同時(shí)使用多個(gè)“ar”命令來(lái)操作相同的靜態(tài)庫時(shí),將會(huì )靜損壞態(tài)庫,甚至導致此靜態(tài)庫不可用。
可能在后期的make版本中,會(huì )提供一種在并行執行時(shí)防止同時(shí)多個(gè)“ar”命令對同一靜態(tài)庫的操作的機制。但是就目前的版本來(lái)說(shuō),這個(gè)問(wèn)題是存在的。因此要求我們在書(shū)寫(xiě)Makefile時(shí),加入控制策略來(lái)避免make并發(fā)執行時(shí)多個(gè)“ar”命令同時(shí)操作同一個(gè)靜態(tài)庫文件?;蛘叻艞壥褂?/span>make的并發(fā)執行功能。
靜態(tài)庫的后綴規則屬于后綴規則的特殊應用,后綴規則在目前版本的GNU make中已經(jīng)被模式規則替代。但目前版本make同樣支持舊風(fēng)格的后綴規則,主要是為了兼容老版本的make。對于靜態(tài)庫的重建也可以使用后綴規則。目標后綴需要是“.a”(在Linux(Unix)中、靜態(tài)庫的后綴為.a)。例如這樣一個(gè)后綴規則:
.c.a:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r $@ $*.o
$(RM) $*.o
它相當于模式規則:
(%.o): %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
$(AR) r $@ $*.o
$(RM) $*.o
對于老風(fēng)格的后綴規則,它的目標是“.a.c”,當轉換為模式規則時(shí)。后綴規則中的“.a”被作為模式規則的目標文件后綴(目標文件就是N.a);“.c”被作為了模式規則依賴(lài)文件的后綴(依賴(lài)文件就是N.c)。
存在這樣一種情況:可能一個(gè)不是靜態(tài)庫的文件使用了后綴.a。那么make也會(huì )按照正常的方式靜態(tài)庫的后綴規則轉換成為一個(gè)模式規則。因此對于一個(gè)雙后綴規則的目標“.x.a”,經(jīng)過(guò)make轉換后會(huì )產(chǎn)生兩個(gè)模式規則:“(%.o): %.x” 和“%.a: %.x”。具體的轉換過(guò)程可參考 后綴規則 一節
聯(lián)系客服