【iOS】—— 编译链接
文章目录
- 【iOS】—— 编译链接
- 编译流程
- 预处理(预编译Prepressing)
- 编译(Compilation)
- 汇编(Assembly)
- 链接(Linking)
编译流程
编译流程分为四步
- 预处理(Prepressing)
- 编译(Compilation)
- 汇编(Assembly)
- 链接(Linking)
预处理(预编译Prepressing)
作为编译的第一步,首先将main.m
文件编译成了main.i
文件,指令如下:
clang -E main.m -o main.i
预处理的过程虽然是将main.m文件编译成了mian.i文件,但是实际上的过程并不是这么简单的,那么具体的预编译情况是什么样的呢:
预编译是要处理源代码中以#开头的所有预编译指令。规则如下:
#define
删除,并展开对应的宏定义。- 处理所有的条件预编译指令。如
#if
、#ifdef
、#else
、#endif
。 #include
&#import
包含的文件递归插入到此处(含#处)。- 删除所有的注释 //、/**/等。
- 添加行号和文件名标识。如 # 1 “main.m"(编译调试会用到)。
编译(Compilation)
将main.i
文件编译成main.s
文件,指令如下:
clang -S main.i -o main.s
这个过程就是把上面的main.i文件进行:词法分析、语法分析、静态分析,优化生成相应的汇编代码,最终生成main.s
文件。
这里我们需要了解一下这几个名词:
- 词法分析:把源代码的字符序列分割成一个个
token
(关键字、表示符、字面量、特殊符号),比如把标识符放到符号表里面。 - 语法分析: 生成抽象语法树AST,此时运算符号的优先级确定了;有些符号具有多重含义也确定了,比如:*是乘号还是对指针取内容;
表达式不合法
、括号不匹配
等等,都会报错。 - 静态分析:分析
类型声明
和匹配问题
。比如整型和字符串相加,肯定会报错。 - 中间语法生成:
CodeGen
根据AST(抽象语法树)
自上向下逐步翻译成LLVM IR
,并且对在编译期就可以确定的表达式进行优化,比如代码里面的a=1+3,可以优化成a=4。(假如开启了bitcode) - 目标代码生成与优化: 根据中间语法生成依赖具体机器的汇编语言;并优化汇编语言。这个过程中,假如有变量且定义在同一个编译单元里,那么就给这个变量分配空间,确定变量的地址。假如变量或者函数不定义在这个编译单元里面,那就等到链接的时候才能确定地址。
汇编(Assembly)
将main.s
文件编译成main.o
文件(也就是我们常说的目标文件),指令如下:
clang -c main.s -o main.o
这个过程就是把上面得到的main.s
文件里面的汇编指令翻译成机器指令,最终生成等到main.o
链接(Linking)
这个过程就是将main.o
编译成对应的Mach-O
文件,也就是我们常说的可执行文件,指令如下:
clang main.o -o main
链接的本质就是把一个或多个目标文件和需要的库(静态库/动态库,如果需要的话)组合成一个文件(Mach-O可执行文件)