基于clang插件的一种iOS包大小瘦身方案
引子
\包瘦身,包瘦身,包瘦身,重要的事情說三遍。 \
最近公司一款iOS APP(本文只討論使用Objective C開發(fā)的iOS安裝包)一直在瘦身,我們團(tuán)隊(duì)的APP也愈發(fā)龐大了。而要解決這個(gè)問題,思路主要集中在兩個(gè)方向,資源和代碼。資源主要在于圖片,方法包括移除未被引用的圖片,只使用一套圖片(2x或3x),圖片伸縮等;代碼層面主要思路包括重構(gòu)消除冗余,linkmap中selector引用分析等。除此之外,有沒有別的路徑呢? \
眾所周知,代碼之間存在調(diào)用關(guān)系。假設(shè)iOS APP的主入口為-[UIApplication main],則所有開發(fā)者的源代碼(包括第三方庫)可分為兩類:存在一條調(diào)用路徑,使得代碼可以被主入口最終調(diào)用(稱此類代碼為被最終調(diào)用);不存在一條調(diào)用路徑,使得代碼最終不能被主入口調(diào)用(稱此類代碼為未被最終調(diào)用)。 \
假設(shè)有一個(gè)源代碼級(jí)別的分析工具(或編譯器),可以輔助分析代碼間的調(diào)用關(guān)系,這樣就使得分析最終被調(diào)用代碼成為可能,剩下的就是未被最終調(diào)用的代碼。 \
這種工具目前有成熟可用的嗎?答案是肯定的,就是clang插件。除可用于分析未被最終調(diào)用代碼外,clang還可輔助發(fā)現(xiàn)重復(fù)代碼。 \
LLVM與clang插件
\LLVM工程包含了一組模塊化,可復(fù)用的編輯器和工具鏈。同其名字原意(Low Level Virtual Machine)不同的是,LLVM不是一個(gè)首字母縮寫,而是工程的名字。目前LLVM包含的主要子項(xiàng)目包括: \
作為LLVM提供的編譯器前端,clang可將用戶的源代碼(C/C++/Objective-C)編譯成語言/目標(biāo)設(shè)備無關(guān)的IR(Intermediate Representation)實(shí)現(xiàn)。其可提供良好的插件支持,容許用戶在編譯時(shí),運(yùn)行額外的自定義動(dòng)作。 \
我們的目標(biāo)是使用clang插件減少包大小。其原理是,針對(duì)目標(biāo)工程,基于clang的插件特性,開發(fā)者可以編寫插件以分析所有源代碼。編譯過程中,將插件作為clang的參數(shù)載入并生成各種中間文件。編譯完成后,還需編寫一個(gè)工具去分析所有包含源碼的方法(包括用戶編寫,以及引入的第三方庫源代碼),檢查這些方法中哪些最終可被程序主入口調(diào)用,剩余即是疑似無用代碼。簡單的一個(gè)復(fù)查,移除那些確定無用的代碼,重新編譯,便可以有效去除無用的代碼從而減少包大小。 \
本文相關(guān)內(nèi)容如下: \
如何編寫一個(gè)clang插件并集成到Xcode
\Clone clang源碼并編譯安裝
cd /opt\sudo mkdir llvm\sudo chown `whoami` llvm\cd llvm\export LLVM_HOME=`pwd`\\git clone -b release_39 git@github.com:llvm-mirror/llvm.git llvm\git clone -b release_39 git@github.com:llvm-mirror/clang.git llvm/tools/clang\git clone -b release_39 git@github.com:llvm-mirror/clang-tools-extra.git llvm/tools/clang/tools/extra\git clone -b release_39 git@github.com:llvm-mirror/compiler-rt.git llvm/projects/compiler-rt\\mkdir llvm_build\cd llvm_build\cmake ../llvm -DCMAKE_BUILD_TYPE:STRING=Release\make -j`sysctl -n hw.logicalcpu`\編寫clang插件
\要實(shí)現(xiàn)自定義的clang插件(以C++ API為例),應(yīng)按照以下步驟: \
clang::PluginASTAction(基于consumer的抽象語法樹(Abstract Syntax Tree/AST)前端Action抽象基類) \
clang::ASTConsumer(用于客戶讀取抽象語法樹的抽象基類), \
clang::RecursiveASTVisitor(前序或后續(xù)地深度優(yōu)先搜索整個(gè)抽象語法樹,并訪問每一個(gè)節(jié)點(diǎn)的基類)等基類。
\PluginASTAction::CreateASTConsumer \
PluginASTAction::ParseArgs \
ASTConsumer::HandleTranslationUnit \
RecursiveASTVisitor::VisitDecl \
RecursiveASTVisitor::VisitStmt \
等方法,實(shí)現(xiàn)自定義的分析邏輯。
\static FrontendPluginRegistry::Add\u0026lt;MyPlugin\u0026gt; X(\"my-plugin- name\
總結(jié)
以上是生活随笔為你收集整理的基于clang插件的一种iOS包大小瘦身方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pxe+kickstart无人值守安装
- 下一篇: 原创经验:微信小程序开发总结