编译原理
本文参考
前言
像C++,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高。
像JavaScript,Python等都是直译式语言(脚本语言)。直译式语言不需要经过编译的过程,而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码。所以,较编译语言来说,直译式语言效率低一些,但是编写的更灵活,也就是为啥JS大法好。
iOS开发目前的常用语言是:Objective和Swift。二者都是编译语言,换句话说都是需要编译才能执行的。二者的编译都是依赖于Clang + LLVM. 篇幅限制,本文只关注Objective C,因为原理上大同小异。
可能会有同学想问,我不懂编译的过程,写代码也没问题啊?这点我是不否定的。但是,充分理解了编译的过程,会对你的开发大有帮助。本文的最后,会以以下几个例子,来讲解如何合理利用XCode和编译
__attribute__Clang警告处理
预处理
插入编译期脚本
提高项目编译速度
对于不想看我啰里八嗦讲一大堆原理的同学,可以直接跳到本文的最后一个章节。LLVM源码编译
三段式设计

编译主要步骤 1. 源代码(source code) -> 2. 预处理器(preprocessor) -> 3. 编译器(compiler) -> 4. 汇编程序(assembler) -> 5. 目标代码(object code) -> 6. 链接器(Linker) -> 7. 可执行文件(executables)
自己编译LLVM
废话不多说,直接进入正题😍
准备工作
Clang 需要用 CMake 和 Ninja 来编译,可以通过 Homebrew 安装
安装 Homebrew
安装 CMake 3.12.4
安装 Ninja 1.8.2
源码下载
下载 LLVM (clang 9)
源码编译
1. 使用 Ninja 编译
2. 使用 Xcode 编译
选择自动创建schemes,选择targetALL_BUILD,然后开始漫长的编译预计1500s
出现以下错误时,可能是权限导致,加上sudo再次尝试编译
编译成功后将权限还原到默认
安装
iOS编译
Objective C采用Clang(swift采用swift)作为编译器前端,LLVM(Low level vritual machine)作为编译器后端。
简单的编译过程如图

编译器前端
编译器前端的任务是进行:语法分析,语义分析,生成中间代码(intermediate representation )。在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。

编译器后端
编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化。iOS的编译过程,后端的处理如下
LVVM优化器会进行BitCode的生成,链接期优化等等。

LLVM机器码生成器会针对不同的架构,比如arm64等生成不同的机器码。

编译过程
编译信息写入辅助文件,创建文件架构 .app 文件
处理文件打包信息
执行 CocoaPod 编译前脚本,checkPods Manifest.lock
编译.m文件,使用 CompileC 和 clang 命令
链接需要的 Framework
编译 xib
拷贝 xib ,资源文件
编译 ImageAssets
处理 info.plist
执行 CocoaPod 脚本
拷贝标准库
创建 .app 文件和签名
预处理&词法分析
替换宏定义
头文件的导入
编译条件
把代码细拆分成最小的Token(包含代码位置),如大小括号,
等于号还有字符串等
语法分析
验证语法是否正确
将所有节点生成AST
中间代码IR
CodeGen 会负责将AST自上而下递归遍历翻译成 LLVM IR
IR 是编译过程的前端输出,后端的输入
编译优化
LLMV在编译时会做些优化,Xcode编译设置中可设置级别
开启Bitcode会进一步优化
Pass 是LLVM优化的一个节点,可以自定义
生成汇编
生成目标
生成可执行文件
执行
Last updated
Was this helpful?