背景:XCFramework
之前的多架構(gòu)合并
我們生成一個(gè)庫(kù)文件蓝撇,可能有模擬器的架構(gòu)墙贱,也可能有真機(jī)的架構(gòu)檐盟。但我們通常給別人提供SDK的時(shí)候都是將各種平臺(tái)架構(gòu)的庫(kù)合在一起梯投。引入一個(gè)庫(kù)文件,就可以支持調(diào)試和在真機(jī)上運(yùn)行沟涨。這種格式的庫(kù)我們通常叫他Fat Binary(胖二進(jìn)制)
恤批。
xcodebuild指令
xcodebuild -- build Xcode projects and workspaces
,Xcode中自帶的打包工具裹赴,平時(shí)我們用xcode打包就是用的這個(gè)玩意喜庞。
xcodebuild archive #打包操作
-archivePath <archivePath> #打包后的輸出路徑
-project <projectName> #項(xiàng)目名稱
-workspace <workspaceName> #項(xiàng)目空間名稱
-scheme <schemeName> #指定是項(xiàng)目中哪個(gè)scheme,可以從-list命令中獲取
-configuration <Debug|Release> #哪種環(huán)境棋返,Debug還是Release
-destination <DESTINATIONSPECIFIER> #分發(fā)的平臺(tái)
編譯一個(gè)模擬器架構(gòu)的庫(kù)
xcodebuild archive -project 'SYTimer.xcodeproj' \
-scheme 'SYTimer' \
-configuration Release \
-destination 'generic/platform=iOS Simulator' \
-archivePath '../archives/SYTimer.framework-iphonesimulator.xcarchive' \
SKIP_INSTALL=NO
執(zhí)行完后會(huì)在項(xiàng)目同級(jí)目錄生成一個(gè)archives
文件夾延都,里面包含iphonesimulator.xcarchive
文件,右鍵顯示包內(nèi)容睛竣,會(huì)看到Products
->Library
->Frameworks
晰房,Frameworks
存在一個(gè)叫SYTimer.framework
的庫(kù),這個(gè)庫(kù)就是我們編譯好的framework
。
從圖中可以看到多了一個(gè)參數(shù):
SKIP_INSTALL=NO
設(shè)置這個(gè)參數(shù)的意義在于:是否將編譯好的庫(kù)拷貝到Products
目錄下殊者,如果SKIP_INSTALL=YES
与境,則Products
目錄下為空。我們做庫(kù)合并時(shí)幽污,需要用到Framework,所以必須加上這個(gè)參數(shù)簿姨。
編譯一個(gè)真機(jī)架構(gòu)的庫(kù)
修改xcodebuild指令中的分發(fā)平臺(tái)
和輸出路徑
參數(shù):
-destination 'generic/platform=iOS' \
-archivePath '../archives/SYTimer.framework-iphoneos.xcarchive' \
lipo
指令將模擬器和真機(jī)架構(gòu)合并
使用file SYTimer
命令可以查看庫(kù)文件包含的架構(gòu)距误。
打包命令中,并沒有指定架構(gòu)扁位。但打包后SYTimer
可執(zhí)行文件中准潭,包含了arm_v7
和arm64
兩種架構(gòu)。這個(gè)和SYTimer
項(xiàng)目中的Build Settings
設(shè)置有關(guān)域仇,在打包時(shí)也執(zhí)行了Build Settings
中的設(shè)置刑然。
架構(gòu)合并需要使用lipo
命令。將不同的架構(gòu)合并到一起暇务,生成一個(gè)胖二進(jìn)制泼掠。但lipo命令卻不能將包含相同架構(gòu)的庫(kù)進(jìn)行合并。在上面生成的兩個(gè)庫(kù)文件中均包含了arm64
垦细,無法進(jìn)行合并择镇。
lipo -output SYTimer -create ../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework/SYTimer ../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework/SYTimer
lipo指令無法合并的解決辦法
使用lipo
命令,最大的問題就是包含相同架構(gòu)括改,無法合并Fat Binary
腻豌。這種情況只能將所需的架構(gòu)提取出來,再進(jìn)行合并嘱能。
lipo -output SYTimer-x86_64 -extract x86_64 ../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework/SYTimer
從模擬器中提取x86_64架構(gòu)吝梅,輸出到當(dāng)前目錄生成SYTimer-x86_64
文件。再與真機(jī)庫(kù)進(jìn)行合并惹骂,因?yàn)?code>arm64只有真機(jī)存在苏携,所以可以執(zhí)行合并成功了。
lipo -output SYTimer -create ../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework/SYTimer SYTimer-x86_64
生成XCFramework
-
XCFramework
:是蘋果官方推薦的对粪、支持的兜叨,可以更方便的表示一個(gè)多個(gè)平臺(tái)和架構(gòu)的分發(fā)進(jìn)制庫(kù)的格式。 - 需要Xcode11以上支持衩侥。
- 是為更好的支持
Mac Catalyst
和ARM芯片的macOS国旷。 - 專門在2019年提出的Framework的另一種先進(jìn)格式。
和傳統(tǒng)的Framework
相?:
- 可以?單個(gè)
.xcframework
?件提供多個(gè)平臺(tái)的分發(fā)?進(jìn)制?件 - 與
Fat Header
相?茫死,可以按照平臺(tái)劃分跪但,可以包含相同架構(gòu)的不同平臺(tái)的?件 - 在使?時(shí),不需要再通過腳本去剝離不需要的架構(gòu)體系
將兩個(gè)架構(gòu)的Framework合并成XCFramework
使用xcodebuild
命令,將模擬器和真機(jī)兩個(gè)平臺(tái)的Framework
合并成XCFramework
xcodebuild -create-xcframework \
-framework '../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-framework '../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-output 'SYTimer.xcframework'
一般XCFramework需要包含BitCode和dSYMs方便崩潰時(shí)恢復(fù)調(diào)用棧屡久,那么修改創(chuàng)建XCFramework的命令如下:
xcodebuild -create-xcframework \
-framework '../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-debug-symbols '/Users/chenshuangchao/Desktop/archives/SYTimer.framework-iphoneos.xcarchive/BCSymbolMaps/618E16C1-20B9-39A5-98A1-42E947A26ADB.bcsymbolmap' \
-debug-symbols '/Users/chenshuangchao/Desktop/archives/SYTimer.framework-iphoneos.xcarchive/BCSymbolMaps/6E502109-851C-3FA9-A5B9-8A1373F73FE5.bcsymbolmap' \
-debug-symbols '/Users/chenshuangchao/Desktop/archives/SYTimer.framework-iphoneos.xcarchive/dSYMs/SYTimer.framework.dSYM' \
-framework '../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-debug-symbols '/Users/chenshuangchao/Desktop/archives/SYTimer.framework-iphonesimulator.xcarchive/dSYMs/SYTimer.framework.dSYM' \
-output 'SYTimer.xcframework'
- 只有真機(jī)才有BitCode忆首。
- BitCode和dSYMs的文件路徑必須傳絕對(duì)路徑,否則會(huì)出現(xiàn)錯(cuò)誤the path does not point to a valid debug symbols file被环。
上面指令也可以用腳本實(shí)現(xiàn)
ARCHIVES=/Users/chenshuangchao/Desktop/archives
# -debug-symbols:必須使用絕對(duì)路徑
# Shell變量必須放在""中
xcodebuild -create-xcframework \
-framework '../archives/SYTimer.framework-iphoneos.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-debug-symbols "${ARCHIVES}/SYTimer.framework-iphoneos.xcarchive/BCSymbolMaps/9D87CD30-46F3-302A-ADCF-BF46F07578D4.bcsymbolmap" \
-debug-symbols "${ARCHIVES}/SYTimer.framework-iphoneos.xcarchive/BCSymbolMaps/ACA28AC6-6E0E-3F6F-8105-BC1175739A0B.bcsymbolmap" \
-debug-symbols "${ARCHIVES}/SYTimer.framework-iphoneos.xcarchive/dSYMs/SYTimer.framework.dSYM" \
-framework '../archives/SYTimer.framework-iphonesimulator.xcarchive/Products/Library/Frameworks/SYTimer.framework' \
-debug-symbols "${ARCHIVES}/SYTimer.framework-iphonesimulator.xcarchive/dSYMs/SYTimer.framework.dSYM" \
-output 'SYTimer.xcframework'
xcframework
文件和普通Framework
文件的使用別無二致糙及。xcframework
中打包了多個(gè)平臺(tái)的Framework
,比普通Framework
文件更大筛欢。但在實(shí)際使用中浸锨,xcframework
會(huì)根據(jù)當(dāng)前鏈接的平臺(tái)架構(gòu),僅鏈接相應(yīng)的庫(kù)文件版姑,不會(huì)將整個(gè)xcframework
全部鏈接柱搜。
xcframework的優(yōu)勢(shì):
- 不用手動(dòng)處理頭文件、資源文件等內(nèi)容(
lipo
合并后需要鏈接) - 重復(fù)架構(gòu)可自行處理剥险,(免去
lipo
指令重復(fù)時(shí)需要提取指定架構(gòu)的步驟) - 更方便的導(dǎo)入調(diào)式符號(hào)聪蘸,直接在指令中完成
- 自動(dòng)鏈接相應(yīng)平臺(tái)架構(gòu)的庫(kù)文件,將不需要的架構(gòu)去掉(上線時(shí)自動(dòng)去掉模擬器架構(gòu))