C/C++——编译器 GCC与LLVM_gcc llvm-程序员宅基地

技术标签: C/C++  c语言  

1.编译器

简单地说,编译器可以看作是一个语言翻译器。就像把中文翻译成英语一样,编译器可以把高级语言翻译成计算机能够执行的机器语言。这样看来,GCC可以算得上是一个精通多国语言的高级翻译官了。

最简单的GCC使用指令如下所示:
gcc hello.c -o hello

GCC接受hello.c作为输入,最后产生目标可执行代码hello。

这个简单的流程实际上经历了很多步骤,依次呼叫了cpp,gcc自己,gas以及ld来进行完整的编译流程,最后生成最终的可执行文件hello。

以中间代码为分界,前面的词法分析、语法分析、语义分析我们把它称之为前端处理,后面的优化和目标代码生成我们称之为后端处理。

2.编译器前端、后端

试想一下,是否可以为不同的高级语言单独写一个前端,然后为不同的处理器架构单独写一个后端呢?

GCC基本上也是这么实现的,不过不要误会,并没有一个统一的gcc执行程序能够处理如此多的前端和后端,每个语言的编译器都是一个独立的程序(如C语言的编译器是gccC++的编译器是g++),而不同的后端也要对应不同的可执行程序。

前端的主要功能是产生一个可供后端处理的语法树,而语法树结构实际上很难与处理器架构脱钩,这些都是编译器应用中需要解决的问题。

4.GNU与GCC

4.1 GNU

“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编译器,却非常的好,在移植到各大操作系统上一直广泛使用至今

4.2 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编译,有很大的机会可得到正确无误的输出程序。

  1. mac之前的cocoa框架便是用GCC编译的,所以ios与mac os都是默认使用的GCC编译器(现在是clang与llvm)
  2. android的系统层因为是linux内核,自然也是GCC编译的,但是android的app因为是运行在Dalvik虚拟机,所以用的不是GCC。
  3. windows的应用,大部分都是使用的vs系列的编译器,毕竟是windows自家的编译器,用到GCC的不多。

4.3.GCC强大的两个真正原因

是因为它支持了众多的前端和后端吗?这些都不过是一个表象而已。
GCC是一款真正自由的编译器,我们可以随时把代码拿过来修改以实现自己需要的功能。

  1. 在编译器中增加硬件平台指令(后端)
    如果你的硬件平台增加了一些指令,而普通的编译器并不能产生这些指令怎么办?在GCC后端添加这些指令吧。

  2. 为编程语言添加新的语法功能(前端)
    如果你觉得C语言用的不太顺手,想给它添加一些功能怎么办?修改GCC的前端吧。

因为有了GCC,我们才拥有这些自由,以及迅速实现自己想法的能力,而这些才是GCC强大背后的基础。

5. Clang与LLVM

LLVM(Low Level Virtual Machine)是一个自由软件项目,它是一种编译器基础设施,以C++写成,包含一系列模块化的编译器组件和工具链,用来开发编译器前端和后端。它是为了任意一种编程语言而写成的程序,利用虚拟技术创造出编译时期、链接时期、运行时期以及“闲置时期”的最优化。它最早以C/C++为实现对象,而当前它已支持包括ActionScript、Ada、D语言、Fortran、GLSL、Haskell、Java字节码、Objective-C、Swift、Python、Ruby、Rust、Scala以及C#等语言。

5.1 LLVM 设计思想

以下是传统的三相设计思想:

  1. 前端
  2. 优化器
  3. 后端

对于iOS开发者来说,整个流程可以简要概括为 Clang对代码进行处理形成中间层作为输出,llvm把CLang的输出作为输入生成机器码。

GCC目前作为跨平台编译器来说它的兼容性无异是最强的,兼容最强肯定是以牺牲一定的性能为基础的,苹果为了提高性能,因此专门针对mac系统开发了专用的编译器Clang与LLVM,Clang用于编译器前端,LLVM用于后端。

