什么是LLVM
官網(wǎng):https://llvm.org/
LLVM項(xiàng)目是模塊化、可重用的編譯器以及工具鏈技術(shù)的集合。美國(guó)計(jì)算機(jī)協(xié)會(huì) (ACM) 將其2012 年軟件系統(tǒng)獎(jiǎng)項(xiàng)頒給了LLVM,之前曾經(jīng)獲得此獎(jiǎng)項(xiàng)的軟件和技術(shù)包括:Java研底、Apache轰传、 Mosaic、the World Wide Web跪楞、Smalltalk、UNIX侣灶、Eclipse等等
創(chuàng)始人:Chris Lattner甸祭,亦是Swift之父
傳統(tǒng)的編譯器架構(gòu)
LLVM編譯器架構(gòu)
從上面的2張圖就可以看出來(lái)LLVM編譯器的優(yōu)點(diǎn)
1.不同的前端后端使用統(tǒng)一的中間代碼LLVM Intermediate Representation (LLVM IR)
2.如果需要支持一種新的編程語(yǔ)言,那么只需要實(shí)現(xiàn)一個(gè)新的前端
3.如果需要支持一種新的硬件設(shè)備褥影,那么只需要實(shí)現(xiàn)一個(gè)新的后端
4.優(yōu)化階段是一個(gè)通用的階段池户,它針對(duì)的是統(tǒng)一的LLVM IR,不論是支持新的編程語(yǔ)言凡怎,還是支持新的硬件設(shè)備校焦,都不需要對(duì)優(yōu)化階段做修改
5.相比之下,GCC的前端和后端沒(méi)分得太開统倒,前端后端耦合在了一起寨典。所以GCC為了支持一門新的語(yǔ)言,或者為了支持一個(gè)新的目標(biāo)平臺(tái)檐薯,就 變得特別困難
6LLVM現(xiàn)在被作為實(shí)現(xiàn)各種靜態(tài)和運(yùn)行時(shí)編譯語(yǔ)言的通用基礎(chǔ)結(jié)構(gòu)(GCC家族凝赛、Java、.NET坛缕、Python墓猎、Ruby、Scheme赚楚、Haskell毙沾、D等)
下面主要介紹下Clang
Clang是LLVM項(xiàng)目的一個(gè)子項(xiàng)目
基于LLVM架構(gòu)的C/C++/Objective-C編譯器前端
-
官網(wǎng):http://clang.llvm.org/
相比于GCC ,Clang具有的優(yōu)點(diǎn)1.編譯速度快:在某些平臺(tái)上宠页,Clang的編譯速度顯著的快過(guò)GCC(Debug模式下編譯OC速度比GGC快3倍) 2.占用內(nèi)存小:Clang生成的AST所占用的內(nèi)存是GCC的五分之一左右 3.模塊化設(shè)計(jì):Clang采用基于庫(kù)的模塊化設(shè)計(jì)左胞,易于 IDE 集成及其他用途的重用 4.診斷信息可讀性強(qiáng):在編譯過(guò)程中,Clang 創(chuàng)建并保留了大量詳細(xì)的元數(shù)據(jù) (metadata)举户,有利于調(diào)試和錯(cuò)誤報(bào)告 5.設(shè)計(jì)清晰簡(jiǎn)單烤宙,容易理解,易于擴(kuò)展增強(qiáng)
Clang 與LLVM 的關(guān)系
- 可以看的出Clang可以對(duì)語(yǔ)法進(jìn)行分析俭嘁,所以我們接下來(lái)做個(gè)類名規(guī)范的插件
具體操作開始
下載LLVM
- git clone https://git.llvm.org/git/llvm.git/ 大小大約700M左右
下載Clang
- 下載完llvm后然后進(jìn)入cd llvm/tools 這個(gè)目錄下 再去下載clang
- git clone https://git.llvm.org/git/clang.git/
編譯源碼
- 首先安裝brew(https://brew.sh/)
- curl -LsSf http://github.com/mxcl/homebrew/tarball/master | sudo tar xvz -C/usr/local --strip 1(安裝過(guò)的可以忽略)
當(dāng)brew安裝成功后躺枕,就可以隨意安裝自己想要的軟件了
安裝cmake和ninja
- brew install cmake
- brew install ninja
(ninja如果安裝失敗,可以直接從github獲取release版放入【/usr/local/bin】中 下載地址 :https://github.com/ninja-build/ninja/releases) - 在LLVM源碼同級(jí)目錄下新建一個(gè)【llvm_build】目錄(最終會(huì)在【llvm_build】目錄下生成【build.ninja】
- cd llvm_build
- cmake -G Ninja ../llvm -DCMAKE_INSTALL_PREFIX=../llvm_release
(cmake -G Ninja ../llvm -DCMAKE_INSTALL_PREFIX=LLVM的安裝路徑) - 然后依次執(zhí)行命令
- ninja (備注:編譯完畢后,編譯時(shí)間大概半個(gè)小時(shí) 【llvm_build】目錄大概 21.05 G(僅供參考) )
- ninja install ( 備注: 安裝完畢后拐云,安裝時(shí)間大概20分鐘罢猪,安裝目錄大概 11.92 G(僅供參考))
- 在llvm同級(jí)目錄下新建一個(gè)【llvm_xcode】目錄
- cd llvm_xcode
- cmake -G Xcode ../llvm
-
完成之后 雙擊 LLVM.xcodeproj 打開項(xiàng)目
- 然后command+B 編譯一下
libclang、libTooling
- 官方參考:https://clang.llvm.org/docs/Tooling.html
- 應(yīng)用:語(yǔ)法樹分析叉瘩、語(yǔ)言轉(zhuǎn)換等
Clang插件開發(fā)
- 官方參考:
- https://clang.llvm.org/docs/ClangPlugins.html
- https://clang.llvm.org/docs/ExternalClangExamples.html
- https://clang.llvm.org/docs/RAVFrontendAction.html
- 應(yīng)用:代碼檢查(命名規(guī)范膳帕、代碼規(guī)范)等
clang插件開發(fā)
- 在【clang/tools】源碼目錄下新建一個(gè)插件目錄,假設(shè)叫做【zw-plugin】
-
/llvm/tools/clang/tools 在這個(gè)目錄下創(chuàng)建一個(gè)zw-plugin 文件夾
-
在/llvm/tools/clang/tools/CMakeLists.txt 最后加入內(nèi)容: add_clang_subdirectory(zw-plugin)薇缅,小括號(hào)里是插件目錄名
- 然后在/llvm/tools/clang/tools/zw-plugin 的目錄下新建一個(gè)CMakeLists.txt 危彩。
- 文件添加內(nèi)容是:add_llvm_loadable_module(ZWPlugin ZWPlugin.cpp)
-
然后在/llvm/tools/clang/tools/zw-plugin 文件里 創(chuàng)建名字為ZWPlugin.cpp 的文件
- ZWPlugin.cpp 里面的源碼,我上傳到github
寫完插件代碼后需要重新來(lái)到我們創(chuàng)建llvm_xcode 文件下
- cd llvm_xcode
- cmake -G Xcode ../llvm
(利用cmake生成的Xcode項(xiàng)目來(lái)編譯插件(第一次編寫完插件泳桦,需要利用cmake重新生成一下Xcode項(xiàng)目)) - 選擇MJPlugin這個(gè)target進(jìn)行編譯恬砂,編譯完會(huì)生成一個(gè)動(dòng)態(tài)庫(kù)文件
- ZWPlugin 就是最后做成插件的動(dòng)態(tài)庫(kù)
測(cè)試插件效果
- 自己新創(chuàng)建一個(gè)xcode 工程 在創(chuàng)建一個(gè)zw_class 帶下劃線的類名
-
在新建的工程中找到下圖
- -Xclang -load -Xclang 動(dòng)態(tài)庫(kù)路徑 -Xclang -add-plugin -Xclang 插件名稱
clang插件開發(fā)6 – Hack Xcode
- 首先要對(duì)Xcode進(jìn)行Hack,才能修改默認(rèn)的編譯器
- 下載【XcodeHacking.zip】蓬痒,解壓,修改【HackedClang.xcplugin/Contents/Resources/HackedClang.xcspec】的內(nèi)容漆羔,設(shè)置一下自己編譯好的clang的路徑
- 然后在XcodeHacking目錄下進(jìn)行命令行梧奢,將XcodeHacking的內(nèi)容剪切到Xcode內(nèi)部
- sudo mv HackedClang.xcplugin
xcode-select-print- path
/../PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins - sudo mv HackedBuildSystem.xcspec
xcode-select-print- path
/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications - 如果上面的命令報(bào)錯(cuò)的話,就根據(jù)上面的路徑找到對(duì)應(yīng)的文件演痒,然后把解壓的文件放在里面