靜態庫和共享庫
靜態庫
把多個.o檔案打包成靜態庫,以libXXX.a的格式命名,程式連結時,會把靜態庫整合在可執行檔案中,程式執行時,會直接載入到記憶體中。
生成靜態庫
- 靜態庫中新增或替換.o檔案
ar r libXXX.a x1.o x2.o x3.o
注:如果.o檔案不存在,就新增檔案,如果.o檔案已存在,就替換檔案。 - 靜態庫中刪除.o檔案
ar d libXXX.a x1.o
- 檢視靜態庫
ar tv libXXX.a
- 提取靜態庫中的.o檔案
ar x libXXX.a x1.o
使用靜態庫
方法1:直接使用
gcc a.c libXXX.a
方法2:連結使用
gcc a.c -L靜態庫檔案所在目錄 -l靜態庫名
注意:libXXX.a的靜態庫名為XXX
共享庫
把多個.o檔案打包成共享庫,以libXXX.so的格式命名,程式連結時,不會把共享庫整合在可執行檔案中,程式執行時,如果呼叫共享庫中的函式,此時會把共享庫載入到記憶體。
生成共享庫
- 生成與位置無關的.o檔案
gcc -c -fPIC a.c -o a.o
注意:共享庫必須使用與位置無關的.o檔案 - 打包共享庫
gcc -shared a.o b.o c.o -o libXXX.so
- 檢視.o檔案是否使用-fPIC選項編譯
nm a.o | grep _GLOBAL_OFFSET_TABLE_
有_GLOBAL_OFFSET_TABLE_,則表示使用了-fPIC選項
使用共享庫
動態連結
因可執行檔案不包含共享庫,所以需要某種機制找出共享庫所在路徑通知動態連結器
方法1:環境變數:LD_LIBRARY_PATH
方法2:配置檔案:/etc/ld.so.conf
方法3:編譯時指定:gcc -Wl,rpath,/共享庫目錄
直接使用
gcc a.c libXXX.so
連結使用
gcc a.c -L共享庫目錄 -l共享庫名
帶有so-name的共享庫
生成有so-name的共享庫
gcc -shared -Wl,-soname,libBBB.so -o libAAA.so a.o b.o c.o
-Wl,-soname,libBBB.so:指定共享庫AAA的so-name為BBB生成軟連結檔案
ln -s libAAA.so libBBB.so
共享庫的版本控制
真實名稱
libXXX.so.1.0.1
第一個數字:大版本號
後兩個數字:修訂號真實名稱、so-name、連結名稱三者的關係
真實名稱:libXXX.so.1.0.1,共享庫實際的檔案
so-name:libXXX.so.1,區分大版本,不同大版本之間不相容
連結名稱:libXXX.so,連結時使用,此名稱一直不變使用標準規範建立一個共享庫
gcc -g -c -fPIC mod1.c mod2.c mod3.c
gcc -g -shared -Wl,soname,libdemo.so.1 -o libdemo.so.1.0.1 mod1.o mod2.o mod3.o
ln -s libdemo.so.1.0.1 libdemo.so.1
ln -s libdemo.so.1 libdemo.so
安裝共享庫
cp libXXX.so.1.0.1 /指定目錄
ln -s libXXX.so.1.0.1 /指定目錄/libXXX.so.1
ln -s libXXX.so.1 /指定目錄/libXXX.so
共享庫安裝路徑
/lib
/usr/lib
/usr/local/lib
共享庫升級小版本
編譯好小版本後,放入指定路徑
執行ldconfig -v
可以自動更新小版本共享庫升級大版本
拷貝libXXX.so.2.0.0放入指定路徑
執行ldconfig -v
更新,會生成libXXX.so.2軟連結
執行ln -s libXXX.so.2 libXXX.so
混合連結靜態庫、共享庫
當靜態庫和共享庫同名時,編譯器預設會優先使用共享庫,如果共享庫不存在,則使用靜態庫。
- 全部使用靜態庫
gcc a.c -static -L庫目錄 -lXXX
- 混合使用靜態庫、共享庫
gcc a.c -L庫目錄 -Wl,-dn -lX1 -Wl,-dy -lX2
-Wl,-dn:表示開始使用靜態庫
-Wl,-dy:表示結束使用靜態庫
注意:-Wl,-dn 和 -Wl,-dy要成對出現