編譯器就是將“一種語(yǔ)言(通常為高級(jí)語(yǔ)言)”翻譯為“另一種語(yǔ)言(通常為低級(jí)語(yǔ)言)”的程序。一個(gè)現(xiàn)代編譯器的主要工作流程:源代碼 (source code) → 預(yù)處理器 (preprocessor) → 編譯器 (compiler) → 目標(biāo)代碼 (object code) → 鏈接器(Linker) → 可執(zhí)行程序 (executables)
傳統(tǒng)編譯器的工作原理基本上都是三段式的,可以分為前端(Frontend)垂券、優(yōu)化器(Optimizer)要门、后端(Backend)形导。前端負(fù)責(zé)解析源代碼婉烟,檢查語(yǔ)法錯(cuò)誤鼻弧,并將其翻譯為抽象的語(yǔ)法樹(shù)(Abstract Syntax Tree)设江。優(yōu)化器對(duì)這一中間代碼進(jìn)行優(yōu)化,試圖使代碼更高效攘轩。后端則負(fù)責(zé)將優(yōu)化器優(yōu)化后的中間代碼轉(zhuǎn)換為目標(biāo)機(jī)器的代碼叉存,這一過(guò)程后端會(huì)最大化的利用目標(biāo)機(jī)器的特殊指令,以提高代碼的性能度帮。
GCC(GNU Compiler Collection歼捏,GNU編譯器套裝)
GCC原名為GNU C語(yǔ)言編譯器(GNU C Compiler)稿存,因?yàn)樗局荒芴幚鞢語(yǔ)言。GCC很快地?cái)U(kuò)展瞳秽,變得可處理C++瓣履。之后也變得可處理Fortran、Pascal练俐、Objective-C袖迎、Java、Ada腺晾,以及Go與其他語(yǔ)言燕锥。
GCC通常是跨平臺(tái)軟件的編譯器首選。有別于一般局限于特定系統(tǒng)與運(yùn)行環(huán)境的編譯器悯蝉,GCC在所有平臺(tái)上都使用同一個(gè)前端處理程序归形,產(chǎn)生一樣的中介碼,因此此中介碼在各個(gè)其他平臺(tái)上使用GCC編譯鼻由,有很大的機(jī)會(huì)可得到正確無(wú)誤的輸出程序暇榴。
總結(jié): mac之前的cocoa框架便是用GCC編譯的,所以ios與mac os都是默認(rèn)使用的GCC編譯器(現(xiàn)在是clang與llvm蕉世,下面會(huì)有介紹) android的系統(tǒng)層因?yàn)槭莑inux內(nèi)核蔼紧,自然也是GCC編譯的,但是android的app因?yàn)槭沁\(yùn)行在Dalvik虛擬機(jī)讨彼,所以用的不是GCC歉井。 windows的應(yīng)用柿祈,大部分都是使用的vs系列的編譯器哈误,畢竟是windows自家的編譯器,用到GCC的不多躏嚎。
Clang
Clang 是一個(gè)C蜜自、C++、Objective-C和Objective-C++編程語(yǔ)言的編譯器前端卢佣。它采用了底層虛擬機(jī)(LLVM)作為其后端重荠。
它的目標(biāo)是提供一個(gè)GNU編譯器套裝(GCC)的替代品。 Clang項(xiàng)目包括Clang前端和Clang靜態(tài)分析器等虚茶。
這個(gè)軟件項(xiàng)目在2005年由蘋果電腦發(fā)起戈鲁,是LLVM編譯器工具集的前端(front-end),目的是輸出代碼對(duì)應(yīng)的抽象語(yǔ)法樹(shù)(Abstract Syntax Tree, AST)嘹叫,并將代碼編譯成LLVM Bitcode婆殿。接著在后端(back-end)使用LLVM編譯成平臺(tái)相關(guān)的機(jī)器語(yǔ)言 。Clang支持C罩扇、C++婆芦、Objective C怕磨。
Clang本身性能優(yōu)異,其生成的AST所耗用掉的內(nèi)存僅僅是GCC的20%左右消约。FreeBSD 10將Clang/LLVM作為默認(rèn)編譯器.
測(cè)試證明Clang編譯Objective-C代碼時(shí)速度為GCC的3倍肠鲫,還能針對(duì)用戶發(fā)生的編譯錯(cuò)誤準(zhǔn)確地給出建議。
總結(jié): GCC目前作為跨平臺(tái)編譯器來(lái)說(shuō)它的兼容性無(wú)異是最強(qiáng)的或粮,兼容最強(qiáng)肯定是以犧牲一定的性能為基礎(chǔ)的导饲,蘋果為了提高性能,因此專門針對(duì)mac系統(tǒng)開(kāi)發(fā)了專用的編譯器clang與llvm被啼,clang用于編譯器前段帜消,llvm用于后端。
LLVM
LLVM浓体,它是一個(gè)編譯器的基礎(chǔ)建設(shè)泡挺,以C++寫成。它是為了任意一種編程語(yǔ)言寫成的程序命浴,利用虛擬技術(shù)娄猫,創(chuàng)造出編譯時(shí)期,鏈結(jié)時(shí)期生闲,運(yùn)行時(shí)期以及“閑置時(shí)期”的優(yōu)化媳溺。
在Xcode4之后,蘋果將Xcode的默認(rèn)編譯器變成了LLVM
Apple(包括中后期的NeXT) 一直使用GCC作為官方的編譯器碍讯。GCC作為開(kāi)源世界的編譯器標(biāo)準(zhǔn)一直做得不錯(cuò)悬蔽,但Apple對(duì)編譯工具會(huì)提出更高的要求。Apple大量使用的Objective-C在GCC中優(yōu)先級(jí)很低捉兴。此外GCC作為一個(gè)純粹的編譯系統(tǒng)蝎困,與IDE配合得很差。加之許可證方面的要求倍啥,Apple無(wú)法使用LLVM 繼續(xù)改進(jìn)GCC的代碼質(zhì)量禾乘。于是,Apple決定從零開(kāi)始寫 C虽缕、C++始藕、Objective-C語(yǔ)言的前端 Clang,完全替代掉GCC氮趋。
正像名字所寫的那樣伍派,Clang只支持C,C++和Objective-C三種C家族語(yǔ)言剩胁。2007年開(kāi)始開(kāi)發(fā)诉植,C編譯器最早完成,而由于Objective-C相對(duì)簡(jiǎn)單摧冀,只是C語(yǔ)言的一個(gè)簡(jiǎn)單擴(kuò)展倍踪,很多情況下甚至可以等價(jià)地改寫為C語(yǔ)言對(duì)Objective-C運(yùn)行庫(kù)的函數(shù)調(diào)用系宫,因此在2009年時(shí),已經(jīng)完全可以用于生產(chǎn)環(huán)境建车。C++的支持也熱火朝天地進(jìn)行著扩借。
總結(jié): 因?yàn)镚CC的編譯器已經(jīng)慢慢無(wú)法滿足蘋果的需求,因此缤至,蘋果開(kāi)發(fā)了Clang與LLVM來(lái)完全取代GCC潮罪,Xcode4之后,蘋果的默認(rèn)編譯器已經(jīng)是LLVM了领斥。Clang作為編譯器前端嫉到,LLVM作為編譯器后端。
后邊的話
隨著 Android P 的逐步應(yīng)用月洛,越來(lái)越多的客戶要求編譯庫(kù)時(shí)用 libc++ 來(lái)代替 libstdc++何恶。libc++ 和 libstdc++ 這兩個(gè)庫(kù)有關(guān)系呢?它們兩個(gè)都是 C++ 標(biāo)準(zhǔn)庫(kù)嚼黔,libc++ 是針對(duì) Clang 編譯器特別重寫的 C++ 標(biāo)準(zhǔn)庫(kù)细层,而 libstdc++ 則是 GCC 的對(duì)應(yīng) C++ 標(biāo)準(zhǔn)庫(kù)了。從 Android 市場(chǎng)來(lái)說(shuō)唬涧,Android NDK 已在具體應(yīng)用中放棄了 GCC疫赎,全面轉(zhuǎn)向 Clang
Clang 是一個(gè) C、C++碎节、Objective-C 和 Objective-C++ 編程語(yǔ)言的編譯器前端捧搞,采用底層虛擬機(jī)(LLVM)作為后端。至于為什么有了 GCC 還要開(kāi)發(fā) Clang狮荔?Clang 相比 GCC 又有什么優(yōu)勢(shì)呢胎撇?網(wǎng)上有很多信息可以參考,這里只簡(jiǎn)單提兩點(diǎn):(1)Clang 采用的是 BSD 協(xié)議的許可證轴合,而 GCC 采用的是 GPL 協(xié)議创坞,顯然前者更為寬松碗短;(2)Clang 是一個(gè)高度模塊化開(kāi)發(fā)的輕量級(jí)編譯器受葛,編譯速度快、占用內(nèi)存小偎谁、有著友好的出錯(cuò)提示总滩。
目前 LLVM 因其寬松的許可協(xié)議,更好的模塊化巡雨、更清晰的架構(gòu)闰渔,成為很多廠商或者組織的選擇,已經(jīng)被蘋果 IOS 開(kāi)發(fā)工具铐望、Facebook冈涧、Google 等各大公司采用茂附,像 Swift、Rust 等語(yǔ)言都選擇了以 LLVM 為后端督弓。