软件的构建分解为4个步骤,分别是预处理(Prepressing),编译(Compilation),汇编(Assembly),链接(Linking)。
下面以C语言为例,分别对这4步做简单说明:
预处理
预处理主要是将源文件中以"#"开始命令进行处理,主要为:
1、将宏定义(#define)在源文件引用位置原封原样的展开(所以使用宏定义要多用括号打包整个定义)。
2、处理条件预编译(#ifdef ...),得出正确的条件流程。
3、在包含文件的预编译处(#include )将对应的头文件展开,如果头文件也有包含其他文件,则递归展开。
4、删除代码中的注释
5、添加行号和文件名标识,便于编译器调试或警告等可以显示行号
6、保留编译器设置指令(#pragma),用于编译器
预处理后的文件为".i"后缀,我们可以查看此文件来判断整理后的代码是否正确。
编译
编译就是把预处理过程的".i"文件处理为".s"汇编文件,这个过程会经历词法分析、语法分析、语义分析和优化步骤。
词法分析:
将代码逐个扫描,根据当前所使用语言的规则分离出关键字、标识符、特殊符号、字面量等,分类生成有序的表格。
语法分析:
根据使用语言的语法规则,将词法分析的表格进行语法检查,并生成语法树。语法树也是表明了一行代码中运行的优先级及顺序等。
若有语法错误,在这步就会报错。
语义分析:
将语法树进行语义分析,经过语言分析后,标识符的类型就能够被确定(判断是否需要强制转换等等)。
若有语义错误,在这步就会报错(比如两个指针相乘)。
优化:
将最后的语法树转换为中间代码后优化,最终生成和硬件有关的汇编代码。
汇编
汇编将编译生成的汇编文件根据硬件构架而转换成对应的机器码文件,也叫目标文件(Object File),为".o"后缀。
注意:此时汇编而成的文件中,内部变量及函数等的最终地址需要通过链接才能确定。
链接
链接将多个目标文件中指令及其对其他符号的地址引用修正,生成可执行的文件。
主要包括地址和空间分配(Address and Storage Allocation)、符号决议(Symbol Resolution)、重定位(Relocation)等步骤。