1. 介紹
1.1 GCC
GCC:GNU(Gnu's Not Unix)編譯器套裝(GNU Compiler Collection悯姊,GCC)泼橘,指一套編程語言編譯器择份,以GPL及LGPL許可證所發(fā)行的自由軟件蘸嘶,也是GNU項目的關(guān)鍵部分,也是GNU工具鏈的主要組成部分之一吊骤。GCC(特別是其中的C語言編譯器)也常被認(rèn)為是跨平臺編譯器的事實標(biāo)準(zhǔn)缎岗。1985年由理查德·馬修·斯托曼開始發(fā)展静尼,現(xiàn)在由自由軟件基金會負(fù)責(zé)維護工作白粉。GCC原本用C開發(fā),后來因為LLVM鼠渺、Clang的崛起鸭巴,它更快地將開發(fā)語言轉(zhuǎn)換為C++。
GCC支持的語言:原名為GNU C語言編譯器(GNU C Compiler)拦盹,因為它原本只能處理C語言鹃祖。GCC在發(fā)布后很快地得到擴展,變得可處理C++普舆。之后也變得可處理Fortran恬口、Pascal、Objective-C沼侣、Java祖能、Ada,Go與其他語言蛾洛。
許多操作系統(tǒng)养铸,包括許多類Unix系統(tǒng),如Linux及BSD家族都采用GCC作為標(biāo)準(zhǔn)編譯器轧膘。蘋果電腦預(yù)裝的Mac OS X操作系統(tǒng)也采用這個編譯器钞螟。
GCC目前由世界各地不同的數(shù)個程序員小組維護。它是移植到最多中央處理器架構(gòu)以及最多操作系統(tǒng)的編譯器谎碍。由于GCC已成為GNU系統(tǒng)的官方編譯器(包括GNU/Linux家族)鳞滨,它也成為編譯與創(chuàng)建其他操作系統(tǒng)的主要編譯器,包括BSD家族蟆淀、Mac OS X拯啦、NeXTSTEP與BeOS。
GCC通常是跨平臺軟件的編譯器首選扳碍。有別于一般局限于特定系統(tǒng)與運行環(huán)境的編譯器提岔,GCC在所有平臺上都使用同一個前端處理程序,產(chǎn)生一樣的中介碼笋敞,因此此中介碼在各個其他平臺上使用GCC編譯碱蒙,有很大的機會可得到正確無誤的輸出程序。
GCC支持的主要處理器架構(gòu):ARM、x86赛惩、x86-64哀墓、MIPS、PowerPC等喷兼。
GCC結(jié)構(gòu):GCC的外部接口長得像一個標(biāo)準(zhǔn)的Unix編譯器篮绰。用戶在命令行下鍵入gcc之程序名,以及一些命令參數(shù)季惯,以便決定每個輸入文件使用的個別語言編譯器吠各,并為輸出代碼使用適合此硬件平臺的匯編語言編譯器,并且選擇性地運行連接器以制造可執(zhí)行的程序勉抓。每個語言編譯器都是獨立程序贾漏,此程序可處理輸入的源代碼,并輸出匯編語言碼藕筋。全部的語言編譯器都擁有共通的中介架構(gòu):一個前端解析匹配此語言的源代碼纵散,并產(chǎn)生一抽象語法樹,以及一翻譯此語法樹成為GCC的寄存器轉(zhuǎn)換語言的后端隐圾。編譯器最優(yōu)化與靜態(tài)代碼解析技術(shù)在此階段應(yīng)用于代碼上伍掀。最后,適用于此硬件架構(gòu)的匯編語言代碼以杰克·戴維森與克里斯·弗雷澤發(fā)明的算法產(chǎn)出暇藏。
幾乎全部的GCC都由C/C++寫成蜜笤,除了Ada前端大部分以Ada寫成。
1.2 Clang
Clang:是一個C叨咖、C++瘩例、Objective-C和Objective-C++編程語言的編譯器前端。它采用了底層虛擬機(LLVM)作為其后端甸各。它的目標(biāo)是提供一個GNU編譯器套裝(GCC)的替代品垛贤。作者是克里斯·拉特納(Chris Lattner),在蘋果公司的贊助支持下進行開發(fā)趣倾,而源代碼授權(quán)是使用類BSD的伊利諾伊大學(xué)厄巴納-香檳分校開源碼許可聘惦。Clang主要由C++編寫。
Clang項目包括Clang前端和Clang靜態(tài)分析器等儒恋。這個軟件項目在2005年由蘋果電腦發(fā)起善绎,是LLVM(Low Level Virtual Machine)編譯器工具集的前端(front-end),目的是輸出代碼對應(yīng)的抽象語法樹(Abstract Syntax Tree, AST)诫尽,并將代碼編譯成LLVM Bitcode禀酱。接著在后端(back-end)使用LLVM編譯成平臺相關(guān)的機器語言。
Clang本身性能優(yōu)異牧嫉,其生成的AST所耗用掉的內(nèi)存僅僅是GCC的20%左右剂跟。2014年1月發(fā)行的FreeBSD10.0版將Clang/LLVM作為默認(rèn)編譯器减途。
Clang性能:測試證明Clang編譯Objective-C代碼時速度為GCC的3倍,還能針對用戶發(fā)生的編譯錯誤準(zhǔn)確地給出建議曹洽。
GCC與Clang區(qū)別:
GCC特性:除支持C/C++/ Objective-C/Objective-C++語言外鳍置,還是支持Java/Ada/Fortran/Go等;當(dāng)前的Clang的C++支持落后于GCC送淆;支持更多平臺税产;更流行,廣泛使用偷崩,支持完備辟拷。
Clang特性:編譯速度快;內(nèi)存占用谢吩洹梧兼;兼容GCC;設(shè)計清晰簡單智听、容易理解,易于擴展增強渡紫;基于庫的模塊化設(shè)計到推,易于IDE集成;出錯提示更友好惕澎。
Clang采用的license是BSD莉测,而GCC是GPLv3。
它們使用的宏不同:
(1)GCC定義的宏包括:
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
__GNUG__
(2)Clang除了支持GCC定義的宏之外還定義了:
__clang__
__clang_major__
__clang_minor__
__clang_patchlevel__
2 用法
終端輸入 gcc -help 唧喉、 clang -help 查看
常用:
(1) 查看編譯源文件需要的幾個不同的階段:clang -ccc-print-phases main.m
(2) 查看oc的c實現(xiàn):clang -rewrite-objc main.m
(3) 查看操作內(nèi)部命令: clang -### main.m -o main
(4) 想看清clang的全部過程捣卤,可以先通過-E查看clang在預(yù)處理處理這步做了什么:(這個過程的處理包括宏的替換,頭文件的導(dǎo)入八孝,以及類似#if的處理)clang -E main.m
(5) 預(yù)處理完成后就會進行詞法分析董朝,這里會把代碼切成一個個 Token,比如大小括號干跛,等于號還有字符串等:clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m
(6)然后是語法分析子姜,驗證語法是否正確,然后將所有節(jié)點組成抽象語法樹 AST:clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
(7) 完成這些步驟后就可以開始IR中間代碼的生成了楼入,CodeGen 會負(fù)責(zé)將語法樹自頂向下遍歷逐步翻譯成 LLVM IR哥捕,IR 是編譯過程的前端的輸出后端的輸入:clang -S -fobjc-arc -emit-llvm main.m -o main.ll
(8) 這里 LLVM 會去做些優(yōu)化工作,在 Xcode 的編譯設(shè)置里也可以設(shè)置優(yōu)化級別-01嘉熊,-03遥赚,-0s,還可以寫些自己的 Pass: clang -O3 -S -fobjc-arc -emit-llvm main.m -o main.ll
(9) 生成匯編 clang -S -fobjc-arc main.m -o main.s
(10) 生成目標(biāo)文件 clang -fmodules -c main.m -o main.o
(11) 生成可執(zhí)行文件 clang main.o -o main
(12) 執(zhí)行 ./main
完整步驟:
- 編譯信息寫入輔助文件阐肤,創(chuàng)建文件架構(gòu) .app 文件
- 處理文件打包信息
- 執(zhí)行 CocoaPod 編譯前腳本凫佛,checkPods Manifest.lock
- 編譯.m文件,使用 CompileC 和 clang 命令
- 鏈接需要的 Framework
- 編譯 xib
- 拷貝 xib ,資源文件
- 編譯 ImageAssets
- 處理 info.plist
- 執(zhí)行 CocoaPod 腳本
- 拷貝標(biāo)準(zhǔn)庫
- 創(chuàng)建 .app 文件和簽名