一、BitCode是什么
Bitcode is an intermediate representation of a compiled program. Apps you upload to iTunes Connect that contain bitcode will be compiled and linked on the store. Including bitcode will allow Apple to re-optimize your app binary in the future without the need to submit a new version of your app to the store.
Xcode hides symbols generated during build time by default, so they are not readable by Apple. Only if you choose to include symbols when uploading your app to iTunes Connect would the symbols be sent to Apple. You must include symbols to receive crash reports from Apple.
上述引自Apple的文檔?App Thinning (iOS, tvOS, watchOS)隅肥。
其大概意思是Bitcode類似于一個中間碼竿奏,被上傳到applestore之后,蘋果會根據(jù)下載應(yīng)用的用戶的手機(jī)指令集類型生成只有該指令集的二進(jìn)制腥放,進(jìn)行下發(fā)泛啸。從而達(dá)到精簡安裝包體積的目的。
為了更好的理解什么是bitcode秃症,我們簡短的看一下編譯器編譯的過程:
Lexer:讀入源文件候址,并將其轉(zhuǎn)化成字符流
Parser:將字符流轉(zhuǎn)換成AST(抽象語法樹)
Semantic Analysis: 對輸入的AST進(jìn)行語法檢查吕粹。
Code Generation: 代碼生成,將AST轉(zhuǎn)換成低層次的IR指令
Optimization: 分析IR指令岗仑,將其中潛在會拖慢運(yùn)行速度的指令干掉昂芜。
AsmPrinter: 通過IR(中間碼)生成特定CPU架構(gòu)的匯編代碼
Assemble: 將匯編代碼轉(zhuǎn)化成二進(jìn)制
Linker: 通常程序會引用其他的二進(jìn)制文件(.a或者framework),但是這些鏈接在程序中沒有正確的地址赔蒲,只是個占位符。Linker的工作就是給這些占位符正確的地址良漱。
更多信息可以參考:The Compiler
一般情況下舞虱,在真實(shí)的編譯器構(gòu)架那種,會將上述過程分成前端和后端兩部分來處理:
在前后端之間傳遞的就是IR(中間碼)母市,而bitcode就是一種特殊形式的中間碼矾兜。原本前后端的工作都是在本地LLVM中完成,雖然Apple沒有給出具體的Bitcode實(shí)現(xiàn)患久,但是通過他們的文檔可以猜測椅寺,是將一部分后端的工作移到了服務(wù)器進(jìn)行。從Xcode上傳IR到服務(wù)器蒋失,服務(wù)器來真對不同的機(jī)型進(jìn)行后續(xù)操作返帕。從而達(dá)到真對不同機(jī)型生成對應(yīng)指令集的二進(jìn)制,而減小報體積的目的篙挽。
二荆萤、打開bitcode設(shè)置
實(shí)際上在Xcode 7中,我們新建一個iOS程序時铣卡,bitcode選項(xiàng)默認(rèn)是設(shè)置為YES的链韭。我們可以在”Build Settings”->”Enable Bitcode”選項(xiàng)中看到這個設(shè)置。
不過煮落,我們現(xiàn)在需要考慮的是三個平臺:iOS敞峭,Mac OS,watchOS蝉仇。
對應(yīng)iOS旋讹,bitcode是可選的。
對于watchOS轿衔,bitcode是必須的骗村。
Mac OS不支持bitcode。
如果我們開啟了bitcode呀枢,在提交包時胚股,下面這個界面也會有個bitcode選項(xiàng):
但是如果其中包含第三方庫,不支持bitcode時候裙秋。需要將”Enable BitCode”設(shè)置成NO琅拌。而且這個選項(xiàng)是缨伊,只要有一個第三方庫不支持,就不能開的进宝。否則連接錯誤刻坊。
確保打包的時候使用的是fembed-bitcode, 而不是fembed-bitcode-maker
You should be aware that a normal build with the -fembed-bitcode-marker option will produce minimal size embedded bitcode sections without any real content. This is done as a way of testing the bitcode-related aspects of your build without slowing down the build process. The actual bitcode content is included when you do an Archive build.
fembed-bitcode-maker:只是簡單的標(biāo)記一下在archive出來的二進(jìn)制中bitcdoe所在的位置。
fembed-bitcode: 真的會生成bitcode指令党晋,并且嵌入到二進(jìn)制中谭胚,這個設(shè)置不止要在app中設(shè)置,同樣你也必須在編譯靜態(tài)鏈接庫的時候使用未玻。而且需要主題的是該參數(shù)系統(tǒng)只默認(rèn)在archive模式下會添加
需要注意的是bitcode只默認(rèn)在archive下編譯灾而。在debug和release下并不會。
如果您開發(fā)的是app那么走正常的打包archive流程就好了扳剿。如果你正在開發(fā).a靜態(tài)庫或者framework旁趟,請注意打包方式設(shè)置為archive,或者在打包腳本中加入-fembed-bitcode參數(shù)。如果需要的話庇绽,需要在Build Settings中打開 DEPLOYMENT_POSTPROCESSING=YES锡搜,設(shè)置Strip Style為debugging。
三瞧掺、檢測是否打開Bitcode
當(dāng)打開bitcdoe選項(xiàng)之后耕餐,我們可以使用otool工具來檢查二進(jìn)制文件中是否包含bitcode段。
針對于靜態(tài)鏈接庫.a文件
otool -arch armv7 -l xxxx.a | grep __bitcode | wc -l
如果是當(dāng)前庫支持.a文件則會輸出一個數(shù)字
如果不支持bitcode則不會出現(xiàn)該數(shù)字辟狈。
上述命令只檢查了armv7架構(gòu)蛾方,同時,也必須使用改指令檢查其他的指令集是否包含bitcode如:arm64上陕,armv7s等等
檢查app或者framework中是否包含bitcode
由于app中二進(jìn)制和framework中二進(jìn)制文件與.a文件存在差異桩砰,因?yàn)樾枰獧z查的是__LLVM段,當(dāng)出現(xiàn)該段的時候释簿,則表示支持bitcdoe亚隅,否則不支持。
otool -l xxxx | grep __LLVM | wc -l
這里otool有個bug庶溶,當(dāng)你的framework使用過lipo命令煮纵,進(jìn)行拆解和合并之后,需要指定指令集進(jìn)行檢查才可以偏螺。
otool -arch armv7 -l xxxx | grep __LLVM | wc -l
BUT, 上述檢查過了之后行疏,也不一定是真的支持bitcode,在實(shí)際的測試中套像,發(fā)現(xiàn)上述檢測命令通過之后酿联,某個使用的第三方庫,依然報錯不支持bitcode。因而最終結(jié)果贞让,還是需要以是否能夠連接成功為準(zhǔn)周崭。重要事情說三遍,上述網(wǎng)上流傳的檢測方法只做參考喳张,最終還是要以實(shí)際效果為準(zhǔn)续镇。
四、最終結(jié)果檢查
如果您是一個APP销部,可以直接進(jìn)行Archive打包摸航,如果是一個庫,則建議建一個Demo工程進(jìn)行打包舅桩,記得要打開bitcode設(shè)置酱虎。
CheckPoint1 連接是否報錯
如果有任何一個庫沒有打開bitcode鏈接,將會出現(xiàn)類似下方的錯誤江咳。只要鏈接過了,那么恭喜了哥放,基本上是OK了歼指。
CheckPoint2 檢查最終效果
使用開發(fā)模式導(dǎo)出ipa
五、選擇出包的方式
這里建議使用第二種甥雕,生成真對具體機(jī)型的包
出現(xiàn)了踩身,Compiling Bitcode,這個過程I缏丁P琛!G偷堋附鸽!
六、最終結(jié)果
在最后輸出的文件中瞒瘸,你能夠看到一個App Thinning的結(jié)果坷备,里面有針對各個機(jī)型的ipa包。