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