Linux下動態庫 靜態庫的生成與使用

2021-07-23 12:00:11 字數 2731 閱讀 4300

動態庫和靜態庫的介紹

一般情況下,在專案裡會把功能相似的**封裝成庫,方便使用和管理,同時增加了**的內聚性。庫分為兩種,一種為靜態庫,檔名以.a結尾,另一種是動態庫,檔名以.so結尾。靜態庫和動態庫的使用各有利弊。使用靜態庫的好處就是簡單,因為在鏈結的時候直接把靜態庫中的內容鏈結到可執行檔案中,鏈結完成後,就不再需要靜態庫了。靜態庫的缺點是,增大了可執行檔案的體積,增長了可執行檔案裝載的時間。同時靜態庫不能共享,所有使用靜態庫的可執行檔案中,都有靜態庫中的內容。動態庫則沒有這些缺點,因為動態庫是在程式開始執行後才載入的,而且程式可以根據需求自主選擇載入動態庫的時機,所以使用動態庫可以加快可執行檔案裝載的時間。同時,動態庫是可以共享的,多個程式在執行中可以使用同乙個動態庫,可以減少程式總的大小。

現在用乙個微型的工程,來講述靜態庫、動態庫的生成和使用。假設有3個.c檔案,分別為:add.c sub.c main.c,實現了add()和sub()這兩個函式,功能是返回兩個整數相加或者相減的結果,main.c中使用到了這兩個函式。下面講述怎樣把這add.c和sub.c兩個檔案生成並使用靜態庫和動態庫,然後生成可執行檔案。

int add(int a, int b);

int add(int a, int b)

int sub(int a, int b);

int sub(int a, int b)

#include "add.h"

#include "sub.h"

#include int main()

一、生成靜態庫

生成靜態庫一般使用ar命令,關於ar命令詳情可參考這裡,或者linux manual page。

通常步驟是把生成靜態庫所涉及到的.c檔案全都編譯,生成.o檔案,然後使用ar命令生成.a檔案,即靜態庫。這裡需要使用到gcc的-c選項,意思是只進行編譯,不進行鏈結。

gcc -w -c add.c -o add.o

gcc -w -c sub.c -o sub.o

ar cvr libaddsub.a add.o sub.o

此時得到了靜態庫libaddsub.a。可以用命令nm來檢視.a中的符號名稱。

二、使用靜態庫

使用靜態庫的方法非常簡單,直接把靜態庫的名字加入到需要編譯的檔案裡就可以。如下所示,注意被依賴的靜態庫應該放在後面:

gcc -w -c main.c -o main.o

gcc main.o libaddsub.a -o test

執行test得到如下結果:

result of 1 + 1 is: 2

result of 6 - 3 is: 3

三、生成動態庫

生成動態庫要求編譯出的.o檔案是位置無關的**,也就是說需要使用-fpic選項。然後使用gcc的-share選項生成動態庫。

gcc -w -c add.c -fpic -o add.o

gcc -w -c sub.c -fpic -o sub.o

gcc -shared add.o sub.o -o libaddsub.so

四、使用動態庫

生成可執行檔案的時候需要指定動態庫所在的位置,以及動態庫的名稱。-l選項表示指定動態庫所在的目錄,-l選項表示需要鏈結的動態庫的名稱。一般linux下動態庫的明明規則都是lib***.so,其中***為動態庫的真正名稱,所以-l選項的寫法是-l***。-l選項與它後的內容以及-l選項與它後面的內容之間可以沒有空格,也可以加上空格。也就是說,-l***和-l ***都是可以的。

gcc -w -c main.c -o main.o

gcc main.o -o test -l./ -laddsub

如果此時直接執行test的話,會得到類似下面的錯誤:

./test: error while loading shared libraries: libaddsub.so: cannot open shared object file: no such file or directory

意思是libaddsub.so不在系統預設載入動態庫的目錄裡面。解決的辦法有很多種:

(1)系統預設的動態庫目錄為/lib*,/usr/lib*,和/etc/ld.so.conf檔案中配置的目錄。所以可以把libaddsub.so複製到預設的動態庫載入目錄裡,比如/usr/lib目錄下。一般安裝程式時會這麼做,安裝完後程式就可以正常啟動了。

(2)修改/etc/ld.so.conf配置檔案。把所需的動態庫所在的目錄新增到這個檔案裡。

(3)啟動程式之前向環境變數ld_library_path中加入動態庫所在的目錄。可以使用export,或者這樣:

ld_library_path=$ld_library_path:pwd ./test

這只是乙個臨時的做法,不建議使用這個方法。

(4)生成可執行檔案時加入-wl,-rpath=***引數,其中***是動態庫所在的目錄,這裡最好寫成絕對路徑。-wl表示後面的引數是鏈結器ld的引數而不是gcc的引數。-rpath表示執行時載入動態庫的目錄。這樣做的話就可以直接執行可執行檔案了,因為動態庫所在目錄的資訊已經儲存在了可執行檔案中。例如:

gcc main.o -o test -l./ -laddsub -wl,-rpath=./

./test

執行程式後,還是可以得到和使用靜態庫相同的結果。

linux下動態庫和靜態庫生成

有時候需要把一組 編譯成乙個庫,這個庫在很多專案中都要用到,例如libc就是這樣乙個庫,我們在不同的程式中都會用到libc中的庫函式 例如printf 也會用到libc中的變數 例如以後 要講到的environ變數 本文將介紹怎麼建立這樣乙個庫。這些檔案的目錄結構是 tree main.c stac...

Linux下靜態庫和動態庫的生成

1.何為靜態庫 何為動態庫 windows下 dll 是動態庫 lib是靜態庫 linux下 so是動態庫 a是靜態庫 靜態庫 在生成可執行程式的時候,會把函式的具體執行方式封裝到程式中,程式體積比較大,只要能編譯成功,就可以在任意相同的平台上執行 動態庫 在生成可執行程式的時候,只會把函式的介面封...

Linux動態庫靜態庫的生成

函式庫 1 便於移植,方便使用 2 保密,保護智財權 靜態庫 編譯生成靜態庫 編譯生成靜態庫 1 把.c檔案編譯生成.o檔案 gcc c add.c 或gcc add.c c o add.c 2 把.o檔案編譯生成.a靜態庫 ar rc libadd.a add.o 3 靜態庫的使用 gcc mai...