[What]链接、装载与库 --> 编译和链接

学习编译及链接的大体过程。

预处理(Preprocessing)

将源码文件及其相关头文件被cpp预编译成一个 .i 文件。

  • 对于c++来说是被预编译为 .ii 文件

预编译的处理规则如下:

  • 将所有 "#define" 删除,并且展开所有的宏定义
  • 处理所有条件预编译指令,比如 "#if, #ifdef, #elif, #else, #endif"
  • 处理 "#include" 预编译指令,将被包含的文件 插入到该预编译指令的位置
    • 这个过程是递归进行的,如果被包含文件还包含其他文件,也会依次展开
  • 删除所有的代码注释
  • 添加行号和文件名标识,便于编译时编译器产生调试用的符号信息和错误或警告时的提醒
  • 保留所有的 "#pragma" 编译器指令,在编译阶段被使用

通过查看预编译后的文件,可以检查宏是否正确以及文件包含是否正确。

编译(Compilation)

编译的过程就是把预处理完的文件进行一系列的词法分析,语法分析,语义分析以及优化后生成相应的汇编代码文件.

在gcc中,将从预编译到编译使用命令 gcc -S hello.i -o hello.s,也可以使用 cc1 来完成预处理和编译.

编译过程一般可以分为6步:扫描,语法分析,语义分析,源代码优化,代码生成,目标代码优化.

扫描器(词法分析)

源代码程序首先被输入到 扫描器(Scanner),扫描器的任务很简单,只是简单的进行词法分析, 运用一种类似于 有限状态机(Finite State Machine) 可以很轻松的将源代码的 非空格字符 序列分割成一系列的 记号(Token). 说简单点就是把各个小字符提取成一张表.这一过程和简易命令行shell 的扫描命令内容过程很相似.

词法分析产生的记号一般可以分为如下几类:关键字,标识符,字面量(数字,字符串等)和特殊符号(加号,等号等)在识别记号的同时,扫描器也完成库其他工作,比如将标识符存放到符号表,将数字,字符串常量存放到文字表等.

扫描器的程序工具叫做 lex.

语法分析(Grammar Parser)

对扫描器产生的记号进行语法分析,从而 产生语法树(Syntax Tree) ,整个分析过程采用了 上下文无关语法(Context-free Grammar) 的分析手段.

语法分析器的工具叫做 yacc(Yet Another Compiler Compiler).

语义分析(Semantic Analyzer)

语法分析仅仅完成了对表达式的语法层面分析,但是它并不了解这个语句是否真正有意义.

编译器所能分析的是 静态语义(Static Semantic),是指在编译时可以确定的语义,与之对应的是 动态语义(Dynaic Semantic) 就是只有在运行期才能确定的语义. 经过语义分析后,语法树的表达式都被标识了类型,如果有些类型需要作隐式转换,语义分析程序会在语法树中插入相应的转换节点.

中间语言生成

源代码优化器(Source Code Optimizer) 在源代码级别进行优化,但是由于直接在语法树上做优化比较困难, 所以源代码优化器往往将整个语法树转换成 中间代码(Intermediate Code), 它是语法树的顺序表示. 中间代码有很多种形式,在不同的编译器中有着不同的形式,比较常见的有: 三地址码(Three-address Code)P-代码(P-Code).

中间代码使得编译器可以被分为前端和后端,编译器前端负责产生机器无关的中间代码,后端将中间代码转换成目标机器码. 这样对于一些跨平台的编译器而言,它们可以针对不同的平台使用同一个前端和不同的后端.

目标代码生成与优化

源代码级优化器产生中间代码标志着下面的过程都属于后端,后端主要包括 代码生成器(Code Generator)目标代码优化器(Target Code Optimizer). 代码生成器将中间代码转换为目标机器码,这个过程十分依赖于目标机器.

汇编(Assembly)

将编译后的汇编代码转变为二进制文件,因为汇编都有对应的二进制值,所以汇编器的汇编过程相对于编译器来讲比较简单.

在gcc中,将汇编文件到二进制文件使用命令 gcc -c hello.s -o hello.o / gcc -c hello.c -o hello.o,也可以使用 as 来完成.

经过预编译,编译,汇编之后的 .o 文件被称为 目标文件.

链接(Linking)

将目标文件与库文件以一定的规则, 确定的地址 结合,才能形成最后的可执行文件.

Last Updated 2018-11-21 Wed 07:59.
Render by hexo-renderer-org with Emacs 26.1 (Org mode 9.1.14)