5.2 Clang

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倍,还能针对用户发生的编译错误准确地给出建议。

5.2 LLVM

LLVM 命名最早源自于底层虚拟机(Low Level Virtual Machine)的缩写,由于命名带来的混乱,目前LLVM就是该项目的全称。LLVM 核心库提供了与编译器相关的支持,可以作为多种语言编译器的后台来使用。能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。LLVM的项目是一个模块化和可重复使用的编译器和工具技术的集合。

LLVM,它是一个编译器的基础建设,以C++写成。它是为了任意一种编程语言写成的程序,利用虚拟技术,创造出编译时期,链接时期,运行时期以及“闲置时期”的优化。

Apple(包括中后期的NeXT) 一直使用GCC作为官方的编译器。GCC作为开源世界的编译器标准一直做得不错,但Apple对编译工具会提出更高的要求,GCC的编译器已经慢慢无法满足苹果的需求:

  • 一方面,是Apple对Objective-C语言(甚至后来对C语言)新增很多特性,但GCC开发者并不买Apple的帐——不给实现,因此索性后来两者分成两条分支分别开发,这也造成Apple的编译器版本远落后于GCC的官方版本。
  • 另一方面,GCC的代码耦合度太高,不好独立,而且越是后期的版本,代码质量越差,但Apple想做的很多功能(比如更好的IDE支持)需要模块化的方式来调用GCC,但GCC一直不给做,从根本上限制了LLVM-GCC 的开发。

所以,这种让Apple一直在寻找一个高效的、模块化的、协议更放松的开源替代品,于是LLVM就这样产生了。Xcode4之后,苹果的默认编译器已经是LLVM了。Clang作为编译器前端,LLVM作为编译器后端。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012564117/article/details/94898806

智能推荐

路漫漫其修远兮:js的成长经历(十七)—— vue基础(一)-程序员宅基地

文章浏览阅读241次。目录什么是Vue.js为什么要学习流行框架框架和库的区别Node(后端)中的 MVC 与 前端中的 MVVM 之间的区别Vue.js 基本代码 和 MVVM 之间的对应关系Vue之 - 基本的代码结构`Vue指令之`插值表达式`、`v-cloak``v-text`和`v-html`Vue指令之`v-bind`的三种用法Vue指令之`v-on`和`跑马灯效果`跑马灯效果Vue指令之`v-on的缩写...

node.js云学堂微信小程序学习系统的设计与实现毕业设计源码011735_基于微信平台的《javascript程序设计》学习系统的设计与实现-程序员宅基地

文章浏览阅读246次。用户:免费好课、直播公开课、课程信息推荐、云学堂资讯、精选好课管理员:首页、用户管理、课程信息管理、精选好课管理、直播公开管理、免费分类管理、云学堂资讯管理_基于微信平台的《javascript程序设计》学习系统的设计与实现

【解决Anaconda3安装问题】conda --version 不是内部命令、没有script文件_conda --version没反应-程序员宅基地

文章浏览阅读9.7k次,点赞11次,收藏9次。这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Ma..._conda --version没反应

flex绑定数据-程序员宅基地

文章浏览阅读664次。在使用Flex开发的过程中,数据绑定是一定会遇到的,这种技术简单,又有点好玩,重要的是它让开发变得简单了。 在Flex中,数据绑定的方式有这么三种:直接在“{}”中填写绑定变量 使用标签绑定 使用ActionScript中的BindingUtils类绑定 示例1中的绑定方式即是第一种绑定方式,在“{}”中直接填写inputUnit.text,表

超融合、软件定义存储(SDS)、分布式存储以及Server SAN的区别与联系_部署方式包括集中式存储、分布式存储、超融合等-程序员宅基地

