被隐藏的过程: 分解为4个步骤: 预处理(prepressing) 、编译(compilation)、汇编(Assembly) 和 连接(Linking)
2.1.1 预编译
clang -E hello.c -o hello.i // 这里进行了预编译
看一下OC中的代码是如本编译的命令。
预编译主要处理:
- 将所有的额#define删除,并展开所有的宏定义
- 处理所有条件预编译指令, eg:#if , #endif 等
- 处理#include预编译指令,将被包含的文件插入到该编译指令的位置。 Note: 这个过程是递归精心的,也就是说呗包含的文件可能还包含其他文件。
- 删除注释
- 添加行号和文件名标识, eg: #2 hello.c 2 ,以便于编译时编译器产生调试的行号信心以及用于编译时产生编译错误或警告时能够显示行号。
- 保留所有的#pragma编译器指令,因为编译器须使用它们
经过预编译后的.i 文件不包含任何宏定义, 因为所有的宏已经被展开,并且包含的文件也已经被插入到.i 文件中。所以,当我们无法判断宏定义是否正确或投文件包含是否正确时候 ——
可以查看预编译后的文件确定问题。
在xcode上查看预编译的过程:
预编译的选项在右上角选择assistant, 然后再左上角看到有关的预编译选项。
2.1.2 编译 【核心、复杂】
编译过程是吧预处理完的文件进行一系列 词法分析、语法分析、语义分析 以及优化后生产相应的汇编代码文件。
clang -S hello.i -o hello.s // 将预编译的代码转化为汇编代码
相当于: clang -S hello.c -o hello.s
clang 是一些命令的集合,根据平参数去调用预编译程序,汇编器,连接器
2.1.3 汇编 【相对简单】
汇编器 将 汇编代码转变成机器可以执行的指令。
Note: 这个过程没有复杂的语法、语义、也不需要优化,只是根据汇编指令和机器指令的对照表一一翻译。
as hello.s -o hello.o
相当于: clang -c hello.s -o hello.o
链接 (ld)
使用ld进行对hello.o 进行链接。 需要将一大堆文件链接起来才得到a.out 可执行文件。
看到这样的链接命令
编译器做了什么?
词法分析、语法分析、语义分析、 —— 编译的内容,【暂略】
经历词法、语法、语义分析之后得到的中间代码2.2.5 目标代码生成与优化
编译器的后端:主要包括代码生成器(code generator) 和目标代码优化器(target code Optimizer) 。
需要最后连接器生成最终的目标可执行文件代码生成器: 将中间代码转换成机器代码【这个过程依赖于目标机器】
2.3 连接器年龄比编译器长
2.4 模块拼装 —— 静态链接
链接主要过程决议 链接过程示意图: 目标文件+库 连接器对地址的修正和符号决议
PS:
1》从源代码到最终可之心文件的4个步骤:预编译、编译、汇编、链接
2》 编译的步骤: 词法分析、语法分析、语义分析、中间代码生成、目标代码生成、优化
3》连接的历史和静态链接的一系列基本概念:重定位、符号、符号决议、目标文件、库、运行库等概念。
网友评论