在widows平臺下,靜態(tài)鏈接庫是.lib文件,動態(tài)庫文件是.dll文件。在linux平臺下,靜態(tài)鏈接庫是.a文件,動態(tài)鏈接庫是.so文件。這里主要講在linux平臺下的動態(tài)庫和靜態(tài)庫的生成以及鏈接。本文主要參考【1】【2】【3】【4】
一、庫的基本知識
首先說明要對庫有一個比較直觀的理解。庫是寫好的現(xiàn)有的,成熟的,可以復(fù)用的代碼?,F(xiàn)實中每個程序都依賴很多基礎(chǔ)的底層庫,不可能每個人的代碼都從零開始,因此庫的存在意義非同尋常。本質(zhì)上說來庫是一種可執(zhí)行代碼的二進(jìn)制形式(注,其本身不可執(zhí)行),可以被操作系統(tǒng)載入內(nèi)存執(zhí)行。
靜態(tài)鏈接庫,之所以稱為“靜態(tài)庫”,是因為在鏈接階段,會將匯編生成的目標(biāo)文件.o與引用到的庫一起鏈接打包到可執(zhí)行文件中,因此對應(yīng)的鏈接方式為靜態(tài)鏈接。其實一個靜態(tài)鏈接庫可以簡單看成一組目標(biāo)文件(.o/.obj文件)的集合,即很多目標(biāo)文件經(jīng)過壓縮打包后形成的一個文件。靜態(tài)庫特點總結(jié):
1. 靜態(tài)庫對函數(shù)庫的鏈接是放在編譯時期完成
2. 程序在運行時對函數(shù)庫再唔瓜葛,一直方便。
3. 浪費空間和資源,因為所有相關(guān)的目標(biāo)文件和牽涉到的函數(shù)庫被鏈接合成一個可執(zhí)行文件。
linux下使用ar工具(windows下用lib.exe)(具體的用法參考【5】),可以將目標(biāo)文件壓縮到一起,并且對其進(jìn)行編號和索引,一便于查找和索引。一般創(chuàng)建靜態(tài)鏈接庫的步驟如下:
靜態(tài)鏈接庫的命名規(guī)則,庫的名稱和庫文件名稱不同,有聯(lián)系,假定庫名稱為"my_library_name",那么起庫文件名為"lib[my_library_name].a"(方括號是為了區(qū)分,實際上沒有)
動態(tài)鏈接庫,在程序編譯是并不會被連接到目標(biāo)代碼中,而是在程序運行時才被載入。不同的應(yīng)用程序如果調(diào)用相同的庫,那么在內(nèi)存里只需要有一份該共享庫的實例,規(guī)避了空間浪費問題。動態(tài)庫的一些總結(jié):
1. 動態(tài)庫把對一些庫函數(shù)的鏈接載入推遲到程序運行時期
2. 可以實現(xiàn)進(jìn)程之間的資源共享,(動態(tài)庫也成為共享庫)
3. 將一些程序升級變得簡單
4. 設(shè)置可以真正做到鏈接載入完全由程序員在程序代碼中控制(顯式調(diào)用)
Linux下gcc編譯的執(zhí)行文件默認(rèn)是ELF格式,不需要初始化入口,亦不需要函數(shù)做特別的聲明,編寫比較方便。與windows系統(tǒng)下的格式不同。與創(chuàng)建靜態(tài)庫不同的是,不需要打包工具,直接使用編譯器即可創(chuàng)建動態(tài)庫。
二、庫的編譯和鏈接
下面使用一個例子來說明鏈接庫是如何生成與鏈接的。這個例子的源代碼參考【4】。這里有五個文件,頭文件“SoDemoTest.h”,三個cpp文件“one.cpp”、"two.cpp"、"three.cpp",main函數(shù)實現(xiàn)文件“main.cpp”。
gcc/g++的編譯參數(shù),這里只介紹 -L 、-l、-include、-I、-shared、-fPIC
-L :表示要鏈接的庫所在的目錄。-L. 表示要鏈接的庫在當(dāng)前目錄, -L/usr/lib 表示要連接的庫在/usr/lib下。目錄在/usr/lib時,系統(tǒng)會自動搜索這個目錄,可以不用指明。
-l (L的小寫):表示需要鏈接庫的名稱,注意不是庫文件名稱,比如庫文件為 libtest.so,那么庫名稱為test
-include :包含頭文件,這個很少用,因為一般情況下在源碼中,都有指定頭文件。
-I (i 的大寫):指定頭文件的所在的目錄,可以使用相對路徑。
-shared :指定生成動態(tài)鏈接庫
-fPIC: 表示編譯為位置獨立的代碼,不用此選項的話編譯后的代碼是位置相關(guān)的所以動態(tài)載入時事通過代碼拷貝的方式來滿足不同進(jìn)程的需要,而不能達(dá)到真正代碼共享的目的。
生成鏈接庫
第1步,生成目標(biāo)文件:g++ -c xxx.cpp
庫的鏈接,上面簡單演示了一遍庫的生成過程,但是還有很多細(xì)節(jié)沒有講清楚。以下問題需要注意:
1. 鏈接過程中可能出現(xiàn)多種鏈接方式,需要使用一些參數(shù)來指定,下面只是一個演示,在測試時,自己填寫具體的名稱
【1】博客園:C++靜態(tài)庫與動態(tài)庫
【2】CSDN:Linux 靜態(tài)庫&動態(tài)庫調(diào)用
【3】博客園:gcc/g++ 動態(tài)編譯和鏈接問題
【4】Linux公社:用g++編譯生成動態(tài)連接庫*.so的方法及連接
【5】CSDN:linux ar命令