前言
clang提供了一些命令,讓我們可以對編譯的過程進行一些配置和查看,下面我們就對一些常用的指令進行一個基本的介紹.
常用指令
- 查看編譯的步驟
clang -ccc-print-phases main.m
輸出結(jié)果
0: input, “main.m”, objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, “x86_64”, {5}, image
查看編譯結(jié)果 :
clang -rewrite-objc main.m查看操作內(nèi)部命令,可以使用
-###命令
clang -### main.m -o main
- 想看清clang的全部過程,可以先通過
-E查看clang在預編譯處理這步做了什么。
clang -E main.m
clang基本語法介紹
針對下面會用到的語法進行分析
-fmodules
允許modules的語言特性-fsyntax-only
防止編譯器生成代碼,只是語法級別的說明和修改-Xclang <arg>
向clang編譯器傳遞參數(shù)-dump-tokens
運行預處理器,拆分內(nèi)部代碼段為各種token-ast-dump
構(gòu)建抽象語法樹AST,然后對其進行拆解和調(diào)試-S
只運行預處理和編譯步驟-fobjc-arc
為OC對象生成retain和release的調(diào)用-emit-llvm
使用LLVM描述匯編和對象文件-o <file>
輸出到目標文件-c
只運行預處理,編譯和匯編步驟
其余的就不多贅述了, 查看更多的clang使用方法可以在終端輸入clang --hep查看,也可以點擊如下鏈接: clang options
代碼編譯的執(zhí)行步驟拆解
下面我們對iOS代碼編譯的步驟進行一個簡單的拆解,看看內(nèi)部是如何實現(xiàn)的.
預處理完成后就會進行詞法分析,這里會把代碼切成一個個 Token,比如大小括號,等于號還有字符串等。
clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m
然后是語法分析,驗證語法是否正確,然后將所有節(jié)點組成抽象語法樹 AST 。
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
完成這些步驟后就可以開始IR(intermediate representation)中間代碼的生成了,CodeGen 會負責將語法樹自頂向下遍歷逐步翻譯成 LLVM IR,IR 是編譯過程的前端的輸出后端的輸入。
clang -S -fobjc-arc -emit-llvm main.m -o main.ll
這里 LLVM 會去做些優(yōu)化工作,在 Xcode 的編譯設(shè)置里也可以設(shè)置優(yōu)化級別-01,-03,-0s,還可以寫些自己的 Pass,官方有比較完整的 Pass 教程: Writing an LLVM Pass — LLVM 5 documentation 。
clang -O3 -S -fobjc-arc -emit-llvm main.m -o main.ll
Pass 是 LLVM 優(yōu)化工作的一個節(jié)點,一個節(jié)點做些事,一起加起來就構(gòu)成了 LLVM 完整的優(yōu)化和轉(zhuǎn)化。
如果開啟了 bitcode 蘋果會做進一步的優(yōu)化,有新的后端架構(gòu)還是可以用這份優(yōu)化過的 bitcode 去生成。
clang -emit-llvm -c main.m -o main.bc
生成匯編
clang -S -fobjc-arc main.m -o main.s
生成目標文件
clang -fmodules -c main.m -o main.o
生成可執(zhí)行文件,這樣就能夠執(zhí)行看到輸出結(jié)果
clang main.o -o main
執(zhí)行./main
輸出starming rank 14