iOS编译

161 阅读4分钟
  1. ClangLLVM项目中的一个子项目。它是基于LLVM架构的轻量级编译器,诞生之初是为了替代GCC,提供更快的编译速度。它负责CC++Objective-C语言的编译器,它属于整个LLVM框架中的编译器前端。

  2. 传统编译器的设计

对的.webp 3. 编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。
一个现代编译器的主要工作流程:源代码 (source code)预处理器(preprocessor)编译器 (compiler)目标代码 (object code)链接器(Linker)可执行程序

编译的概念(词法->语法->语义->IR->优化->CodeGen)

  1. 编译器设计
  • 编译器前端(Frontend) 任务是解析源代码。词法分析语法分析语义分析检查源代码是否存在错误构建抽象语法树AST(Abstract Syntax Tree)。 如果是LLVM前端(Clang/Swift)还会生成中间代码(intermediate representation)
  • 优化器(Optimizer)
    各种优化。改善代码运行时间,例如消除冗余计算等。(类似Xcode里设置编译优化等级)
  • 后端(Backend)/代码生成器(CodeGenerator)
    将代码映射到目标指令集,生成机器语言,并进行机器相关代码优化。
    (64位arm的指令集就是arm64,64位x86的指令集就是x86_64)

下面是演示

1. 宏的替换,头文件的导入
2. 词法解析:这里会把代码切成一个个 Token,比如大小括号,等于号还有字符串等。:简单示意
int main(){

    @autoreleasepool {

        int e' Loc=<main.m:8:1>

int 'int' [StartOfLine] Loc=<main.m:12:1>

identifier 'main' [LeadingSpace] Loc=<main.m:12:5>

l_paren '(' Loc=<main.m:12:9>

r_paren ')' Loc=<main.m:12:10>

l_brace '{' Loc=<main.m:12:11>

at '@' [StartOfLine] [LeadingSpace] Loc=<main.m:13:5>

3.语法分析、抽象语法树
**FunctionDecl** 0x7fb1a70e7c70 <line:12:1, line:21:1> line:12:5 **main** 'int ()'

  `-**CompoundStmt** 0x7fb1a69b95d8 <col:11, line:21:1>

    |-**ObjCAutoreleasePoolStmt** 0x7fb1a69b9590 <line:13:5, line:19:5>

    | `-**CompoundStmt** 0x7fb1a69b9558 <line:13:22, line:19:5>

    |   |-**DeclStmt** 0x7fb1a70e7e10 <line:14:9, col:32>

    |   | `-**VarDecl** 0x7fb1a70e7d88 <col:9, line:10:21> line:14:13 used **eight** 'int' cinit

    |   |   `-**IntegerLiteral** 0x7fb1a70e7df0 <line:10:21> 'int' **8**

    |   |-**DeclStmt** 0x7fb1a69ba298 <line:15:9, col:20>

    |   | `-**VarDecl** 0x7fb1a70e7e40 <col:9, col:19> col:13 used **six** 'int' cinit
4. 生成IR中间代码(到此 编译器前端 完成)
; Function Attrs: noinline optnone ssp uwtable
define i32 @main() #1 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  %3 = alloca i32, align 4
  %4 = alloca %0*, align 8
  %5 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  %6 = call i8* @llvm.objc.autoreleasePoolPush() #2
5.LLVM 会去做些优化工作+bitcode(优化完成)
6.生成汇编 生成目标代码,生成可执行文件(生成可执行文件完成)

5.app完整编译流程

  • 编译信息写入辅助文件,创建文件架构 .app 文件
  • 处理文件打包信息
  • 执行 CocoaPod 编译前脚本,checkPods Manifest.lock
  • 编译.m文件,使用 CompileC 和 clang 命令(对应上面流程)
  • 链接需要的 Framework
  • 编译 xib
  • 拷贝 xib ,资源文件
  • 编译 ImageAssets
  • 处理 info.plist
  • 执行 CocoaPod 脚本
  • 拷贝标准库
  • 创建 .app 文件和签名

targetID,包含它对应的编译选项

  1. clang static analyzer 主要是进行语法分析,语义分析和生成中间代码,当然这个过程会对代码进行检查,出错的和需要警告的会标注出来。
  2. Token
Token 可以分为以下几类

-   关键字:语法中的关键字,if else while for 等。
-   标识符:变量名
-   字面量:值,数字,字符串
-   特殊符号:加减乘除等符号
  1. 生成出来的IR代码都是一样的语法形式

不管编译的语言时 Objective-C 还是 Swift 也不管对应机器是什么,亦或是即时编译,LLVM 里唯一不变的是中间语言 LLVM IR。

  1. CodeGen 生成 IR 代码 这个过程中还会跟 runtime 桥接。(抽象语法树之后,生成IR)
  • 各种类,方法,成员变量等的结构体的生成,并将其放到对应的Mach-O的section中。
  • Non-Fragile ABI 合成 OBJC_IVAR_$_ 偏移值常量。
  • ObjCMessageExpr 翻译成相应版本的 objc_msgSend,super 翻译成 objc_msgSendSuper。
  • strong,weak,copy,atomic 合成 @property 自动实现 setter 和 getter。
  • @synthesize 的处理。
  • 生成 block_layout 数据结构
  • __block 和 __weak
  • _block_invoke
  • ARC 处理,插入 objc_storeStrong 和 objc_storeWeak 等 ARC 代码。ObjCAutoreleasePoolStmt 转 objc_autorealeasePoolPush / Pop。自动添加 [super dealloc]。给每个 ivar 的类合成 .cxx_destructor 方法自动释放类的成员变量。 11.IR:一个文件 对应一个Module LLVM LLVM2 编译流程 12.什么是抽象语法树 抽象语法树