對於講解iOS
中靜態庫和動態庫的文章已經不少了,以前本身也總結了一篇。從今天目前來講,以前就是總結了皮毛。今天的文章也算是後續的總結,應該隨着後面的深刻還會有不一樣的體會。ios
- 靜態庫徹底複製進可執行的二進制裏面
- 後綴是
.a
或者.framework
- 動態庫是在程序冷啓動時候被連接到手機內存或者 App 內存裏面
- 後綴是
.tbd
或者.framework
關於說明不少,能夠看一下網上的文章。我如今說的是基於上面理論的證實。剛開始以爲網上說的可能不太準確,後來獲得驗證是正確的。git
爲了研究咱們建立的.a
和.framework
究竟是靜態庫和動態庫,咱們分別建立對應的簡單的庫。github
咱們分別能夠經過上面圖中紅色區域建立.framework
和.a
。咱們知道區分是靜態庫仍是動態庫最終是咱們選擇的 Mach-O
的類型究竟是Dynamic Library
仍是Static Library
。xcode
這裏簡單說一下Mach-O
類型,爲何說簡單說一下。由於深刻我也不瞭解了,深刻能夠谷歌資料。bash
Executable:應用的主要二進制架構
Dylib Library:動態連接庫(又稱DSO或DLL)mvc
Static Library:靜態連接庫框架
Bundle:不能被連接的Dylib,只能在運行時使用dlopen( )加載,可當作macOS的插件iphone
Relocatable Object File:可重定向文件類型post
上面的解釋也是抄別人的(小聲).
爲了讓打出來的庫更加的真實,咱們使用網上出名的庫做爲測試。咱們選取的是FLEX做爲測試的目標,由於這個庫所包含的文件多,數據真實性更加的可靠。咱們編譯的環境是基於iPhone 6s Plus
進行編譯出來的,真正的大小會包含其餘框架會比我測試大得多。
二進制大小(iPhone 6s Plus) | .a | .framework |
---|---|---|
靜態庫 | 6.8MB | 4.6MB |
動態庫 | 1.6MB | 1.6MB |
爲了驗證咱們所謂靜態庫和動態庫是不是真正的靜態庫和動態庫,咱們使用File
命令和Mach-O查看軟件分別對比一下。
輸出顯示 | .a | .framework |
---|---|---|
靜態庫 | ✅(current ar archive) | ✅(current ar archive) |
動態庫 | ✅(Mach-O 64-bit dynamically linked shared library x86_64) | ✅(Mach-O 64-bit dynamically linked shared library x86_64) |
輸出顯示 | .a | .framework |
---|---|---|
靜態庫 | ✅(Static Library) | ✅(Static Library) |
動態庫 | ✅(Shared Library) | ✅(Shared Library) |
咱們對比結果發現,不論是.a
仍是.framework
均可以做爲動態連接庫來使用,這和咱們在網上看到文章說.a
是靜態庫是不嚴謹的。
咱們按照靜態庫是完整被拷貝到工程二進制裏面,動態庫是在啓動時候動態連接的描述,咱們分別對比一下運行包裏面的表現。咱們一樣是按照iPhone 11 Pro Max
作爲對比的,這樣數據比較真實。
Static Library
的.a
和.framework
代碼所在位置(iPhone 6s Plus) | .a | .framework |
---|---|---|
靜態庫 | App 二進制中 | App 二進制和 Frameworks 文件夾中 |
動態庫 | 無(二進制沒有 Frameworks文件夾 沒有) | Frameworks 文件夾中 |
App二進制大小(iPhone 6s Plus) | .a | .framework |
---|---|---|
靜態庫 | 93KB | 93KB |
動態庫 | 92KB | 92KB |
冷啓動速度(iPhone 6s Plus) | .a | .framework |
---|---|---|
靜態庫 | 151.44毫秒 | 53.35毫秒 |
動態庫 | 0 毫秒(運行報錯) | 254.58毫秒 |
熱啓動速度 | .a | .framework |
---|---|---|
靜態庫 | 160.99 毫秒 | 154.65 毫秒 |
動態庫 | 0 毫秒(運行報錯) | 199.04 毫秒 |
這裏描述的冷啓動是指代程序第一次安裝以後運行可能會加載系統動態庫而形成啓動時間邊長,熱啓動是第二次啓動不須要加載系統動態庫。
經過上面的代碼位置,二進制大小,冷啓動速度和熱啓動速度大概能夠得出一個結論。雖然嚴格來講.a
是支持打包出來動態庫的,可是代碼不會複製進二進制,也不會存放在Frameworks
裏面。形成咱們打出來的動態庫.a
在程序裏面沒法運行,也就換句話說.a
只支持靜態庫特徵了。
雖然.a
的靜態庫的熱啓動比冷啓動還要慢,可是這幾毫秒的偏差能夠拋棄。可能基於咱們手機已經打開了其餘應用形成冷啓動沒有再次加載系統動態庫而和熱啓動速度差很少。
可是對比.framework
能夠得知靜態庫
的啓動速度確實比動態庫
的加載速度快不少。而靜態庫的.framework
會存在兩份,因此安裝包會變大,由於靜態庫的.framework
直接複製進二進制裏面,因此二進制會變大。
經過上面咱們得出下面的結論
.a
只支持靜態庫(打包出動態庫也是支持的 只不過目前 iOS 不支持加載).framework
靜態庫會存在於二進制和Frameworks
兩份。.framework
比.a
的二進制文件小的多.framework
不推薦用.a
說完了咱們經常使用的動態庫和靜態庫,咱們說一下今年出的新特徵XCFramework
。根據以前一篇文章瞭解,XCFramework
是爲了取代以前的.framework
的。
我很想深刻的探究一下XCframeworks
來談一下用這個的好處,可是蘋果對於這個的資料少之又少。咱們經過真實的對比一下XCFrameworks
的好處。
咱們經過對比包含模擬器
和真機
的.framework
和對比.xcframework
對比一下數據。
對於生成多架構的.framework
咱們須要用到lipo
命令進行合成,可是對於生成.xcframework
能夠用到個人xcbuild
的腳本生成。
(X86_64 + ARM64) | .framework | .xcframework |
---|---|---|
文件大小 | 10.6MB | 10.8MB |
二進制大小 | 10.4MB | 8.3MB+2.2MB |
App 大小(iPhone 6S Plus Debug) | 4.8MB | 2.8MB |
冷啓動 | 169.8 毫秒 | 155.52毫秒 |
熱啓動 | 159.56 毫秒 | 153.62 毫秒 |
經過對比.xcframework
比.framework
不但 App 大小少了不少,並且還對於啓動速度提高了很多。
咱們以前說的能夠將.a
和頭文件打包到.xcframework
中,咱們下面嘗試一下。
咱們事先準備好模擬器和真機架構的.a
和頭文件,使用下面的命令建立一個XCFrameworks
.
xcodebuild -create-xcframework -library <path> [-headers <path>] [-library <path> [-headers <path>]...] -output <path>
//Example
xcodebuild -create-xcframework -library /Users/zhangxing/Library/Developer/Xcode/DerivedData/MyLibrary-frqlmvciureprnbnytogqzjagose/Build/Products/Debug-iphonesimulator/libMyLibrary.a -headers /Users/zhangxing/Library/Developer/Xcode/DerivedData/MyLibrary-frqlmvciureprnbnytogqzjagose/Build/Products/Debug-iphonesimulator/include/MyLibrary -library /Users/zhangxing/Library/Developer/Xcode/DerivedData/MyLibrary-frqlmvciureprnbnytogqzjagose/Build/Products/Debug-iphoneos/libMyLibrary.a -headers /Users/zhangxing/Library/Developer/Xcode/DerivedData/MyLibrary-frqlmvciureprnbnytogqzjagose/Build/Products/Debug-iphoneos/include/MyLibrary -output /Users/zhangxing/Library/Developer/Xcode/DerivedData/MyLibrary-frqlmvciureprnbnytogqzjagose/Build/Products/MyLibrary.xcframework
複製代碼
假設咱們的MyFramework
依賴一個咱們本身的另外的庫或者其餘第三方的庫
xcodebuild -create-xcframework -framework <path> [-framework <path>...] -output <path>
//Example
xcodebuild -create-xcframework -framework /Users/zhangxing/Downloads/data/MyFrameworkB.xcframework/ios-arm64/MyFrameworkB.framework -framework /Users/zhangxing/Downloads/data/MyFrameworkB.xcframework/ios-x86_64-simulator/MyFrameworkB.framework -framework /Users/zhangxing/Downloads/data/ios-arm64/MyFramework.framework -framework /Users/zhangxing/Downloads/data/ios-x86_64-simulator/MyFramework.framework -output /Users/zhangxing/Downloads/data/MyFrameworkC.xcframework
複製代碼
結果是一個 XCFrameworks
只能包含一個框架,可是能夠包含多個架構。和以前寫的文章寫的理解有誤,這裏糾正一下。
Fat Framework
變成最新的XCFramework
若是有源碼能夠直接使用xcbuild
命令生成,若是沒有或者是其餘第三方的可使用下面的命令。
lipo 靜態庫源文件路徑 -thin CPU架構名稱 -output 拆分後文件存放路徑
複製代碼
用分離出來的架構從新合成XCFrmaework
。
其實這樣很麻煩,以後我會有空完善一下xcbuild
的功能。寫到這裏這篇文章就寫完了,對於靜態庫和動態庫知道了一些,還有一些疑惑。對於XCFrmaework
驗證了一些猜測,也存在太多的疑問。