C++编译过程

参考 https://www.runoob.com/w3cnote/working-process-of-the-compiler.html

配置

编译器工作前,需要知道系统环境:

  1. 标准库的位置
  2. 软件的安装位置
  3. 安装的组件
    ……
    配置保存在configure的脚本文件里,通常用autoconf生成。

确定标准库、头文件的位置

配置文件给出一个清单,列出具体目录,编译的时候依次寻找。

确定依赖关系

编译器确定编译的先后顺序,如果A依赖于B,那么编译器会:
(1)只有在B文件编译完成后,才开始编译A文件。
(2)当B文件发生变化时,A文件会被重新编译。
编译顺序保存在一个叫做makefile的文件中,里面列出哪个文件先编译,哪个文件后编译。而makefile文件由configure脚本运行生成,这就是为什么编译时configure必须首先运行的原因。

在确定依赖关系的同时,编译器也确定了,编译时会用到哪些头文件。

头文件预编译

不同源码编译的时候可能会用同一个头文件,预先编译头文件会节省后面的时间,保证只编译一次。

但不是头文件的所有内容都会被编译,#define等声明宏的命令不会被预编译。

预处理

编译器开始替换源码中的头文件和宏。移除注释。

extern int fputs(const char *, FILE *);
extern FILE *stdout;

int main(void)
{
    fputs("Hello, world!\n", stdout);
    return 0;
}

此步之后得到 .i 文件

编译,生成目标代码

开始生成机器码,对于某些编译器还会转成汇编码(.s文件),再转成机器码。

汇编器把.s文件转成.o文件。

链接

静态链接

把库文件,启动文件,其他目标文件链接到.o文件上。生成可执行文件。此为静态链接,即编译期间链接。Windows下是.lib,Linux下是.a文件。

优点:装载快,执行快,不需要考虑用户是否存在正确的.lib文件。缺点:可执行文件大,可能包含相同代码,造成浪费,可扩展性低。

动态链接

在运行的时候才进行链接,Windows下是.dll,Linux下是.so文件。

优点:可执行文件小,扩展性好,适合大规模开发,可维护性好,更换动态链接文件不需要换exe文件。缺点:装载略慢,执行略慢,需要考虑用户是否存在正确的.lib文件。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!