一、C++代码编译流程

以下面 C++代码为例:

1
2
3
4
5
6
7
#include <stdio.h>

int main()
{
printf("Hello World");
return 0;
}

编译成二进制文件需要经过如下 4 个过程:

  • 预编译:将 hello.c 和 stdio.h 预编译为 hello.i
  • 编译:将 hello.i 编译为 hello.s
  • 汇编:将 hello.s 翻译为机器指令 hello.o(.o 目标文件)
  • 链接:链接各种需要的库和其他目标文件(该 hello 程序不需要)得到可执行文件 hello.out(相当于 windows 的.exe)。

二、编译器架构

编译器通常分为三个部分:

  • 前端(FrontEnd)
  • 优化器(Optimizer)
  • 后端(BackEnd)

在编译过程中,前端主要负责词法和语法分析,将源代码转化为抽象语法树;优化器则是在前端的基础上,对得到的中间代码进行优化,使代码更加高效;后端则是将已经优化的中间代码转化为针对各自平台的机器代码。

2.1 GCC

GCC(GNU Compiler Collection,GNU 编译器集合)是一个完整的编译器,包含 FrontEnd、Optimizer 和 BackEnd。

2.2 LLVM 架构

Clang是 LLVM 编译器架构的前端,可以用来编译 C,C++,ObjectiveC 等语言;

LLVM是该架构的优化器和后端;

二者统称为 LLVM 架构。

三、编译版本选择

3.1 x86、x86-64、AMD64

x86 是指 Intel 的开发的一种 32 位指令集,从 386 时代开始,一直沿用至今,所有 Intel 早期的 cpu,以及 amd 早期的 cpu 都支持这种指令集。

由于AMD 领先 Intel 制造出兼容 x86 的商用 CPU,AMD 称之为 AMD64,且得到用户的认同。Intel 后面才决定设计一种不兼容 x86 的全新 64 位指令集,称之为 IA-64,由于是全新设计的 CPU,没有编译器、不支持 Windows,后来还不得不在时机落后的情况下开始支持 AMD64 指令集,因此 Intel 将 IA-64 换了个名字,叫 x86_64,表示 x86 指令集的 64 位扩展。

x86_64、x64、AMD64 实际上是一个东西,我们现在用的 intel/amd 的桌面级 CPU 基本上都是 x86_64。

3.2 i386

i386 即 Intel 80386。 其实 i386 通常被用来作为对 Intel(英特尔)32 位微处理器的统称。

但是目前更多的时候,我们公认 i386 为 32 位系统,其实就是 x86。

3.3 i686

i686 仍然属于 i386 体系,不过相对于 386 CPU 的特性作了指令优化。

3.4 MSVC 编译器版本描述

  • x86:编译器为 x86 版本,输出文件为 x86。
  • amd64_x86:编译器为 amd64 版本,输出文件为 x86。
  • amd64:编译器为 amd64 版本,输出文件为 amd64。
  • x86_amd64:编译器为 x86 版本,输出文件为 amd64。