什么是庫
程序庫(library),一個可供使用的各種標(biāo)準(zhǔn)程序、子程序、文件以及它們的目錄等信息的有序集合。 匯集在一起的經(jīng)常應(yīng)用的程序。
簡單來說,庫(Library)就是一段編譯好的二進(jìn)制代碼,加上頭文件就可以供別人使用。
為什么要用到庫
當(dāng)我們的代碼要提供給別人使用,我們又不希望用戶看到代碼的具體實(shí)現(xiàn)。就需要已庫的形式封裝,只暴露出頭文件。
對于某些不會進(jìn)行大的改動的代碼,想要減少編譯的時間,就可以把它打成庫,因?yàn)閹焓蔷幾g好的二進(jìn)制,編譯的時候只需要Link一下。節(jié)省時間。例如我們在做組件化的時期都會盡量做二進(jìn)制化,來提高M(jìn)erge編譯效率。
靜態(tài)庫
靜態(tài)庫即靜態(tài)鏈接庫(Windows下的.lib, Linux和Mac下的.a)。之所以叫靜態(tài)庫,是因?yàn)殪o態(tài)庫在編譯時候會被拷貝一份,復(fù)制到目標(biāo)程序里,復(fù)制到目標(biāo)程序里。這段代碼在目標(biāo)程序里就不會再改變了。
優(yōu)點(diǎn):
- 編譯完成之后,目標(biāo)程序就沒有外部依賴,直接就可以運(yùn)行。
- 提高目標(biāo)程序編譯效率。
缺點(diǎn):
增大目標(biāo)程序體積。
多次使用就會有多份冗余拷貝。(沙盒機(jī)制避免了多個目標(biāo)程序同時使用)
動態(tài)庫
動態(tài)庫即動態(tài)鏈接庫(Windows下的.dll, Linux下的.so,Mac下的.dylib/.tbd)。與靜態(tài)庫相反,動態(tài)庫在編譯時并不會被拷貝到目標(biāo)程序中,目標(biāo)程序中會存儲指向動態(tài)庫的引用。等到程序運(yùn)行時,動態(tài)庫才會被真正加載進(jìn)來。
優(yōu)點(diǎn):
- 不需要拷貝到目標(biāo)程序中,不會影響目標(biāo)程序體積,
- 同一個庫可以被多個程序使用(因?yàn)檫@個原因,動態(tài)庫也被稱為共享庫)。
- 運(yùn)行時才載入的特性,也可以讓我們隨時對庫進(jìn)行替換,而不需要重新編譯代碼。
缺點(diǎn):
- 動態(tài)載入會帶來一部分性能損失。
- 動態(tài)庫使得程序依賴外部環(huán)境,如果環(huán)境缺少動態(tài)庫或者庫版本不正確,導(dǎo)致程序無法運(yùn)行。
Framework
除了.a 和.dylib/.tbd,Mac OS/iOS 平臺還可以使用Framework。
Framework實(shí)際上是一種打包方式,將庫的二進(jìn)制文件,頭文件和有關(guān)的資源文件打包在一起。方便管理和分發(fā),和靜態(tài)動態(tài)庫的本質(zhì)沒有什么關(guān)系。
在iOS8之前,iOS平臺不支持使用動態(tài)Framework,開發(fā)者只可以使用系統(tǒng)的UIKit 、Foundation這些Framework。同時因?yàn)閕OS的沙盒機(jī)制,不同程序不能共享代碼,同時動態(tài)下載代碼是被蘋果命令禁止的,沒有辦法發(fā)揮出動態(tài)庫的優(yōu)勢。所以在iOS平臺共享代碼,唯一的選擇就是打成靜態(tài)庫.a文件,同時附上頭文件。
小結(jié):
- 動態(tài)庫類型: .a和.framework 靜態(tài)庫類型:dylib和.framework。 系統(tǒng)提供的Framework是動態(tài)的,自己創(chuàng)建的是靜態(tài)的。
- .a 是單純的二進(jìn)制文件,.framework是二進(jìn)制文件+資源文件。 .framework = .a + .h + sorrceFile(資源文件)
- 在iOS上共享代碼理論上只能使用靜態(tài)庫。
Embedded Framework
但是后來iOS8之后,iOS有了App Extesion特性,而且Swift也誕生了。由于iOS主App需要和Extension共享代碼,Swift語言機(jī)制也需要動態(tài)庫,于是蘋果后來提出了Embedded Framework,這種動態(tài)庫允許APP和APP Extension共享代碼,但是這份動態(tài)庫的生命被限定在一個APP進(jìn)程內(nèi)。簡單點(diǎn)可以理解為被閹割的動態(tài)庫。
但是這種動態(tài)庫(Embedded Framework) 和系統(tǒng)的 UIKit.Framework 還是有很大區(qū)別,傳統(tǒng)的動態(tài)庫是給多個進(jìn)程用的,而這里的動態(tài)庫(Embedded Framework)是給單個進(jìn)程里面多個可執(zhí)行文件用的。系統(tǒng)的 Framework 不需要拷貝到目標(biāo)程序中,我們自己做出來的 動態(tài)庫(Embedded Framework) 哪怕是動態(tài)的,最后也還是要拷貝到 App 中(App 和 Extension 的 Bundle 是共享的)。所以蘋果沒有直接把這種Embedded Framework稱作動態(tài)庫而是叫Embedded Framework。
上面提到跟Swift也有原因,在Swift的項目中如果要在項目中使用外部的代碼,可選的方式只有兩種,一種是把代碼拷貝到工程中,另一種是用動態(tài) Framework。使用靜態(tài)庫是不支持的。這個問題的根本原因主要是 Swift 的運(yùn)行庫沒有被包含在 iOS 系統(tǒng)中,而是會打包進(jìn) App 中(這也是造成 Swift App 體積大的原因),靜態(tài)庫會導(dǎo)致最終的目標(biāo)程序中包含重復(fù)的運(yùn)行庫。