gcc下如何主動創建並使用自己的動態庫或靜態庫

庫:本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行,分爲靜態庫和動態庫兩類。另外,需要知道的是,由於windowsLinux是兩款操作系統,因此,二者的庫是不兼容的。

 

靜態函數庫:

後綴通常爲***.a,利用靜態庫編譯的程序有着一定的優點,即編譯後的執行程序不需要外部的函數庫支持,因爲所有使用的函數都已經被編譯進去,但這會造成另外一個問題,如果靜態庫發生改變,程序就需要重新編譯,同時,靜態庫編譯程序生成的文件較大,因爲整個函數庫的所有數據都會被整合進目標代碼中。

利用靜態庫編譯,通常情況下是因爲我們希望我們的程序需要有更好的移植性。

動態函數庫:

後綴通常爲***.so,動態函數庫在編譯的時候並沒有被編譯進目標代碼,只有當程序執行到相關函數時才調用該函數庫裏的相應函數,因此動態函數庫所產生的可執行文件比較小。關於平臺的問題上,如果利用動態庫編譯的程序希望得到運行,那麼該運行環境中必須要有相應的庫來支持,動態函數庫並不影響程序,所以動態函數庫升級更加方便。

 

二者的最大不同之處在於庫代碼被在於內存的時刻不同,靜態庫通常在編譯時刻就被載入可執行程序,動態庫是在程序運行時載入內存的,編譯過程中只是簡單的引用。


gcc生成靜態鏈接庫實例:

在當前目錄下,有如下幾個文件,Makefile暫不關心。

wKioL1i5eE6wdbVGAAAXGO5hn_I986.png

前三個文件內容如下:

wKiom1i5eE_xYYkyAACvcg0dugE110.png



要生成靜態庫文件,首先我們需要將源代碼轉換爲二進制目標文件(hello.c -- > hello.o

[muhui@bogon mylib]$ gcc -c hello.c -o hello.o

接下來我們需要將hello.o依照靜態庫命名規範【注1】轉化爲靜態庫文件 libmyhello.a

[muhui@bogon mylib]$ ar cr libmyhello.a hello.o

得到靜態庫文件之後,就可以使用gcc命令生成最終目標文件時指明靜態庫名,gcc將會從靜態庫中將共用函數鏈接到目標文件。【注2

[muhui@bogon mylib]$ gcc -o hello main.c -L. -lmyhello 

# -L.指定了靜態庫文件目錄在當前目錄下

完成了gcc編譯的任務之後,我們需要做一件事,來驗證是否我們成功使用了靜態庫。我們嘗試將靜態庫文件刪除,看生成的可執行程序是否還能正確運行。

    [muhui@bogon mylib]$ rm -f libmyhello.a

    [muhui@bogon mylib]$ ./hello

    hello world

程序運行正常,表明靜態庫文件已經被添加進入目標文件。

最後這裏我們留意一下生成的目標文件大小:

    [muhui@bogon mylib]$ ll

    總用量 652

    -rwxrwxr-x. 1 muhui muhui 645220 2月  18 08:44 hello

    -rw-rw-r--. 1 muhui muhui     81 2月  17 18:17 hello.c

    -rw-rw-r--. 1 muhui muhui    108 2月  17 18:15 hello.h

    -rw-rw-r--. 1 muhui muhui    856 2月  18 08:36 hello.o

    -rw-rw-r--. 1 muhui muhui     63 2月  17 18:19 main.c

 

gcc生成動態鏈接庫實例:

同樣還是和上面一樣,使用同一個例子。

動態庫文件依舊需要由.o文件來創建,首先我們清理當前工作目錄。

    [muhui@bogon mylib]$ ls

    hello  hello.c  hello.h  hello.o  main.c  Makefile

    [muhui@bogon mylib]$ rm -f hello

    [muhui@bogon mylib]$ ls

    hello.c  hello.h  hello.o  main.c  Makefile

 

這裏保留的hello.o文件,同時也遵守動態庫文件命名規範【注3】,創建動態庫文件libmuhello.so

    [muhui@bogon mylib]$ gcc -shared -fPCI -o libmyhello.so hello.o

    [muhui@bogon mylib]$ ls

    hello.c  hello.h  hello.o  libmyhello.so  main.c  Makefile

 

接下來在程序中使用動態庫文件,使用動態庫和使用靜態庫文件方式完全一樣,如下

[muhui@bogon mylib]$ gcc -o hello main.c -L. -lmyhello

[muhui@bogon mylib]$ ls

hello  hello.c  hello.h  hello.o  libmyhello.so  main.c  Makefile

[muhui@bogon mylib]$ ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

 

報錯!原因說的很清楚,沒有找到動態庫文件。程序運行時,通常還在/usr/lib /lib 目錄下查找所需要的動態庫文件,所以這裏我們需要將我們生成的動態庫文件移動到/usr/lib 目錄下(需要root權限)

    [muhui@bogon mylib]$ sudo mv libmyhello.so /usr/lib/

    [sudo] password for muhui:

    [muhui@bogon mylib]$ ls

    hello  hello.c  hello.h  hello.o  main.c  Makefile

    [muhui@bogon mylib]$ ./hello

    hello world

完成之後,我們再次查看目標文件大小

    [muhui@bogon mylib]$ ll

    總用量 28

    -rwxrwxr-x. 1 muhui muhui 4888 2月  18 09:06 hello

    -rw-rw-r--. 1 muhui muhui   81 2月  17 18:17 hello.c

    -rw-rw-r--. 1 muhui muhui  108 2月  17 18:15 hello.h

    -rw-rw-r--. 1 muhui muhui  856 2月  18 08:36 hello.o

    -rw-rw-r--. 1 muhui muhui   63 2月  17 18:19 main.c

兩次對比,就會發現,使用動態庫文件的話,生成的目標文件就會小的多。

 

 

這裏需要強調的一點是,如果我們同時生成靜態庫和動態庫文件的話,操作系統一般會優先選擇動態庫。

 

 

 

 

 

 

 

 

 

【注1】靜態庫命名規範:以lib爲前綴,緊接着跟靜態庫名,擴展名爲.a

【注2gcc會在靜態庫名前加上lib前綴,然後追加擴展名.a,得到的靜態庫文件名來查找靜態庫文件,注意下面靜態庫名的變化,前綴lib變爲l,同時省略後綴。

【注3】動態庫命名規範:以lib爲前綴,緊接着跟動態庫名,擴展名爲.so








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章