linux 靜態庫與動態庫的編譯和使用

2021-06-02 10:01:30 字數 3555 閱讀 4581

gcc -o test.o test.c

-----------將.c檔案編譯成.o

ar -xv libtest.a

--------------靜態庫解包

ar -rv libtest.a *.o

------------將.o檔案編譯成.a,用*.o可以將所有.o檔案編譯成乙個.a

gcc -shared -o test.so *.o

-------將.o檔案編譯成.so,用*.o可以將所有.o檔案編譯成乙個.so

靜態庫:靜態庫也叫檔案(archive),他們的名字都按管理 *.a 命名,靜態庫也就是被歸檔的二進位制目標**檔案,當要使用時,就用include 來包含該庫的標頭檔案即可,

如果不是標準庫,要指名路徑,用」-l「 指名,自己建立靜態庫,用歸檔命令」ar「 即可,例如」ar crv  test.a  test1.o test2.o「

在linux環境中, 使用ar命令建立靜態庫檔案.如下是命令的選項:

d -----從指定的靜態庫檔案中刪除檔案
m -----把檔案移動到指定的靜態庫檔案中
p -----把靜態庫檔案中指定的檔案輸出到標準輸出
q -----快速地把檔案追加到靜態庫檔案中
r -----把檔案插入到靜態庫檔案中
t -----顯示靜態庫檔案中檔案的列表
x -----從靜態庫檔案中提取檔案
還有多個修飾符修改以上基本選項

a -----把新的目標檔案(*.o)新增到靜態庫檔案中現有檔案之後
b -----把新的目標檔案(*.o)新增到靜態庫檔案中現有檔案之前
v -----使用詳細模式
ar 命令的命令列格式如下:

ar [-][abcfilnopssuvv] [membername] [count] archive files...

引數archive定義庫的名稱, files是庫檔案中包含的目標檔案的清單, 用空格分隔每個檔案.

比如建立乙個靜態庫檔案的命令如下:

ar -rv libtest.a a.o b.o

可以用 t 選項顯示包含在庫中的檔案

ar -t test.a

建立庫檔案之後,可以建立這個靜態庫檔案的索引來幫助提高和庫連線的其他程式的編譯速度.使用ranlib程式建立庫的索引,索引存放在庫檔案內部.

ranlib libtest.a

用nm程式顯示存檔檔案的索引,它可以顯示目標檔案的符號

nm libtest.a | more

如果是顯示目標檔案的符號:

nm a.o | more

在test.c中呼叫在libtest.a中的函式:

gcc -o test test.c libtest.a

動態庫:動態庫也叫共享庫,系統存放的位置和靜態庫是乙個地方,不通的是字尾名不一樣,以」.so「結尾,如果乙個程式使用動態庫,則該程式本身不包含呼叫的函式代

碼,只包含呼叫的線索,只是在程式需要呼叫時才去呼叫動態庫。

1、建立共享庫

建立檔案hello.c,內容如下:

#include
void hello(void)
用命令gcc -shared hello.c -o libhello.so編譯為動態庫。可以看到,當前目錄下多了乙個檔案libhello.so。

2.編譯共享庫

檢視檔案

$ file libhello.so
libhello.so: elf 32-bit lsb shared object, intel 80386, version 1 (sysv), not stripped
再編輯乙個測試檔案test.c,內容如下:

int
main()

編譯test.c

$ gcc test.c
/tmp/ccm7w6mn.o: in function `main':
test.c:(.text+0x1d): undefined reference to `hello'
collect2: ld returned 1 exit status
鏈結時gcc找不到hello函式,編譯失敗:原因是hello在我們自己建立的庫中

$ gcc test.c -lhello
/usr/lib/gcc/i686-pc-linux-gnu/4.0.0/../../../../i686-pc-linux-gnu/bin/ld: cannot find -lhello
collect2: ld returned 1 exit status
$ gcc test.c -lhello -l.
$
第一次編譯直接編譯,gcc缺省會鏈結標準c庫,但符號名hello解析不出來,故連線階段通不過了。

現在用gcc test.c -lhello -l.已經編譯成功了,預設輸出為a.out。現在來試著執行一下:

$ ./a.out
./a.out: error while loading shared libraries: libhello.so: cannot open shared object file: no such file or directory
雖然鏈結時鏈結器(dynamic linker)找到了動態庫libhello.so,但動態載入器(dynamic loader, 一般是/lib/ld-linux.so.2)卻沒找到。再來看看ldd的輸出:

$ ldd a.out
linux-gate.so.1 => (0xffffe000)
libhello.so => not found
libc.so.6 => /lib/libc.so.6 (0x40034000)
/lib/ld-linux.so.2 (0x40000000)
linux為我們提供了兩種解決方法:

1.可以把當前路徑加入 /etc/ld.so.conf中然後執行ldconfig,或者以當前路徑為引數執行ldconfig(要有root許可權才行)。

2.把當前路徑加入環境變數ld_library_path中

當然,如果你覺得不會引起混亂的話,可以直接把該庫拷入/lib,/usr/lib/等位置(這樣做也要有許可權),這樣鏈結器和載入器就都可以準確的找到該庫了。

採用第二種方法:

$ export ld_library_path=.:$ld_library_path
$ ldd a.out
linux-gate.so.1 => (0xffffe000)
libhello.so => ./libhello.so (0x4001f000)
libc.so.6 => /lib/libc.so.6 (0x40036000)
/lib/ld-linux.so.2 (0x40000000)
這樣ld-linux.so.2就可以找到libhello.so這個庫了。

現在可以直接執行了:

$ ./a.out

hello world

編譯靜態庫編譯動態庫

編譯靜態庫 cr標誌告訴ar將object檔案封裝 archive 我們可以使用nm s 命令來檢視.a檔案的內容 ar cr libmyhello.a hello.o 或 cvr 編譯動態庫 gcc c fpic test1.c gcc c fpic test2.c fpic告訴gcc將源 編譯成...

Linux靜態庫與動態庫

靜態庫 a 靜態庫的 在編譯過程中已經被載入可執行程式,因此體積較大。編譯程式時候需要庫作依賴,執行時候不需要。方便,不再需要外部函式庫支援 缺點 1 因為靜態庫被鏈結後直接嵌入可執行程式中,相當於每乙個可執行程式裡都有乙個庫的副本,浪費空間 2 一旦庫中有bug,需要重新編譯。建立步驟 1 編寫函...

linux動態庫與靜態庫

現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的 都從零開始。盡量不重複做別人已經做過的事,站在巨人的肩膀上 做事情。根據鏈結時期的不同,庫又有 靜態庫和共享庫 動態庫 二者的不同點在於 被載入的時刻不同,靜態庫的 在編譯過程中已經被載入可執行程式,因此體積較大。共享庫的 是在可執行程式執行時...