文章浏览阅读5.7k次。一时让人眼花缭乱的技术概念存储设备一直作为计算机系统的重要组成部分,过去很长一段时间,用户习惯于使用 SAN 存储作为保存企业关键业务数据的不二选择。基于 SAN 存储为核心的三层式基础架构(服务器-存储网络-存储设备),成为企业中最常用的基础架构,也称作传统架构。互联网的出现,信息量呈现爆炸式增长,人类产生数据的速度超越了以往所有时代的总和,需要存储的数据量也是急剧地增长。大数据,人工智能,物联网等新技术出现,对存储提出了新的需求。于是市面涌现了一系列的关于存储的新的技术概念和名词(包括 软件定义存储_部署方式包括集中式存储、分布式存储、超融合等

【Unity3d】百度AI人脸识别实例——描绘人脸特征点_unity 如何判断texture2d 是否黑色-程序员宅基地

文章浏览阅读5.1k次。上一篇文章介绍了在Unity3d中使用百度AI人脸识别功能,本文将用一个描绘人脸特征点的程序来讲解对SDK的调用。首先我们需要搭建一个简单的场景:一个开始测试的按钮,一张供测试和绘制特征点的图片,和显示debug信息的文字框: 然后新建一个叫FaceDetector的脚本,定义变量:public Text debugInfo; // 显示d_unity 如何判断texture2d 是否黑色

随便推点

Thinkjs——采用nodemailer发送邮件_thinkjs服务端发送邮件-程序员宅基地

文章浏览阅读863次。介绍 ThinkJS 是一款面向未来开发的 Node.js 框架,整合了大量的项目最佳实践,让企业级开发变得如此简单、高效。从 3.0 开始,框架底层基于 Koa 2.x 实现,兼容 Koa 的所有功能。 官方文档传送门点这里步骤: 1.创建一个thinkjs项目,执行 thinkjs new [project_name] 来创建项目,如: 2.安装如下包:..._thinkjs服务端发送邮件

操作系统 - 进程管理_实现生产者—消费者问题基于消息队列-程序员宅基地

文章浏览阅读385次。目录进程与线程1. 进程2. 线程3. 区别进程状态的切换进程调度算法1. 批处理系统1.1 先来先服务 first-come first-serverd(FCFS)1.2 短作业优先 shortest job first(SJF)1.3 最短剩余时间优先 shortest remaining time next(SRTN)1.4 最高相应比优先..._实现生产者—消费者问题基于消息队列

C语言实验4:指针-程序员宅基地

文章浏览阅读1.5k次,点赞39次,收藏18次。指针是一个变量,其值是另一个变量的地址。通过指针,可以直接访问存储在该地址上的数据。

SQL 数据库 学习 024 查询-07 order by 的用法 --- 以某个字段排序_sql使数据按字段排序-程序员宅基地

文章浏览阅读1.3w次。我的电脑系统:Windows 10 64位SQL Server 软件版本: SQL Server 2014 Express 本篇博客里面使用了 scott 库,如何你现在还没有添加这个库到你的服务器里面,请在查看本篇博客前,访问这篇博文来在你的服务器里面附加scott库。order by — 以某个字段排序例子:select * from emp order by sal; --默认_sql使数据按字段排序

解决360浏览器不支持IDM下载的问题_360下载失败怎么用idm安装-程序员宅基地

文章浏览阅读4.5w次,点赞2次,收藏2次。像360安全浏览器和360极速浏览器的设置中,下载工具都只能选择自己。不能选择IDM下载。 如图: 如何让它们支持IDM下载呢? 在IDM的文件夹中,可以看到一个扩展文件,将它拖动的浏览器中进行安装即可。 如图: 然后打开IDM,可以看到360安全/技术浏览器了。如果没有手动添加浏览器。 然后就可以用IDM下载了。..._360下载失败怎么用idm安装

scala方法中的变量_Scala中的变量-程序员宅基地

文章浏览阅读405次。scala方法中的变量 Scala变量 (Scala variables)A variable is named a reference to a memory location. The location stores the data that is used by the program. 变量被称为对存储位置的引用。 该位置存储程序使用的数据。 Based on the data t..._scala 方法 变量