Clang 之旅--使用 Xcode 开发 Clang 插件

前言

今天是举国同庆的国庆假期的第一天,早上看到庄严的升旗激动坏了,中午都没睡觉,刷着朋友圈看着大家都在玩着,心想要不没事就写点东西吧。有个小伙伴写文章后都会发给我看一下(挑剔的我,开始给挑毛病),还鼓励我继续写技术文档,说实话好久没写了,有点乱,凑合着看吧,欢迎扔砖头。最后祝大家国庆假期快乐,玩的开心哟~~~

很久前学了点关于LLVM的东西,一直没有时间整理,现在抽时间来总结一下,废话不多说,现在开始正经起来。

LLVM

一、简介

1、什么是LLVM

官网:https://llvm.org/

LLVM项目是模块化、可重用的编译器以及工具链技术的集合。曾在2012年获得软件系统奖项。

有些文章把LLVM当做Low Level Virtual Machine(低级虚拟机)的缩写简称,官方描述如下:

The name "LLVM" itself is not an acronym; it is the full name of the project.

“LLVM”这个名称本身不是首字母缩略词,它是项目的全名

2、创始人

Chris Lattner,看到这个名字有没有很熟悉?对了!他就是Swift之父

3、编译器的架构

A、传统的编译器架构

传统的编译器架构

Frontend:前端

词法分析、语法分析、语义分析、生成中间代码

Optimizer:优化器

中间代码优化

Backend:后端

生成机器码

B、LLVM架构

LLVM架构

不同的前端后端使用统一的中间代码LLVM Intermediate Representation(LLVM IR)

如果需要支持一种新的变成语言,那么只需要实现一个新的前端

如果需要支持一种新的硬件设备,那么只需要实现一个新的后端

优化阶段是一个通用的阶段,它针对的是统一的LLVM IR,不论是支持新的编程语言,还是只是新的硬件设备都不需要对优化阶段做修改

相比之下,GCC的前端和后端没分的太开,前端后端耦合在一起,所以GCC为了支持一门新的语言或者为了支持一个新的目标平台就变得特别困难

LLVM现在被作为实现各种静态和运行时编译语言的通用基础结构(GCC家族、Java、   .NET、Python、Ruby、Schem、Haskell、D等)

Clang

1、什么是Clang

LLVM项目的一个子项目

基于LLVM架构的C/C++/Objective-C编译器前端

2、相比于GCC,Clang具有的优点有以下几点:

编译速度快:在某些平台上,Clang的编译速度显著的快过GCC(Debug模式下编译OC速度比GCC快3倍)

占用内存小:Clang生成的AST所占用的内存是GCC的五分之一左右

模块化设计:Clang采用基于库的模块化设计,易于IDE集成及其他用途的重用

诊断信息可读性强:在编译过程中,Clang穿件并保留了大量详细的元数据(metadata),有利于调试和错误报告

设计清晰简单,容易理解,易于扩展增强

Clang与LLVM

Clang与LLVM的对比

OC源文件的编译过程

命令行查看编译的过程:

$ clang -ccc-print-phases main.m

查看preprocessor(预处理)的结果:

$ clang -E main.m

词法分析,生成Token:

$ clang -fmodules -E -Xclang -dump-tokens main.m

词法分析,生成Token

语法分析,生成语法树(AST,Abstract Syntax Tree): 

$ clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

语法分析,生成语法树
语法树

LLVM IR

LLVM IR有3种表示形式:

1、text:便于阅读的文本格式,类似于汇编语言,拓展名 .||

$ clang -S -emit-llvm main.m

2、memory:内存格式

3、bitcode:二进制格式,拓展名 .bc

$ clang -c -emit-llvm main.m

LLVM IR语法

源码下载

1、下载LLVM

$ git clone https://git.llvm.org/git/llvm.git/

2、下载Clang

$ cd llvm/tools

$ git clone https://git.llvm.org/git/clang.git/

源码编译

安装cmake和ninja(先安装brew,https://brew.sh/

$ brew install cmake

$ brew install ninja

ninja如果安装失败,可以直接从github获取release版放入【/usr/local/bin】中

https://github.com/ninja-build/ninja/releases

在LLVM源码同级目录下新建一个【llvm_build】目录(最终会在【llvm_build】目录下生成【build。ninja】)

$ cd llvm_build

$ cmake -G Ninja ../llvm -DCMAKE_INSTALL_PREFIX=LLVM的安装路径

依次执行编译、安装指令

$ ninja

$ ninja install

也可以生成Xcode项目再进行编译,但是速度很慢(可能需要1个多小时)

在llvm同级目录下新建一个【llvm_xcode】目录

$ cd llvm_xcode

$ cmake -G Xcode ../llvm

Clang插件开发

1 -- 插件目录

在【clang/tools】源码目录下新建一个插件目录,假设叫做【mj-plugin】

在【clang/tools/CMakeLists.txt】最后加入内容: add_clang_subdirectory(mj-plugin),小括号里是插件目录名

2 -- 插件必要文件

在【mj-plugin】目录下新建一个【CMakeLists.txt】,文件内容是:add_llvm_loadable_module(MJPlugin MJPlugin.cpp)

MJPlugin是插件名,MJPlugin.cpp是源代码文件

3 -- 编写插件源码

4 -- 编译插件

利用cmake生成的Xcode项目来编译插件(第一次编写完插件,需要利用cmake重新生成一下Xcode项目)

插件源代码在【Sources/Loadable modules】目录下可以找到,这样就可以直接在Xcode里编写插件代码

选择MJPlugin这个target进行编译,编译完会生成一个动态库文件

5 -- 加载插件

在Xcode项目中指定加载插件动态库:BuildSettings > OTHER_CFLAGS

-Xclang -load -Xclang 动态库路径 -Xclang -add-plugin -Xclang 插件名称

6 -- Hack Xcode

首先要对Xcode进行Hack,才能修改默认的编译器

下载【XcodeHacking.zip】,解压,修改【HackedClang.xcplugin/Contents/Resources/HackedClang.xcspec】的内容,设置一下自己编译好的clang的路径

然后在XcodeHacking目录下进行命令行,将XcodeHacking的内容剪切到Xcode内部

$ 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`/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications

7 -- 修改Xcode的编译器

8 -- 编译项目

编译项目后,会在编译日志看到MJPlugin插件的打印信息(如果插件更新了,最好先Clean一下项目)

9 -- 更多

关于AST的资料

https://clang.llvm.org/doxygen/namespaceclang.htmlp  

https://clang.llvm.org/doxygen/classclang_1_1Decl.htmlp

https://clang.llvm.org/doxygen/classclang_1_1Stmt.html

10 -- 应用结果

以上就是该阶段的全部内容了,虽然在自己操作的过程中因为电脑内存太小而导致没有全部完成,有点小遗憾,希望阅读该文章的小伙伴们能够成功哟~加油~

感谢MJ大神,欢迎点赞,打赏哟~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容