1坎背、前言
首先替劈,我認(rèn)為學(xué)習(xí)總結(jié),要有所總得滤,所結(jié)陨献,就是有歸納后,能用自己的話
告訴別人懂更!有所結(jié)眨业,就是有所收獲輸出,一般我認(rèn)為是思維導(dǎo)圖
沮协,所以龄捡,每篇文章前,我都會(huì)先給出文章的腦圖:
2聘殖、正文
注意,本系列總結(jié)不會(huì)引用或提供原課程文章所有的內(nèi)容或代碼行瑞,只會(huì)作出思維導(dǎo)圖奸腺,需要學(xué)習(xí)可購(gòu)買課程 《iOS開(kāi)發(fā)高手課 - 極客時(shí)間》
鏈接器
對(duì)于剛剛接觸程序開(kāi)發(fā)的同學(xué)可能基本不懂,雖然大學(xué)學(xué)習(xí)編譯原理
血久、計(jì)算機(jī)原理
等突照。這些知識(shí)比較抽象,為了讓大家明白氧吐,我們需要站在巨人的肩膀上讹蘑!所以凶伙,本文需要一個(gè)巨人 ----- 編譯器
來(lái)幫助大家理解 鏈接器
是什么矿微?為什么?大家有沒(méi)有想過(guò)械荷,你寫(xiě)的代碼豁翎,最終是怎么樣在計(jì)算機(jī)或手機(jī)上運(yùn)行的角骤??心剥?那現(xiàn)在就讓我們來(lái)了解一下吧邦尊!
《程序是怎樣跑起來(lái)的》
“計(jì)算機(jī)組成原理”圖解趣味版,蹲馬桶就能看懂的編程基礎(chǔ)知識(shí)优烧!普及計(jì)算機(jī)知識(shí)蝉揍。如何向小學(xué)生講解CPU和二進(jìn)制?如何向中學(xué)生講解內(nèi)存和磁盤(pán)畦娄?如何向女高中生講解操作系統(tǒng)的原理又沾?如何向老奶奶說(shuō)明顯示器和電視的不同?
《程序是怎樣跑起來(lái)的》
作者是日本矢澤久雄
熙卡,我們需要解析 編譯器
杖刷,所以需要簡(jiǎn)單入門(mén)級(jí)的計(jì)算機(jī)組成原理
,這本書(shū)就是這樣一本優(yōu)秀的書(shū)驳癌!大家可能通過(guò)微信讀書(shū)讀到電子版: 程序是怎樣跑起來(lái)的 - 微信讀書(shū)滑燃,目前2020年微信還有很多無(wú)限卡會(huì)員的免費(fèi)閱讀,當(dāng)然如果必要花 19.99 元我認(rèn)為也值得颓鲜。好了我們就不多說(shuō)了表窘,下面我主要摘取書(shū)中幾個(gè)示意圖來(lái)解析 編譯器
:
程序運(yùn)行流程示例
上圖展示程序運(yùn)行流程示例,從我們編寫(xiě)的高級(jí)語(yǔ)言的代碼甜滨,到 CPU
(Central Processing Unit乐严,中央處理器)所負(fù)責(zé)的就是解釋和運(yùn)行最終轉(zhuǎn)換成機(jī)器語(yǔ)言的程序內(nèi)容,其實(shí)是 編譯器
工作的流程衣摩。
CPU的四個(gè)構(gòu)成部分
CPU 的內(nèi)部由寄存器
昂验、控制器
、運(yùn)算器
和時(shí)鐘
四個(gè)部分構(gòu)成艾扮,各部分之間由電流信號(hào)相互連通既琴。本文我們不關(guān)注 CPU 的工作原理,本圖主要是后面要解析代碼運(yùn)行在不同 CPU 上栏渺,需要 編譯器
對(duì)不同的 CPU 做兼容和優(yōu)化呛梆。為什么會(huì)有不同的 CPU,上圖就說(shuō)明了磕诊,簡(jiǎn)單來(lái)說(shuō)寄存器填物、控制器、運(yùn)算器和時(shí)鐘的設(shè)計(jì)和數(shù)量不同霎终,那就是不同的 CPU滞磺,所以代碼在不同的 CPU 運(yùn)行就可能有不一樣的要求,這是硬件方面莱褒。這里就不深入解析了击困,大家可以看看本書(shū),或自行搜索了解更多。
CPU負(fù)責(zé)解析并運(yùn)行從源代碼編譯而來(lái)的本地代碼
CPU 只能解釋其自身固有的機(jī)器語(yǔ)言
阅茶,機(jī)器語(yǔ)言的程序稱為本地代碼
(native code)蛛枚。不同的CPU能解釋的機(jī)器語(yǔ)言的種類也是不同的。例如脸哀,CPU有 x86
蹦浦、MIPS
、SPARC
撞蜂、PowerPC
盲镶、ARM
等幾種類型,它們各自的機(jī)器語(yǔ)言是完全不同的蝌诡。
程序員用C語(yǔ)言等編寫(xiě)的程序溉贿,在編寫(xiě)階段僅僅是文本文件
,文本文件(排除文字編碼的問(wèn)題)在任何環(huán)境下都能顯示和編輯浦旱,我們稱之為源代碼
宇色。通過(guò)對(duì)源代碼進(jìn)行編譯,就可以得到本地代碼
闽寡。到目前代兵,我們了解了代碼編譯的流程啦,那具體的流程又是怎么樣的呢爷狈?在講解之前植影,我們先看看 CPU 的歷史,這樣對(duì)我們了解編譯器也起到重要作用啊~
這里解析一下各種 CPU :
-
x86
:美國(guó) Intel (英特爾)的微處理器涎永,是按照8086思币、80286、80386羡微、80486谷饿、Pentium(奔騰)……這樣的順序不斷升級(jí)的。因?yàn)檫@些型號(hào)的后面都帶有86妈倔,所以總稱為x86博投。32位處理器 Intel官方文檔里面稱為“IA-32”,64位處理器稱“x86_64”盯蝴、“x86-64”毅哗,又稱x64,即英文詞 64-bit extended捧挺,64位拓展的簡(jiǎn)寫(xiě)虑绵。這個(gè)64位有點(diǎn)故事
,下面講∶隼樱現(xiàn)在的PC機(jī)都是64位 CPU 啦翅睛。 -
MIPS
:美國(guó) MIPS 科技公司開(kāi)發(fā)的CPU,曾出現(xiàn)過(guò)面向 MIPS工作站的 Windows,不過(guò)現(xiàn)在市面上已經(jīng)不再出售了捕发。 -
SPARC
:美國(guó) SUN系統(tǒng)開(kāi)發(fā)的CPU疏旨,很多工作站都采用了該CPU。 -
PowerPC
:是美國(guó)蘋(píng)果爬骤、IBM充石、摩托羅拉共同開(kāi)發(fā)的CPU莫换,蘋(píng)果的Power Mac及IBM的工作站都采用了該CPU霞玄,不過(guò)現(xiàn)在的Mac采用的是Intel的x86系列CPU。 -
ARM
ARM拉岁,安謀控股公司(英語(yǔ):ARM Holdings plc.)坷剧,又稱ARM公司。ARM的前身為艾康電腦喊暖,1978年于英國(guó)劍橋創(chuàng)立惫企。2016年7月18日,日本軟銀集團(tuán)斥資3.3萬(wàn)億日元(約合311億美元)收購(gòu)了ARM公司陵叽。ARM架構(gòu)版本從 ARMv3 到 ARMv7 支持32位狞尔,2011年發(fā)布的ARMv8-A 架構(gòu)添加了對(duì)64位支持。現(xiàn)在移動(dòng)設(shè)備主流就是使用 ARM 巩掺。
x86-64 的故事
x84_64
是 x86
32位 CPU 開(kāi)始邁向64位的時(shí)候偏序,有2種選擇:
- 向下兼容x86。
- 完全重新設(shè)計(jì)指令集胖替,不兼容x86研儒。
結(jié)果在 1999 年 AMD
搶跑了!比 Intel
率先制造出了商用的兼容 x86 的CPU独令,AMD稱之為 AMD64
端朵,搶了64位PC的第一桶金,得到了用戶的認(rèn)同燃箭。所以 Intel 為了面子就選擇了設(shè)計(jì)一種不兼容x86的全新64為指令集冲呢,稱之為IA-64
(Itanium,安騰)招狸,但是比 AMD 晚了一步敬拓,因?yàn)?AMD64 能有效地把x86架構(gòu)移至64位的環(huán)境,并且能兼容原有的x86應(yīng)用程序瓢颅。并且 IA-64 也挺慘淡的恩尾,因?yàn)槭侨略O(shè)計(jì)的CPU,沒(méi)有編譯器挽懦,也不支持 Windows(微軟把intel給忽悠了翰意,承諾了會(huì)出對(duì)應(yīng)的 Windows server 版,但是遲遲拿不出東西),處理器本身和軟件移植的成本難以控制冀偶,導(dǎo)致 IA-64 最終流產(chǎn)醒第。后來(lái)不得不在時(shí)機(jī)落后的情況下也開(kāi)始支持AMD64的指令集,但是換了個(gè)名字进鸠,叫x86_64
稠曼,表示是 x86 指令集的64擴(kuò)展,大概是不愿意承認(rèn)這玩意是AMD設(shè)計(jì)出來(lái)的客年?現(xiàn)時(shí)英特爾稱之為“Intel 64
”霞幅,在之前曾使用過(guò)“Clackamas Technology” (CT)、“IA-32e”及“EM64T
”等名字量瓜。換湯不換藥司恳,核心與 AMD64 幾乎相同,猶如一對(duì)孿生兄弟绍傲,其實(shí)都是 x86-64 架構(gòu)扔傅。當(dāng)年有媒體為 EM64T 起了“iAMD64
”別名,諷刺 Intel 在迎擊 AMD 的民用64位技術(shù)上烫饼,使用了 AMD 的技術(shù)猎塞,直接把 AMD64 吸納過(guò)來(lái),并以新名重新包裝使用杠纵,所以最后荠耽,Intel 索性將此技術(shù)正式命名為 Intel 64
。
所以淡诗,CPU 的 32 位還是 64位骇塘,一般是用 x86-64
表示64位,而32位現(xiàn)在已經(jīng)沒(méi)有了韩容。另外款违,不同公司對(duì) x86-64 架構(gòu),名字上還是有一些區(qū)別群凶,蘋(píng)果公司和RPM包管理員以“x86-64”或“x86_64”稱呼此64位架構(gòu)插爹。甲骨文公司及Microsoft稱之為“x64”,BSD家族及其他Linux發(fā)行版則使用“x64-64”请梢,32位版本則稱為“i386”(或 i486/586/686)赠尾,Arch Linux用x86_64稱呼此64位架構(gòu)。
最后一個(gè)問(wèn)題毅弧,x86气嫁、x86_64主要的區(qū)別是什么?就是32位和64位的問(wèn)題够坐,x86 中只有8個(gè)32位通用寄存器寸宵,分別是 eax,ebx,ecx崖面,edx, ebp, esp, esi, edi。x86_64 把這8個(gè)通用寄存器擴(kuò)展成了64位的梯影,并且比x86增加了若干個(gè)寄存器(好像增加了8個(gè)巫员,變成了總共16個(gè)通用寄存器)。譬如四個(gè)通用寄存器(RAX, RBX, RCX, RDX)是由32位的(EAX, EBX, ECX, EDX)64位擴(kuò)展而來(lái)甲棍,相應(yīng)的還有指針寄存器(RIP, RBP, RSP, RSI, RDI)简识,以及增加八個(gè)通用寄存器(R8~R15)等等。 這些資源只可在x64處理器的64位模式下使用感猛,在用來(lái)支持x86軟件的遺留模式和兼容模式中是不可見(jiàn)的七扰。
以上內(nèi)容和關(guān)于 CPU 更多歷史和資料,可查看來(lái)源: x86 - 維基百科 唱遭、 x86-64 - 維基百科戳寸,自由的百科全書(shū) 和 X86、X64和X86_64區(qū)別 拷泽。
轉(zhuǎn)換成本地代碼后就變成了同樣的語(yǔ)言
前面提到,CPU 只能解釋其自身固有的機(jī)器語(yǔ)言
袖瞻,而轉(zhuǎn)換成機(jī)器語(yǔ)言的程序就是本地代碼
司致。不管用那種編程語(yǔ)言編寫(xiě)的源代碼,最后只要能翻譯(編譯
)成本地代碼聋迎,那么 CPU 就能理解脂矫。這個(gè)過(guò)程,其實(shí)就是編譯器
的工作內(nèi)容霉晕!
同樣的源代碼可以轉(zhuǎn)換成適用于不同處理器的本地代碼
根據(jù) CPU 類型的不同庭再,本地代碼的類型也不同。因而牺堰,編譯器不僅和編程語(yǔ)言的種類有關(guān)拄轻,和 CPU 的類型也是相關(guān)的。這就是前面為什么要重點(diǎn)說(shuō) CPU 相關(guān)知識(shí)伟葫,現(xiàn)在是不是有點(diǎn)理解編譯器
了恨搓!
把C語(yǔ)言等高級(jí)編程語(yǔ)言
編寫(xiě)的源代碼轉(zhuǎn)換成本地代碼
的程序稱為編譯器
,這個(gè)轉(zhuǎn)換過(guò)程經(jīng)過(guò)語(yǔ)法解析筏养、句法解析斧抱、語(yǔ)義解析等。每種編程語(yǔ)言編寫(xiě)的源代碼都需要其專用的編譯器渐溶,或者是同用類編譯器辉浦,比如 C 家族(C/C++)的編輯器。
Windows中的編譯和鏈接機(jī)制
剛才說(shuō)的高級(jí)編程語(yǔ)言
的源代碼轉(zhuǎn)換成本地代碼
茎辐,本地文件是無(wú)法直接運(yùn)行的宪郊,還需要把多個(gè)目標(biāo)文件結(jié)合眉睹,生成1個(gè)可執(zhí)行文件(圖中是EXE文件,針對(duì)Windows系統(tǒng)的废膘。)竹海,這個(gè)處理就是鏈接
,運(yùn)行連接的程序就稱為鏈接器
(linkage editor丐黄,或連結(jié)器)斋配。至此,我們終于說(shuō)到鏈接器啦9喙搿<枵!現(xiàn)在明白鏈接器是在那里使用了吧桂对?
存儲(chǔ)著目標(biāo)文件的實(shí)體荔睹,并直接和可執(zhí)行文件結(jié)合的庫(kù)文件形式稱為靜態(tài)鏈接庫(kù)
,經(jīng)常簡(jiǎn)稱為靜態(tài)庫(kù)
怕膛。與之相反的,就叫動(dòng)態(tài)鏈接庫(kù)
(動(dòng)態(tài)庫(kù))宅此,就是參與鏈接過(guò)程机错,但是并不會(huì)與可執(zhí)行文件結(jié)合,就是說(shuō)鏈接時(shí)會(huì)做標(biāo)記父腕,綁定的地址在加載后再?zèng)Q定弱匪。這個(gè)不理解,沒(méi)關(guān)系璧亮,下面還會(huì)在詳細(xì)說(shuō)說(shuō)萧诫,下一章的內(nèi)容就是動(dòng)態(tài)鏈接庫(kù)
和動(dòng)態(tài)鏈接器
的內(nèi)容,所以枝嘶,這個(gè)需要了解一下帘饶。
至此,我們就過(guò)編譯器相關(guān)的內(nèi)容躬络,簡(jiǎn)單的解說(shuō)了一下尖奔,不知道大家有點(diǎn)理解沒(méi)有,下面穷当,我們?cè)谏钊胍稽c(diǎn)提茁,了解編譯器的具體工作流程。
編譯器
編譯器一般采用 Three-Phase
(三階段/三相)架構(gòu)設(shè)計(jì):
- 編譯器前端(Front end)
- 中間端(Middle end馁菜,或叫優(yōu)化器茴扁,Optimizer)
- 后端(Backend)
編譯器前端(Front end)
- Preprocess - 預(yù)處理
- Parser - 解析器
- Lexical Analysis - 詞法分析
- Semantic Analysis - 語(yǔ)義分析
- AST(Abstract Syntax Tree,抽象語(yǔ)法樹(shù))
- Static Analysis - 靜態(tài)分析
- CodeGen - IR 代碼生成
編譯器前端的任務(wù):預(yù)處理
汪疮、語(yǔ)法分析
峭火,語(yǔ)義分析
毁习,在這個(gè)過(guò)程中,也會(huì)進(jìn)行類型檢查卖丸,如果發(fā)現(xiàn)錯(cuò)誤或者警告會(huì)標(biāo)注出來(lái)在哪一行等纺且,最終生成中間代碼 IR(Intermediate Representation,中間端表達(dá)式)稍浆。對(duì)于 LLVM
來(lái)說(shuō)载碌,前端就是 CLang
。
中間端(Middle end衅枫,或叫優(yōu)化器嫁艇,Optimizer)
- LLVM Bitcode - 生成字節(jié)碼
- Assemble - 生成Target相關(guān)匯編
- Assemble - 生成Target相關(guān) Object(Mach-o)
- Link 生成 Executable 可執(zhí)行文件
優(yōu)化是非常重要的,很多直接轉(zhuǎn)換來(lái)的代碼是不合適且消耗內(nèi)存的弦撩,因?yàn)槭侵苯愚D(zhuǎn)換步咪,所以必然會(huì)有這樣的問(wèn)題,而優(yōu)化放在這一步的好處在于前端不需要考慮任何優(yōu)化過(guò)程益楼,減少了前端的開(kāi)發(fā)工作猾漫。中間代碼要經(jīng)過(guò)一系列的優(yōu)化,優(yōu)化用的是 Pass
偏形,中間代碼的優(yōu)化也可以開(kāi)發(fā)者自己編寫(xiě)静袖,可以插入一個(gè) Pass
。
后端(Backend)
- ARM(ARM俊扭,安謀控股公司)
- x86|x86-64(Intel,英特爾)
- PowerPC(Apple & IBM & Motorola坠陈,AIM聯(lián)盟)
編譯器后端會(huì)進(jìn)行機(jī)器無(wú)關(guān)的代碼優(yōu)化萨惑,生成機(jī)器語(yǔ)言,并且進(jìn)行機(jī)器相關(guān)的代碼優(yōu)化仇矾。對(duì)于 iOS 的編譯過(guò)程庸蔼,后端的處理:LLVM優(yōu)化器會(huì)進(jìn)行BitCode的生成,鏈接期優(yōu)化等贮匕,LLVM機(jī)器碼生成器會(huì)針對(duì)不同的架構(gòu)姐仅,比如arm64等生成不同的機(jī)器碼。
這里的后端刻盐,最終就是生成對(duì)應(yīng)的 CPU 能執(zhí)行的機(jī)器語(yǔ)言掏膏,前面已經(jīng)介紹過(guò) CPU 相關(guān)的。
上面說(shuō)了編譯器的組成架構(gòu)和簡(jiǎn)要的工作流程敦锌,詳細(xì)的工作流程這里就不多說(shuō)了馒疹,因?yàn)橐呀?jīng)有很多優(yōu)秀的內(nèi)容了,并且本文的主要目的是要說(shuō)明編譯器是什么乙墙!你知道它是什么后颖变,再了解它是怎么用生均,有什么優(yōu)缺點(diǎn),自然不是難事腥刹!以上的部分內(nèi)容是針對(duì) iOS 和 LLVM 的马胧,所以,我們接下來(lái)就來(lái)介紹一下 LLVM 編譯器吧衔峰!
要講解 LLVM
前佩脊,有必要的說(shuō)說(shuō) GCC
(GNU Compiler Collection,GNU編譯器套件) 朽色,因?yàn)樘O(píng)果最初也是使用 GCC邻吞,后來(lái)慢慢的替換為 LLVM 的。
GCC(GNU Compiler Collection葫男,GNU編譯器套件)
原名:GNU C語(yǔ)言編譯器(GNU C Compiler)抱冷,通常是跨平臺(tái)軟件的編譯器首選。(在所有平臺(tái)上都使用同一個(gè)前端處理程序梢褐,產(chǎn)生一樣的中間碼)旺遮。
但是由于以下問(wèn)題,導(dǎo)致蘋(píng)果轉(zhuǎn)為 LLVM:
- GCC 的 Objective-C Frontend 不給力
- GCC 插件盈咳、工具耿眉、IDE的支持薄弱
GCC的前端不是蘋(píng)果提供維護(hù)的,想要添加一些語(yǔ)法提示等功能還得去求GCC的前端去做鱼响。 很多編譯器特性沒(méi)有鸣剪,自動(dòng)補(bǔ)全、代碼提示丈积、warning筐骇、靜態(tài)分析等這些流程不是很給力,都是需要IDE調(diào)用底層命令完成的江滨,結(jié)果需要以插件的形式暴露出來(lái)铛纬,這一塊GCC做的不是很好。
LLVM
早年Apple一直使用 GCC
作為官方的編譯器唬滑,但Apple對(duì) GCC 的性能不滿意告唆,再者 Objective-C
在 GCC 中優(yōu)先級(jí)低,GCC 對(duì) Objective-C 語(yǔ)言新特性的支持程度也不高晶密。因此Apple一直在尋找compiler(編譯器)的開(kāi)源替代品擒悬,于是他們將目光轉(zhuǎn)移到LLVM
身上。
來(lái)自維基百科:關(guān)于LLVM
這個(gè)名字的來(lái)源惹挟,LLVM的命名最早源自于底層虛擬機(jī)(Low Level Virtual Machine)的首字母縮寫(xiě)茄螃,由于這個(gè)項(xiàng)目的范圍并不局限于創(chuàng)建一個(gè)虛擬機(jī),這個(gè)縮寫(xiě)導(dǎo)致了廣泛的疑惑连锯。
LLVM 就是 LLVM
, 并不是 Low Level Virtual Machine(底層虛擬機(jī))的簡(jiǎn)寫(xiě)归苍!現(xiàn)今LLVM 已單純成為一個(gè)品牌用狱!根據(jù)官網(wǎng)說(shuō)明:
The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Despite its name, LLVM has little to do with traditional virtual machines. The name "LLVM" itself is not an acronym; it is the full name of the project.
LLVM項(xiàng)目是模塊化和可重用的編譯器及工具鏈技術(shù)的集合。盡管名稱如此拼弃,LLVM與傳統(tǒng)虛擬機(jī)關(guān)系不大夏伊。名稱“ LLVM”本身不是縮寫(xiě)。它是項(xiàng)目的全名吻氧。
2000年溺忧,伊利諾伊大學(xué)厄巴納-香檳分校(University of Illinois at Urbana-Champaign 簡(jiǎn)稱UIUC)這所享有世界聲望的一流公立研究型大學(xué)的 Chris Lattner
(克里斯·拉特納,twitter @clattner_llvm ) 和 Vikram Adve
(維克拉姆·艾夫)想要為所有靜態(tài)及動(dòng)態(tài)語(yǔ)言創(chuàng)造出動(dòng)態(tài)的編譯技術(shù)盯孙,而開(kāi)發(fā)的編譯器開(kāi)發(fā)工具套件鲁森。2005年,蘋(píng)果電腦雇用了 Chris Lattner 克里斯·拉特納及他的團(tuán)隊(duì)為蘋(píng)果電腦開(kāi)發(fā)應(yīng)用程序系統(tǒng),LLVM 涉及范圍越來(lái)越大振惰,可以用于常規(guī)編譯器歌溉,JIT編譯器,匯編器骑晶,調(diào)試器痛垛,靜態(tài)分析工具等一系列跟編程語(yǔ)言相關(guān)的工作。Chris Lattner 后來(lái)又開(kāi)發(fā)了 Clang桶蛔,使得 LLVM 直接挑戰(zhàn) GCC 的地位匙头。
Chris Lattner 大神簡(jiǎn)介
Chris Lattner
生于 1978 年,2005年加入蘋(píng)果仔雷,將蘋(píng)果使用的 GCC 全面轉(zhuǎn)為 LLVM蹂析。2010年開(kāi)始主導(dǎo)開(kāi)發(fā) Swift 語(yǔ)言。2017年1月,克里斯·拉特納 辭去在蘋(píng)果的工作棘捣,入職特斯拉汽車,負(fù)責(zé)自動(dòng)駕駛軟件的開(kāi)發(fā)。2017年8月14日贸人,克里斯·拉特納 發(fā)表Twitter表示將于一周后加入聚焦于深度學(xué)習(xí)與人工智能研發(fā)的Google Brain團(tuán)隊(duì)。
Xcode 歷史
Clang 編譯效率是 GCC 的3倍褒颈,編譯器性能好廓推,編譯出的文件小。LLVM 3.0 發(fā)布已完整支持所有 ISO C++ 標(biāo)準(zhǔn)锻煌,代表著 LLVM 正式走向成熟妓布。所以,也標(biāo)志著 Xcode 的變化宋梧。
- Xcode3:GCC前端-LLVM后端匣沼,
- Xcode4.2:Clang-LLVM 3.0 成為默認(rèn)編譯器,
- Xcode5: GCC 被廢棄捂龄,新的編譯器是 LLVM 5.0
從 GCC前端 到 LLVM后端的編譯器释涛,到 Clang-LLVM 的編譯器加叁,一步步收回對(duì)編譯工具鏈的控制,也為 Swift 的出現(xiàn)奠定基礎(chǔ)唇撬。所以它匕,Chris Lattner 真的是大神!
LLVM 工具鏈
最后用這張圖來(lái)表示完整的LLVM工具鏈集合的六大執(zhí)行單元窖认。
-
詞法分析
: 將源代碼中的所有字符切分成記號(hào)(Token)的序列豫柬。包括了詞法分析器、記號(hào)序列化生成器和掃描器扑浸,不過(guò)掃描器常常作為詞法分析器的第一階段烧给。 -
語(yǔ)法分析
: 分析符合一定語(yǔ)法規(guī)則的一串符號(hào),它通常會(huì)生成一個(gè)抽象語(yǔ)法樹(shù)(AST - Abstract Syntax tree)喝噪,用于表示記號(hào)之間的語(yǔ)法關(guān)系础嫡。 -
語(yǔ)義分析
: 通過(guò)語(yǔ)法分析的解析后,這個(gè)過(guò)程將從源代碼中收集必要的語(yǔ)義信息仙逻,通常包括類型檢查驰吓、在使用之前確保聲明了變量等等。 -
中間代碼(IR)生成
:代碼在這個(gè)階段會(huì)轉(zhuǎn)換為中間表示式(IR)系奉,這是一種中立的語(yǔ)言檬贰,與源語(yǔ)言(前端)和機(jī)器(后端)無(wú)關(guān)。 -
優(yōu)化中間表達(dá)式
:中間代碼常常會(huì)有冗余和死代碼的情況出現(xiàn)缺亮,而優(yōu)化器可以處理這些問(wèn)題以獲得更優(yōu)異的性能翁涤。 -
生成目標(biāo)代碼
: 最后后端會(huì)生成在目標(biāo)機(jī)器上運(yùn)行的機(jī)器碼萌踱,我們也將其稱之為目標(biāo)代碼葵礼。
鏈接器
- 為什么要讓鏈接器做符號(hào)和地址綁定?不綁定的話并鸵,又會(huì)有什么問(wèn)題鸳粉?
- 鏈接器為什么還要把項(xiàng)目中的多個(gè) Mach-O 文件合并成一個(gè)。
回到本文開(kāi)始的問(wèn)題园担,大家對(duì)這2個(gè)問(wèn)題心中有答案了嗎届谈?
鏈接器
的作用是將符號(hào)綁定到地址上,符號(hào)表
是內(nèi)存地址與函數(shù)名弯汰、文件名艰山、行號(hào)的映射表。所以咏闪,變量曙搬、函數(shù)與地址綁定,CPU 才能理解解析代碼
。而為什么要多個(gè) Mach-O 文件合并一個(gè)最終的 Mach-O
纵装?過(guò)去面向過(guò)程編程時(shí)征讲,可以寫(xiě)一個(gè)文件中,而現(xiàn)在主流是面向?qū)ο舐Р粒陀蓄惻c對(duì)象關(guān)系稳诚,所以一般是分類、分模塊瀑踢、分空間來(lái)編寫(xiě)源代碼扳还,所以,需要把這些類與對(duì)象和他們之前調(diào)用關(guān)系綁定一起橱夭,合并成一個(gè)Mach-O
氨距。為了更好理解這個(gè) Mach-O
,需要了解 CPU 是怎么執(zhí)行他們的棘劣,這里就不展開(kāi)了俏让,感興趣的同學(xué)可以先自行搜索了解更多。
觸類旁通
讓我們?cè)俅位仡櫼幌戮幾g器的工作流程茬暇,以 LLVM 為例首昔,從 iOS 開(kāi)發(fā)視角來(lái)看這個(gè)問(wèn)題。這張圖片來(lái)源:從Swift橋接文件到Clang-LLVM - 掘金糙俗。詳細(xì)的編譯器過(guò)程大家可以參考文章勒奇,這里就不過(guò)多重復(fù)。
另外巧骚,原文還提到很多的概念赊颠,這里也不一一提出了,具體可以看看本文最前面的思維導(dǎo)圖劈彪。比如:
-
AST
(Abstract Syntax Tree竣蹦,抽象語(yǔ)法樹(shù)) -
Mach-O
:是 Mach Object 文件格式的縮寫(xiě),它是一種用于可執(zhí)行文件沧奴,目標(biāo)代碼痘括,動(dòng)態(tài)庫(kù),內(nèi)核轉(zhuǎn)儲(chǔ)的文件格式滔吠。作為a.out格式的替代远寸,Mach-O提供了更強(qiáng)的擴(kuò)展性,并提升了符號(hào)表中信息的訪問(wèn)速度屠凶。 -
符號(hào)表
:是內(nèi)存地址與函數(shù)名、文件名肆资、行號(hào)的映射表矗愧。格式如:<起始地址> <結(jié)束地址> <函數(shù)> [<文件名:行號(hào)>] -
dyld
(the dynamic link editor):當(dāng)加載 Mach-O 文件時(shí),動(dòng)態(tài)鏈接器會(huì)先檢查是否有共享緩存。每個(gè)進(jìn)程都會(huì)在自己的地址空間映射這些共享緩存唉韭,這樣做可以起到優(yōu)化App啟動(dòng)速度的作用夜涕。 -
LLDB
(LLVM項(xiàng)目的調(diào)試器組件) -
ASLR
(Address space layout randomization,地址空間配置隨機(jī)加載) -
解釋器
:不需要經(jīng)過(guò)編譯的過(guò)程属愤,而是在執(zhí)行的時(shí)候通過(guò)一個(gè)中間的解釋器將代碼解釋為CPU可以執(zhí)行的代碼女器。JavaScript、Python住诸、PHP等都是直譯式語(yǔ)言驾胆。 -
Bitcode
:字節(jié)碼 -
SIL
(Swift Intermediate Language):AST 和LLVM IR之間的另一種中間代碼表示形式。主要是用來(lái)彌補(bǔ)一些 Clang編譯器的缺陷贱呐,如無(wú)法執(zhí)行一些高級(jí)分析丧诺,可靠的診斷和優(yōu)化等。
中間代碼 LLVM IR
中間端表達(dá)式 IR(Intermediate Representation)奄薇,有3種表示形式驳阎,但本質(zhì)是等價(jià)的,就好比水可以有氣體馁蒂,液體呵晚,固體3種形式。
-
text
:便于閱讀的文本格式沫屡,類似于匯編語(yǔ)言饵隙,拓展名.II
。生成命令:$ clang -S -emit-llvm main.m
-
memory
:內(nèi)存格式谁鳍,開(kāi)發(fā)時(shí)操作 LLVM IR癞季。 -
bitcode
:二進(jìn)制格式,拓展名.bc
倘潜。生成命令:$ clang -c -emit-llvm main.m
廣義與狹義 LLVM 與 Clang 的關(guān)系
廣義 LLVM
:整個(gè) LLVM 架構(gòu)绷柒。
狹義 LLVM
:LLVM 后端(代碼優(yōu)化,目標(biāo)文件生成等涮因。)
Clang
(C Lange Family Frontend for LLVM)废睦,發(fā)音為/?kl??/
,是C养泡、C++嗜湃、Objective-C、Objective-C++ 編程語(yǔ)言的編譯器前端澜掩。
所以购披,非特指,LLVM 就是廣義 LLVM肩榕,指整個(gè)LLVM項(xiàng)目刚陡,包括Clang前端。另外,本文主要講解了 LLVM 在 Apple 平臺(tái)上的使用筐乳,LLVM 現(xiàn)在被作為實(shí)現(xiàn)各種靜態(tài)和運(yùn)行時(shí)編譯語(yǔ)言的通用基礎(chǔ)結(jié)構(gòu)歌殃,可以使用 LLVM 來(lái)編譯Ruby,Python蝙云,Haskell氓皱,Java,D勃刨,PHP波材,Pure,Lua和許多其他語(yǔ)言朵你。LLVM 的主要優(yōu)勢(shì)在于其多功能性各聘,靈活性和可重用性,這就是它被用于各種不同任務(wù)的原因:從輕量級(jí)JIT編譯嵌入式語(yǔ)言(如Lua)到編譯Fortran代碼(用于大型超級(jí))電腦抡医。
相比較GCC吼拥,Clang具有哪些優(yōu)點(diǎn)
- Clang是:
- LLVM項(xiàng)目的一個(gè)子項(xiàng)目
- 基于LLVM架構(gòu)的 C趴俘、C++摩骨、Objective-C疆虚、Objective-C++ 編譯器前端
- Clang優(yōu)點(diǎn):
- 編譯速度快:在某些平臺(tái)上,Clang的編譯速度顯著的快過(guò)GCC
- 占用內(nèi)存兴ⅰ:Clang生成的AST(語(yǔ)法樹(shù))所占用的內(nèi)存是GCC的五分之一左右
- 模塊化設(shè)計(jì):Clang采用基于庫(kù)的模塊化設(shè)計(jì)镰矿,易于IDE集成及其他用途的重用
- 診斷信息可讀性強(qiáng):在編譯過(guò)程中,Clang創(chuàng)建并保存了大量詳細(xì)的元數(shù)據(jù)俘种,有利于調(diào)試
- 設(shè)計(jì)清晰簡(jiǎn)單秤标,容易理解,易于擴(kuò)展增強(qiáng)
Swift 如何橋接 Objtive-C 文件到 Clang-LLVM 宙刘?
在 Swift 的項(xiàng)目中苍姜,Objtive-C 代碼可以生成 IR(Intermediate Representation,中間端表達(dá)式)悬包,從而與 Swift 生成的 IR 聯(lián)通衙猪。這個(gè)也是分段(層)的好處,編譯器中間端(Middle end布近,或叫優(yōu)化器垫释,Optimizer),作為中間者通過(guò)前端獲取 IR 撑瞧,從而不用關(guān)心前端的編程語(yǔ)言是什么棵譬,這些設(shè)計(jì)特點(diǎn),帶來(lái)了非常大的好處预伺。
假如有N種語(yǔ)言(C茫船、OC琅束、C++、Swift...)的前端算谈,同時(shí)也有M個(gè)架構(gòu)(模擬器、arm64料滥、x86...)的Target然眼,是否就需要 N × M 個(gè)編譯器?
三相架構(gòu)的價(jià)值就體現(xiàn)出來(lái)了葵腹,通過(guò)共享優(yōu)化器的中轉(zhuǎn)高每,很好的解決了這個(gè)問(wèn)題。
假如你需要增加一種語(yǔ)言践宴,只需要增加一種前端鲸匿;假如你需要增加一種處理器架構(gòu),也只需要增加一種后端阻肩,而其他的地方都不需要改動(dòng)带欢。這復(fù)用思想很牛逼吧。來(lái)自:淺談iOS編譯過(guò)程 - 簡(jiǎn)書(shū)
需要注意的是 Clang 是基于LLVM架構(gòu)的 C烤惊、C++乔煞、Objective-C、Objective-C++ 編譯器前端柒室,不包括 Swift
渡贾!蘋(píng)果針對(duì) Swift 做了單獨(dú)的前端,與 Clang 是非常相似的雄右,特點(diǎn)就是增加了 SIL
(Swift Intermediate Language)空骚。詳細(xì)具體可以查看 WWDC 視頻:What's New in LLVM - WWDC 2016 - Videos - Apple Developer 、Behind the Scenes of the Xcode Build Process - WWDC 2018 - Videos - Apple Developer擂仍。
方舟編譯器
當(dāng)前方舟編譯器支持Java/Kotlin程序字節(jié)碼的前端輸入囤屹,其它編程語(yǔ)言的支持(如 C/C++/JS 等)還在規(guī)劃中,方舟編譯器的中間表示(IR)轉(zhuǎn)換器將前端輸入轉(zhuǎn)換成方舟IR防楷,并輸送給后端的優(yōu)化器牺丙,最終生成二進(jìn)制文件,二進(jìn)制文件與編譯器運(yùn)行時(shí)庫(kù)文件鏈接生成可執(zhí)行文件复局,在方舟的運(yùn)行環(huán)境中就可執(zhí)行該文件冲簿。
方舟編譯器IR是支持程序編譯和運(yùn)行的中間程序表示。程序源代碼中的任何信息對(duì)于程序分析和優(yōu)化都是有幫助的亿昏,所以方舟IR的目標(biāo)是盡可能完整詳細(xì)地提供源程序的信息峦剔。
首次開(kāi)源范圍是編譯器 IR( Intermediate Representation)、RC(Reference Counting)和多語(yǔ)言設(shè)計(jì)思想等角钩,用于與業(yè)界吝沫、學(xué)術(shù)界溝通交流呻澜。后續(xù)將陸續(xù)開(kāi)源編譯器前端、后端惨险,支持其它語(yǔ)言(如 JavaScript)的編譯等羹幸,當(dāng)前部分Java語(yǔ)言特性和JVM虛擬機(jī)特性的支持未包括在本次開(kāi)源代碼中,包括:annotation辫愉、lambda表達(dá)式栅受、泛型等。目前仍有很多地方不完善恭朗,會(huì)在社區(qū)陸續(xù)迭代屏镊,遇到問(wèn)題請(qǐng)?jiān)谏鐓^(qū)提交 issue,歡迎在社區(qū)繼續(xù)討論設(shè)計(jì)和代碼共建痰腮。
怎么樣而芥!現(xiàn)在你至少看的懂這個(gè)方舟編譯器架構(gòu)的大體流程了吧,是不是發(fā)現(xiàn)其實(shí)并沒(méi)有那么難理解膀值!那就對(duì)了棍丐,萬(wàn)事開(kāi)頭難,慢慢的一切都會(huì)簡(jiǎn)單起來(lái)~ 至少去知x上看看這些評(píng)論都看懂了啊虫腋,如何看待方舟編譯器于 2019 年 8 月 31 日開(kāi)源骄酗? - 知乎,是不是很開(kāi)心~
詳細(xì)可見(jiàn)官方網(wǎng)頁(yè):方舟編譯器 OpenArkCompiler - FAQ
龍書(shū)悦冀、虎書(shū)趋翻、鯨書(shū) --- 編譯原理三大圣書(shū)
-
龍書(shū)
:《編譯原理》(編譯原理 技術(shù)與工具)(Compilers: Principles,Techniques, and Tools) -
虎書(shū)
:《現(xiàn)代編譯原理 — C語(yǔ)言描 》(Modern Compiler Implement in C) -
鯨書(shū)
:《高級(jí)編譯器設(shè)計(jì)與實(shí)現(xiàn)》(Advanced Compiler Design and Implementation)
龍書(shū):《編譯原理》是編譯領(lǐng)域無(wú)可替代的經(jīng)典著作,被廣大計(jì)算機(jī)專業(yè)人士譽(yù)為“龍書(shū)”盒蟆。
虎書(shū):增加了數(shù)據(jù)流分析踏烙、循環(huán)優(yōu)化、內(nèi)存管理等內(nèi)容历等。
鯨書(shū):包含了一些更比較高級(jí)的編譯器的設(shè)計(jì)和實(shí)現(xiàn)讨惩。
大家是不是瞬間感覺(jué)自己就要買這幾本書(shū)呢!:汀荐捻!我到底能不能看的懂呢?可以先自測(cè)一下自己是不是適配現(xiàn)在就學(xué)習(xí)編譯原理:
學(xué)習(xí)編譯原理前自測(cè)
- a. 編譯型語(yǔ)言和解釋型語(yǔ)言的區(qū)別是什么?
- b. 編譯經(jīng)歷了哪幾個(gè)基本過(guò)程? 每個(gè)過(guò)程主要干了什么事情?
- c. 詳細(xì)描述一下你最熟悉的語(yǔ)言中寡夹,賦值號(hào)的左邊可以由哪些部分組成? 右邊可以由哪些部分組成?
- d. 什么是遞歸? 如何終止一個(gè)遞歸行為?
- e. 什么是貪心過(guò)程?
- f. 聽(tīng)說(shuō)過(guò) KMP 嗎? 介紹一下它的基本思想.
- g. 生成樹(shù)是什么?
- h. 你覺(jué)得編程語(yǔ)言和自然語(yǔ)言最重要的區(qū)別有哪些?
- i. 什么是有限狀態(tài)自動(dòng)機(jī)? 你知道幾種不同的自動(dòng)機(jī)類型? 它們之間的區(qū)別和聯(lián)系?
- j. 內(nèi)存被人為的劃分成了哪幾種不同的類型, 它們之間的區(qū)別和聯(lián)系?
- k. 什么是中斷? CPU 在響應(yīng)中斷時(shí)會(huì)做什么事情?
- l. 你最熟悉的語(yǔ)言有垃圾回收機(jī)制嗎? 若有描述它進(jìn)行垃圾回收的原理, 若沒(méi)有則描述你在編寫(xiě)程序時(shí)是如何管理內(nèi)存的?
本節(jié)內(nèi)容來(lái)自:如何學(xué)習(xí)編譯原理处面? - 歐長(zhǎng)坤的回答 - 知乎
3、總結(jié)
終于到總結(jié)部分啦菩掏!這個(gè)文章魂角,之前給我們組內(nèi)同學(xué)分享時(shí),在回顧都忘記了一大部分智绸,另外在寫(xiě)成文字時(shí)野揪,發(fā)現(xiàn)有很多東西需要考證访忿,每篇文章花了很多心思,正好2020年新型肺炎冠狀病毒都在家里斯稳,正好有這時(shí)間海铆。而 維基百科
就是一個(gè)很棒的網(wǎng)站,關(guān)于大多數(shù)知識(shí)和歷史都能查到挣惰,真的很有趣游添!
關(guān)于編譯器
的知識(shí)有太多了,深入的還可以自己寫(xiě)一個(gè)編譯器通熄!這里就達(dá)不到這樣的層次,所以就提一下找都,有需要的同學(xué)可以自行搜索唇辨。關(guān)于LLVM
的知識(shí)也還有很多沒(méi)有講到,比如抽象語(yǔ)法樹(shù)
(AST)能耻,前端 Clang
是重中之器赏枚,Clang 插件開(kāi)發(fā)等,還有中間端的 Pass
晓猛,后端的Mach-O
和 CPU 執(zhí)行 Mach-O 的過(guò)程等饿幅。
最后,本文還是有很多細(xì)節(jié)無(wú)法用文字記錄下來(lái)戒职,大家可以閱讀下面的參考鏈接栗恩,這樣收獲會(huì)更大。關(guān)于編譯器
和鏈接器
就到這里先洪燥,對(duì)于大家理解這個(gè)概念應(yīng)該是沒(méi)有問(wèn)題啦磕秤!具體的實(shí)現(xiàn)細(xì)節(jié),需要大家多學(xué)習(xí)捧韵,如果有能力市咆,可以看看龍書(shū)!虎書(shū)再来!鯨書(shū)蒙兰! 想想也是一件快樂(lè)的事件!
2020年芒篷,手機(jī)只是小小一部分搜变,智慧家居大屏、穿戴梭伐、車機(jī)痹雅、音響、手表糊识、PC等等各種各樣設(shè)備绩社,作為開(kāi)發(fā)者摔蓝,我們不要只關(guān)注自己開(kāi)發(fā)的App蹬敲,應(yīng)該去理解這個(gè)世界發(fā)生什么變化辆憔,為什么變化尉剩,怎么變化捶障,抓住變化操刀!
當(dāng)然我承認(rèn)世界是掌握于小數(shù)人夫晌,但能先抓住自己麻献!這就是好的開(kāi)始~
注:更多關(guān)于 iOS 開(kāi)發(fā)和程序開(kāi)發(fā)相關(guān)的內(nèi)容辨嗽,可以查看系列赌渣,目前還在連載中 【學(xué)習(xí)總結(jié)】iOS開(kāi)發(fā)高手課 -- (連載中) | iHTCboy's blog魏铅,以上,希望對(duì)你有用坚芜!
參考
WWDC
- What's New in Clang and LLVM - WWDC 2019 - Videos - Apple Developer
- What's New in LLVM - WWDC 2018 - Videos - Apple Developer
- What's New in LLVM - WWDC 2017 - Videos - Apple Developer
- What's New in LLVM - WWDC 2016 - Videos - Apple Developer
- Behind the Scenes of the Xcode Build Process - WWDC 2018 - Videos - Apple Developer
- What's New in Swift - WWDC 2016 - Videos - Apple Developer
- What's New in Swift - WWDC 2017 - Videos - Apple Developer
- What's New in Swift - WWDC 2018 - Videos - Apple Developer
- What's New in Swift - WWDC 2019 - Videos - Apple Developer
Article
- 深入剖析 iOS 編譯 Clang / LLVM | 星光社 - 戴銘的博客
- 淺談iOS編譯過(guò)程 - 簡(jiǎn)書(shū)
- iOS學(xué)習(xí)之深入理解程序編譯過(guò)程 - 掘金
- 淺談iOS安全與入侵(逆向工程)
- dyld簡(jiǎn)介及加載過(guò)程分析 - 簡(jiǎn)書(shū)
- Clang - 維基百科览芳,自由的百科全書(shū)
- LLVM - 維基百科,自由的百科全書(shū)
- LLVM:Swift鸿竖、Rust沧竟、Clang等語(yǔ)言的強(qiáng)大后盾-InfoQ
- About — LLVM 10 documentation
- LLVM Weekly - a weekly newsletter covering developments in LLVM, Clang and more
- mikeash.com: Friday Q&A 2012-11-09: dyld: Dynamic Linking On OS X
- 從Swift橋接文件到Clang-LLVM - 掘金
- App啟動(dòng)之Dyld在做什么 - 掘金
- Mach-O - 維基百科,自由的百科全書(shū)
- Objective-C中的Block
- GitHub - ming1016/SMCheckProject: 使用Swift3開(kāi)發(fā)了個(gè)MacOS的程序可以檢測(cè)出objc項(xiàng)目中無(wú)用方法缚忧,然后一鍵全部清理
- 如何學(xué)習(xí)編譯原理悟泵? - 知乎
- 學(xué)習(xí)《編譯原理》完全沒(méi)有頭緒怎么辦? - 知乎
- 誰(shuí)看完過(guò)龍書(shū)虎書(shū)鯨書(shū)闪水?全部看完是不是就有能力寫(xiě)一個(gè)C語(yǔ)言的編譯器了糕非? - 知乎
- 編譯原理三大圣書(shū)——龍書(shū)、虎書(shū)敦第、鯨…_Working...-CSDN博客
- GitHub - RetVal/objc-runtime: objc runtime 750
- GitHub - opensource-apple/dyld
- iOS 了解Xcode Bitcode - 掘金
- 關(guān)于bitcode, 知道這些就夠了 - xelz's blog
- Joy-Collection/趣探 Mach-O:文件格式.md at master · joy0304/Joy-Collection
- Joy-Collection/點(diǎn)擊 Run 之后發(fā)生了什么峰弹?.md at master · joy0304/Joy-Collection
- Joy-Collection/來(lái)談?wù)?Mac OS X 內(nèi)核.md at master · joy0304/Joy-Collection
- Parsing Mach-O files - Low Level Bits
- 趣探 Mach-O:文件格式分析 - 簡(jiǎn)書(shū)
- 趣探 Mach-O:加載過(guò)程 - 簡(jiǎn)書(shū)
- Mach-O可執(zhí)行文件 - 簡(jiǎn)書(shū)
- GeekTime/LLVM.pdf at master · rogertan30/GeekTime
- 怎樣寫(xiě)一個(gè)解釋器
- The Architecture of Open Source Applications: LLVM
- Welcome to Clang's documentation! — Clang 11 documentation
- Writing an LLVM Pass — LLVM 10 documentation
- The Clang AST - a Tutorial - YouTube
- Index of /afs/cs.cmu.edu/academic/class/15745-s14/public/lectures
- llvm/clang/ Source Tree - Woboq Code Browser
- swift/SIL.rst at master · apple/swift
- Swift Intermediate Language 初探 - 知乎
- LLVM架構(gòu)與Clang - Jerry的博客 | Jerry's Blog
- iOS 編譯詳解 LLVM Clang - 掘金
- iOS 符號(hào)表 - Bugly 文檔
- x86 - 維基百科,自由的百科全書(shū)
- X86芜果、X64和X86_64區(qū)別 - - ITeye博客
- x86-64 - 維基百科鞠呈,自由的百科全書(shū)
- 安謀控股 - 維基百科,自由的百科全書(shū)
- ARM架構(gòu) - 維基百科右钾,自由的百科全書(shū)
- Chris Lattner(克里斯·拉特納) - 維基百科蚁吝,自由的百科全書(shū)
- GeekTime/符號(hào)是怎么綁定到地址上的 at master · rogertan30/GeekTime
- OpenArkCompiler - 方舟編譯器
- 華為方舟編譯器 | 鴻蒙學(xué)堂
- 如何看待方舟編譯器于 2019 年 8 月 31 日開(kāi)源? - 知乎
- 中國(guó)首個(gè)官方推出的開(kāi)源協(xié)議:木蘭寬松許可證上線-InfoQ
- 如有侵權(quán)舀射,聯(lián)系必刪窘茁!
- 如有不正確的地方,歡迎指導(dǎo)脆烟!
- 如有疑問(wèn)山林,歡迎在評(píng)論區(qū)一起討論!
注:本文首發(fā)于 iHTCboy's blog邢羔,如若轉(zhuǎn)載驼抹,請(qǐng)注來(lái)源