軟件開發(fā)者可以使用某種語言的庫函數(shù),這些庫函數(shù)通常放在/lib和/usr/lib目錄中,而大多數(shù)的庫函數(shù)放在/usr/lib中,比如標(biāo)準C庫函數(shù)文件/usr/lib/libc.a和標(biāo)準C++庫函數(shù)/usr/lib/libstdc++.a。
庫對應(yīng)的頭文件有兩種,包括公有頭文件和私有頭文件。公有頭文件聲明的資源對其他程序是有效的,而私有頭文件聲明的資源只能被對應(yīng)的庫代碼使用。
為了使庫成為公有的,應(yīng)將它安裝在目錄/usr/lib中,并將它的頭文件放在/usr/include中,并在用戶程序中使用#include <>的方式引入庫頭文件。將頭文件的路徑名放置在引號中,就可將私有頭文件放入程序中,比如#include "hello.h",預(yù)處理程序會首先在當(dāng)前目錄查找hello.h頭文件,如果寫成#include "-/include/hello.h",預(yù)處理程序就會在目錄~/include中搜索頭文件hello.h。
庫文檔必須以.a擴展名結(jié)束,一旦為一組目標(biāo)模塊創(chuàng)建了一個庫文件,通過制定庫文檔作為參數(shù),這些模塊就可以被C程序根據(jù)-l*鏈接使用。
對于標(biāo)準庫,例如C中的libc.a,只需要在用戶程序中添加相應(yīng)的頭文件比如stdio.h、stdlib.h、ctype.h等,而不需要明確地用-l編譯程序選項去鏈接該庫;但還有許多庫不是標(biāo)準庫,例如數(shù)學(xué)庫libm.a,除了需要添加相應(yīng)頭文件之外,還必須明確地用編譯程序選項-lm鏈接該庫,其中-l編譯選項在lib和.a之間指定子串,不明確指定的話會在編譯器產(chǎn)生錯誤。
注意:
1.標(biāo)準C語言庫libc.a在編譯程序的鏈接階段自動被鏈接。
2.一些常見的與庫相關(guān)的編程錯誤:
沒有為庫加入頭文件
沒有明確鏈接一個庫,而這個庫不能被程序自動鏈接
使用了錯誤版本的庫
鏈接了不兼容的庫
------------------------------------------------------------------------------------------------------
庫的開發(fā)使用ar程序可以執(zhí)行各種與庫相關(guān)的任務(wù),比如在庫文件中創(chuàng)建、修改和提取模塊等。與linux命令不同,ar命令的關(guān)鍵字不需要使用-連字符。
ar 關(guān)鍵字 庫文檔名 文件列表
d 在庫文檔中刪除一個文件
q 在現(xiàn)有庫文檔中添加一個文件,若庫文檔不存在,則創(chuàng)建之
r 新建一個庫文檔或覆蓋一個現(xiàn)有庫文檔
t 顯示一個庫文檔目錄
s 強制生成庫文檔符號表
x 從一個庫文檔中提取一個或多個文件,并將它們保存在當(dāng)前的工作目錄中
v 生成一個詳細的輸出
假設(shè)已存在main.c、compute.c、input.c、main.h、compute.h、input.h這些文件,且compute.c使用了數(shù)學(xué)庫libm.a,下面的例子用于庫文檔的創(chuàng)建和追加等。
ar r libmath.a input.o compute.o
該命令創(chuàng)建了文件input.o和compute.o的庫文檔文件libmath.a,如果該庫文檔已存在則會被覆蓋。上述命令當(dāng)libmath不存在時,可以使用ar q libmath.a input.o compute.o代替,該命令在libmath.a中追加新文件,當(dāng)libmath.a不存在時自動創(chuàng)建;當(dāng)想將當(dāng)前目錄中所有目標(biāo)文件都放入庫文件中,也可以使用ar r libmath.a *.o或者ar r libmath.a `ls *.o`這樣的命令。
gcc main.c libmath.a -o power -lm
該命令將庫文檔中的input.o和compute.o鏈接到main.o上,使用-lm鏈接數(shù)學(xué)庫libm.a,因為在compute.o中使用了pow函數(shù)。將libmath.a安裝到/usr/lib后,就可以通過-lmath的方式使用了。
rm compute.o input.o
創(chuàng)建目標(biāo)模塊的庫文檔后,就可以刪除原有模塊。
ar t libmath.a
該命令用于顯示庫文檔libmath.a的目錄,同理可以使用ar vt libmath.a命令獲得更詳細的輸出。
ar d libmath.a input.o
該命令用于從庫文檔libmath.a中刪除一個或多個目標(biāo)模塊。
ar x libmath.a compute.o
該命令下哦那個庫文檔libmath.o中提取一個或多個目標(biāo)模塊,并放在當(dāng)前目錄中。
在makefile中也可以使用ar命令,這樣創(chuàng)建了軟件的可執(zhí)行文件之后,也可以創(chuàng)建目標(biāo)文檔的庫文檔,具體方法如下:
CC=gcc
OPTIONS=-03
OBJECTS=main.o input.o compute.o
SOURCES=main.c input.c compute.c
HEADERS=main.h input.h compute.h
ARCHIVE=compute.o input.o
LIBRARY=libmath.a
AR_KEYS=qv
complete : power
@echo "Build complete"
power : $(OBJECTS)
$(CC) $(OPTIONS) -o $@ $^ -lm
@echo "The executable is in the 'power' file"
main.o : main.h input.h compute.h
compute.o : compute.h
input.o : input.h
buldle :
@echo "Archiving object modules..."
ar $(AR_KEYS) $(LIBRARY) $(ARCHIVE)
@echo "Archiving is complete."
power.tar : makefile $(HEADERS) $(SOURCES)
tar -cvf $@ $^
clean :
rm -f *.o
---------------------------------------------------------------------------------------------
庫的使用
在安裝庫文檔之前,需要給庫文檔生成和添加一個目錄索引。庫文檔中的目標(biāo)文件不是以任意順序排列的,而是依賴于模塊被插入到庫文檔中的順序。帶有目錄的庫文檔在鏈接階段是必要的,它允許庫文檔中的函數(shù)互相調(diào)用,而無論這些函數(shù)在庫文檔中的位置如何。
ranlib 庫文檔列表
該命令可以為庫文檔列表中的每個庫文檔生成和添加一個目錄,該命令與如下命令相同:
ar s 庫文檔
一旦添加了目錄之后,就可以安裝該庫使其成為公有,主要采取兩個步驟:
1.創(chuàng)建庫的頭文件并把它放在/usr/include目錄中,頭文件包含庫中資源的聲明。一個庫文檔可以對應(yīng)多個頭文件,例如libmath.a可以對應(yīng)input.h和compute.h。
2.在/usr/lib目錄中放置該庫文檔,例如/usr/lib/libmath.a。
3.在使用該庫時,在程序中加入對應(yīng)頭文件,并用帶有-lmath的編譯命令即可。
可以用nm命令顯示一個庫、目標(biāo)或可執(zhí)行文件的符號表,表中包括名稱、類型、大小和進入點等信息。它的輸出告知該庫的屬性,輸出的每一行是每一個標(biāo)識符,例如文件中的某個函數(shù)名或者變量名。nm命令顯示的信息用于調(diào)試庫和可執(zhí)行文件,對于庫文檔中的每個文件或成員,nm命令至少會將下面的信息發(fā)送到標(biāo)準輸出:每個符號的地址、符號的值以及其類型。根據(jù)選項,也可能輸出庫或目標(biāo)的名稱以及符號的大小等。
nm [選項] [文件列表(庫文件/目標(biāo)文件/可執(zhí)行文件)]
-D 只顯示動態(tài)符號,當(dāng)使用動態(tài)庫時很有用
-V nm命令版本號
-g 只顯示全局符號的相關(guān)信息
-l 為每一個符號查找和顯示文件名和行號
-n 用地址給外部符號分類
-u 只顯示未定義的符號,即每個目標(biāo)模塊的外部符號
-w 給出更多警告信息
-f 格式 以不同格式輸出,可以是bsd、sysv、posix等,默認是bsd
對nm命令,以后再進行詳細學(xué)習(xí),在此省略。