简单地说,编译器可以看作是一个语言翻译器。就像把中文翻译成英语一样,编译器可以把高级语言翻译成计算机能够执行的机器语言。这样看来,GCC可以算得上是一个精通多国语言的高级翻译官了。
最简单的GCC使用指令如下所示:
gcc hello.c -o hello
GCC接受hello.c作为输入,最后产生目标可执行代码hello。
这个简单的流程实际上经历了很多步骤,依次呼叫了cpp,gcc自己,gas以及ld来进行完整的编译流程,最后生成最终的可执行文件hello。
以中间代码为分界,前面的词法分析、语法分析、语义分析我们把它称之为前端处理,后面的优化和目标代码生成我们称之为后端处理。
试想一下,是否可以为不同的高级语言单独写一个前端,然后为不同的处理器架构单独写一个后端呢?
GCC基本上也是这么实现的,不过不要误会,并没有一个统一的gcc执行程序能够处理如此多的前端和后端,每个语言的编译器都是一个独立的程序(如C语言的编译器是gcc,C++的编译器是g++),而不同的后端也要对应不同的可执行程序。
前端的主要功能是产生一个可供后端处理的语法树,而语法树结构实际上很难与处理器架构脱钩,这些都是编译器应用中需要解决的问题。
“GNU,名称来自Gnu’s Not Unix"的缩写,一个类UNIX的操作系统,由GNU计划推动,目标在于创建一个完全兼容于UNIX的自由软件环境。
由于当时UNIX系统是商业软件,是收费的,而且有一部分源码是没有开放的,所以在1983年,理查德·斯托曼提出GNU计划,希望发展出一套完整的开放源代码操作系统来取Unix,计划中的操作系统,名为GNU。
因此,GNU的出现的目的就是为了取代UNIX系统。
但是操作系统是包括很多软件的,除了操作系统内核之外,还要有编辑器,编译器,shell等等一些软件来支持。
1989年,GNU项目中的其他部份,如编辑器、编译器、shell等都已经完成,独缺操作系统核心。
1990年,自由软件基金会开始正式发展Hurd,作为GNU项目中的操作系统。
1991年,Linux出现,所有GNU项目中运行于用户空间的软件,都可以在Linux上使用。许多开发者转向于Linux,Linux成为常见的GNU计划软件运行平台。理查德·斯托曼主张,Linux操作系统使用了许多GNU计划软件,应正名为GNU/Linux,但没有得到Linux社区的一致认同,形成GNU/Linux命名争议。
1992年,Linux与其他GNU软件结合,完全自由的操作系统正式诞生。许多程序员参与了Linux的开发与修改,也经常将Linux当成开发GNU计划软件的平台。该操作系统往往被称为“GNU/Linux”或简称Linux。但Linux本身不属于GNU计划的一部份,只是使用了许多GNU计划软件(包括GCC编译器,文本编译器等),GNU计划自己的内核Hurd依然在开发中,但直到2013年为止,都还没有稳定版本发布。
GNU计划采用了部分当时已经可自由使用的软件,例如TeX排版系统和XWindow视窗系统等。不过GNU计划也开发了大批其他的自由软件,这些软件也被移植到其他操作系统平台上,例如Microsoft Windows、BSD家族、Solaris及Mac OS。
许多UNIX系统上也安装了GNU软件,因为GNU软件的质量比之前UNIX的软件还要好。
所以,GNU计划中的许多软件目前在所有的操作系统中都应用广泛(Unix,mac,linux,windows,bsd…),最出名的就是GCC了
GNU计划本来是为了开发一个自由系统来取代UNIX的,但是由于开发的内核hurd一直不怎么样,这个系统至今都没出稳定版本,然而GNU计划中开发的其他一些自由软件,比如GCC编译器,却非常的好,在移植到各大操作系统上一直广泛使用至今。
“GCC(GNU Compiler Collection,GNU编译器套装),是一套由GNU开发的编程语言编译器。它是一套以GPL及LGPL许可证所发布的自由软件,也是GNU项目的关键部分,亦是自由的类Unix及苹果电脑Mac OS X 操作系统的标准编译器。
GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。
GCC原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC很快地扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,以及Go与其他语言。
原本用C开发,后来因为LLVM、Clang的崛起,令GCC更快将开发语言转换为C++。许多C的爱好者在对C++一知半解的情况下主观认定C++的性能一定会输给C,但是Taylor给出了不同的意见,并表明C++不但性能不输给C,而且能设计出更好,更容易维护的程序 。
由于GCC已成为GNU系统的官方编译器(包括GNU/Linux家族),它也成为编译与创建其他操作系统的主要编译器,包括BSD家族、Mac OS X、NeXTSTEP与BeOS。
GCC通常是跨平台软件的编译器首选。有别于一般局限于特定系统与运行环境的编译器,GCC在所有平台上都使用同一个前端处理程序,产生一样的中介码,因此此中介码在各个其他平台上使用GCC编译,有很大的机会可得到正确无误的输出程序。
是因为它支持了众多的前端和后端吗?这些都不过是一个表象而已。
GCC是一款真正自由的编译器,我们可以随时把代码拿过来修改以实现自己需要的功能。
在编译器中增加硬件平台指令(后端)
如果你的硬件平台增加了一些指令,而普通的编译器并不能产生这些指令怎么办?在GCC后端添加这些指令吧。
为编程语言添加新的语法功能(前端)
如果你觉得C语言用的不太顺手,想给它添加一些功能怎么办?修改GCC的前端吧。
因为有了GCC,我们才拥有这些自由,以及迅速实现自己想法的能力,而这些才是GCC强大背后的基础。
LLVM(Low Level Virtual Machine)是一个自由软件项目,它是一种编译器基础设施,以C++写成,包含一系列模块化的编译器组件和工具链,用来开发编译器前端和后端。它是为了任意一种编程语言而写成的程序,利用虚拟技术创造出编译时期、链接时期、运行时期以及“闲置时期”的最优化。它最早以C/C++为实现对象,而当前它已支持包括ActionScript、Ada、D语言、Fortran、GLSL、Haskell、Java字节码、Objective-C、Swift、Python、Ruby、Rust、Scala以及C#等语言。
以下是传统的三相设计思想:
对于iOS开发者来说,整个流程可以简要概括为 Clang对代码进行处理形成中间层作为输出,llvm把CLang的输出作为输入生成机器码。
GCC目前作为跨平台编译器来说它的兼容性无异是最强的,兼容最强肯定是以牺牲一定的性能为基础的,苹果为了提高性能,因此专门针对mac系统开发了专用的编译器Clang与LLVM,Clang用于编译器前端,LLVM用于后端。
GCC系统庞大而笨重,而Apple大量使用的Objective-C在GCC中优先级很低。此外GCC作为一个纯粹的编译系统,与IDE配合得很差。加之许可证方面的要求,Apple无法使用LLVM 继续改进GCC的代码质量。于是,Apple决定从零开始写 C、C++、Objective-C语言的前端Clang,完全替代掉GCC。
它的目标是提供一个GNU编译器套装(GCC)的替代品。 Clang项目包括Clang前端和Clang静态分析器等。Clang是LLVM编译器工具集的前端(front-end),目的是输出代码对应的抽象语法树(Abstract Syntax Tree, AST),并将代码编译成LLVM Bitcode,接着在后端(back-end)使用LLVM编译成平台相关的机器语言。
Clang支持C、C++、Objective C。
Clang本身性能优异,其生成的抽象语法树AST所耗用掉的内存仅仅是GCC的20%左右。FreeBSD 10将Clang/LLVM作为默认编译器。测试证明Clang编译Objective-C代码时速度为GCC的3倍,还能针对用户发生的编译错误准确地给出建议。
LLVM 命名最早源自于底层虚拟机(Low Level Virtual Machine)的缩写,由于命名带来的混乱,目前LLVM就是该项目的全称。LLVM 核心库提供了与编译器相关的支持,可以作为多种语言编译器的后台来使用。能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。LLVM的项目是一个模块化和可重复使用的编译器和工具技术的集合。
LLVM,它是一个编译器的基础建设,以C++写成。它是为了任意一种编程语言写成的程序,利用虚拟技术,创造出编译时期,链接时期,运行时期以及“闲置时期”的优化。
Apple(包括中后期的NeXT) 一直使用GCC作为官方的编译器。GCC作为开源世界的编译器标准一直做得不错,但Apple对编译工具会提出更高的要求,GCC的编译器已经慢慢无法满足苹果的需求:
所以,这种让Apple一直在寻找一个高效的、模块化的、协议更放松的开源替代品,于是LLVM就这样产生了。Xcode4之后,苹果的默认编译器已经是LLVM了。Clang作为编译器前端,LLVM作为编译器后端。