iOS開發(fā)中『庫』的區(qū)別與應(yīng)用
前言
在iOS開發(fā)中你肯定聽說過.framework
桦山、.a
秕岛、.tbd
、.dylib
那么這都是啥折汞?那個是靜態(tài)庫倔幼?那個是動態(tài)庫?
1.編譯過程
首先我們先了解一下編譯過程爽待,這有助于我們對「庫」的理解损同。
1.1 編譯過程中的幾個步驟
當(dāng)我們開始build
后我們的IDE
究竟為我們做了什么事情呢?
- 預(yù)處理(Pre-process)
預(yù)編譯階段是把宏替換鸟款,刪除注釋膏燃,展開頭文件,產(chǎn)生 .i 文件何什。
- 編譯(Compliling)
編譯階段是把之前的 .i 文件轉(zhuǎn)換成匯編語言组哩,產(chǎn)生 .s文件。
- 匯編(Asembly)
匯編階段是把匯編語言文件轉(zhuǎn)換為機(jī)器碼文件,產(chǎn)生 .o 文件伶贰。
- 鏈接(Link)
連接階段是對.o文件中的對于其他的庫的引用的地方進(jìn)行引用蛛砰,生成最后的可執(zhí)行文件(同時也包括多個 .o 文件進(jìn)行 link)。
1.2 編譯選項(xiàng)
- Build phases
主要是用來控制從源文件到可執(zhí)行文件的整個過程的黍衙,所以說應(yīng)該是面向源文件的泥畅,包括編譯那些文件,以及在編譯過程中執(zhí)行一些自定義的腳本琅翻。
- Build rules
主要是用來控制如何編譯某種類型的源文件位仁,例如相對某種類型的源文件進(jìn)行特定的編譯就應(yīng)該在這里進(jìn)行編輯了,同時也會大量的運(yùn)用一些Xcode中的環(huán)境變量望迎。
官方文檔傳送門:Build Setting Reference
查看Xcode中所有環(huán)境變量:
終端->export OBJC_HELP=1
- Build settings
主要是對編譯工作的細(xì)節(jié)設(shè)定障癌,在這個窗口中可以看見大量的選項(xiàng),從編譯到打包再到代碼簽名應(yīng)有盡有辩尊,這里要注意
settings
的section
分類涛浙,同時一般通過右側(cè)的inspector
就可以很好的理解選項(xiàng)的意義了。
2. 動態(tài)庫&靜態(tài)庫
Static frameworks are linked at compile time. Dynamic frameworks are linked at runtime. 靜態(tài)庫在編譯期間進(jìn)行鏈接摄欲,動態(tài)庫在運(yùn)行時進(jìn)行鏈接轿亮。
不管是動態(tài)庫還是靜態(tài)庫都是「庫」也就是編譯好的二進(jìn)制文件,它們的區(qū)別在于用法胸墙,那么為什么還要區(qū)分動態(tài)和靜態(tài)呢我注?請看下圖:
- 靜態(tài)庫
對于靜態(tài)庫而言,在編譯鏈接的時候迟隅,會將靜態(tài)庫中被使用的文件合并到目標(biāo)APP可執(zhí)行文件中但骨,其實(shí)靜態(tài)庫只參與了鏈接過程,因?yàn)樗旧砭褪潜痪幾g好了的.o文件智袭。
靜態(tài)庫鏈接過程
連接器會將所有
.o
用到的global symbol和unresolved symbol放入到一個臨時表奔缠,而且global symbol是不能重復(fù)的。對于靜態(tài)庫的
.o
鏈接器會將沒有任何symbol在unresolved symbol table忽略最后吼野,連接器會將函數(shù)的引用替換為其實(shí)際的實(shí)現(xiàn)地址
動態(tài)庫
首先校哎,對于動態(tài)庫其實(shí)分為動態(tài)鏈接庫和動態(tài)加載庫兩種,這兩個的本質(zhì)區(qū)別還是加載時間瞳步。
- 動態(tài)鏈接庫:在沒有被加載到內(nèi)存的前提下闷哆,當(dāng)可執(zhí)行文件被加載,動態(tài)庫也隨著被加載到內(nèi)存中单起。
-
動態(tài)加載庫:當(dāng)需要使用的時候通過命令進(jìn)行加載抱怔,例如
dlopen
小結(jié):
- 靜態(tài)庫和動態(tài)庫都是二進(jìn)制文件
- 靜態(tài)庫在編譯連接期間就會被合并的可執(zhí)行文件中
- 動態(tài)庫可能隨著可執(zhí)行文件的加載而加載,也可能在被使用的時候通過命令加載
- 動態(tài)庫由于加載延后所以啟動和加載會更耗時
- 在iOS中蘋果通過共享緩存技術(shù)來實(shí)現(xiàn)
UIKit
嘀倒、Foundation
野蝇、CFNetwork
等等庫的加載讼稚,同時也減少了APP包的體積
3. 不同后綴庫的區(qū)別
3.1 .framework & .a
-
.a
是一個純二進(jìn)制文件,需要配合頭文件绕沈,資源文件一起使用锐想,在iOS中一般用作靜態(tài)庫文件的后綴名。 - 乍狐。framework中除了有二進(jìn)制文件還有資源文件赠摇,可以直接使用
- 在不能開發(fā)動態(tài)庫的時候,其實(shí)framework = .a + .h + .bundle浅蚪,在Xcode6以后藕帜,我們可以開發(fā)動態(tài)庫了, framework = 靜態(tài)庫/動態(tài)庫 + .h + .bundle
3.2 .tbd & .dylib
- .dylib是動態(tài)庫常用的后綴名惜傲,我們主要見過的地方就是libsqlite3.dylib
- 在Xcode 7以后我們在導(dǎo)入系統(tǒng)提供的動態(tài)庫的時候不再有.dylib了洽故,取而代之的是.tbd
-
.tbd是一個
YAML
文本文件,描述了需要連接的動態(tài)庫信息盗誊,主要目的還是為了減少app的下載大小
那么為什么要這樣做呢泄鹏?以下是Stackoverflow上的一篇回答
You can also see a .tbd file if you go to the General tab of your Xcode project and then add a library under Linked Frameworks and Libraries. The .tbd file will be copied to your project.
So it appears that the .dylib file is the actual library of binary code that your project is using and is located in the /usr/lib/ directory on the user's device. The .tbd file, on the other hand, is just a text file that is included in your project and serves as a link to the required .dylib binary. Since this text file is much smaller than the binary library, it makes the SDK's download size smaller.
如果轉(zhuǎn)到
Xcode
項(xiàng)目的General
選項(xiàng)卡寥袭,然后在鏈接框架和庫下添加一個庫拱镐,還可以看到一個.tbd
文件慢显。tbd
文件將被復(fù)制到您的項(xiàng)目中。
因此开镣,
.dylib
文件似乎是項(xiàng)目使用的二進(jìn)制代碼的實(shí)際庫刀诬,并且位于用戶設(shè)備的/usr/lib/
目錄中。另一方面邪财,.tbd
文件只是一個包含在項(xiàng)目中的文本文件陕壹,用作所需的.dylib
二進(jìn)制文件的鏈接。因?yàn)檫@個文本文件比二進(jìn)制庫小得多树埠,所以它使得SDK的下載大小更小糠馆。
4.總結(jié)
- 靜態(tài)庫主要是.a文件,也有.framework
- 動態(tài)庫主要使用.dylib弥奸、.tbd榨惠、.framework作為后綴名
- 相對于靜態(tài)庫奋早,動態(tài)庫在包體積上占有絕對優(yōu)勢
- 在iOS上由于蘋果做了優(yōu)化盛霎,所以系統(tǒng)的動態(tài)庫通過共享緩存技術(shù)啟動很快,內(nèi)存占用很少
- 但是我們自己開發(fā)的動態(tài)庫將不會有4中的優(yōu)勢
- 從可用性來看.framework相對于.a在靜態(tài)庫上更有優(yōu)勢