C语言的经典程序“Hello World”并不难写,很多朋友都可以闭着眼将它写出来。那么编译一个“Hello World”到底经历了怎样的过程呢?
从源代码到可执行文件
我们将这个文件命名为hello.c:
#include int main() { printf("Hello World"); return 0;}
程序的第一行引用了stdio.h,stdio.h里有一些C标准库预定义好的方法,比如printf()方法,printf()方法可将字符串打印到标准输出流。
接着,int main()定义了主函数,是这个程序的入口。main()方法的返回值是int,在本程序中,我们返回了0,0表示程序正常结束,非0的结果表示程序异常结束。
在进行下一步的编译之前,我们需要明确:计算机基于二进制,运行在计算机上的程序和数据本质上都是二进制的。二进制写起来难度太大,不适合开发,于是人们一步步抽象,最后发明了高级语言,比如C、C++、Java、Python等。使用高级语言编程,需要通过编译器或解释器,将源代码“翻译”成计算机可执行的二进制文件。可在计算机上直接执行的二进制文件被称作可执行文件。无论是在Windows上还是Linux上,.c、.cpp文件是无法直接运行的,需要使用编译工具转化为可执行文件。例如,.exe文件可以在Windows上被计算机运行。
Hello World程序比较简单,现实中我们用到的很多软件都由成百上千个源代码文件组成,将这些源代码文件最终转化为可执行文件的过程,被称为构建(Build)。复杂软件的构建过程会包括一系列活动:
- 从版本控制系统(比如git)上获取最新的源代码
- 编译当前源代码、检查所依赖的其他库或模块
- 执行各类测试,比如单元测试
- 链接(Link)所依赖的库或模块
- 生成可执行文件
构建大型软件确实非常麻烦,一般都会有一些工具辅助完成上述工作。我们把上述这些过程拆解,只关注编译的过程。编译一般分为四步:预处理(Preprocess)、编译(Compile)、汇编(Assembly)和链接(Link)。
下面以Linux下的GCC编译过程为例做一些拆解。在介绍编译前,我们先简单介绍一下GCC。
GCC简介
GCC是GNU Compiler Collection的缩写,GCC是一系列编译器的集合,是Linux操作系统的核心组件之一。GCC最初名为GNU C Compiler,当时它只是一款C语言的编译器,不过随着后续迭代,它支持C++、Fortran、Go等语言,GCC也因此成为一个编译器集合。GCC有以下特点:
- GCC支持的编程语言多。比如,g++是C++编译器,gfortran是Fortran编译器。
- GCC支持的硬件全。GCC可以将源代码编译成x86_64、ARM、PowerPC等硬件架构平台的可执行文件。
- GCC支持众多业界标准。GCC能