升级GCC
第一步,下载你需要的gcc源码,https://mirror.sergal.org/gnu/gcc/ 到这个地址去找就可以了。这里我们假设安装的是gcc-5.5.0.tar.gz
。国内源为 https://mirrors.ustc.edu.cn/gnu/gcc/
第二步,tar -xzvf gcc-5.5.0.tar.gz
然后cd gcc-5.5.0
第三步,找到./contrib/download_prerequisites
文件,这里面放着所需的依赖,由于是国内的网站可能会在线安装不了(如果在线安装成功,直接进入第四步),这里讲下手动安装,其实就是三个依赖gmp-4.3.2.tar.gz,mpfr-3.1.4.tar.bz2,mpc-1.0.1.tar.gz
,不同版本的gcc可能需要不同的版的,如果出现错误,根据错误提示更换需要的版本即可,这三个依赖最好按照顺序安装,因为它们之间也是有依赖关系的。
- 安装
gmp-4.3.2.tar.gz
,到这里找你要的版本http://ftp.gnu.org/pub/gnu/gmp/,然后解压`tar -xzvf gmp-4.3.2.tar.gz,然后进入目录
cd gmp-4.3.2,再依次执行
./configure —prefix=/data4/zhaodali/usr && make -j 8 && make install` - 安装
`mpfr-3.1.4.tar.bz2
,到这里找你要的版本https://www.mpfr.org/history.html,然后解压`tar -jxvf mpfr-3.1.4.tar.bz2,然后进入目录
cd mpfr-3.1.4,再依次执行
./configure —prefix=/data4/zhaodali/usr && make -j 8&& make install` - 安装
mpc-1.0.1.tar.gz
,到这里找你要的版本http://ftp.gnu.org/gnu/mpc/ 或者 https://gcc.gnu.org/pub/gcc/infrastructure/,然后解压`tar -xzvf mpc-1.0.1.tar.gz,然后进入目录
cd mpc-1.0.1,再依次执行
./configure —prefix=/data4/zhaodali/usr && make -j 8 && make install`
需要注意的是,这里安装的时候是没有sudo
权限的,所以将这些都安装到了/data4/zhaodali/usr
目录下面。
另外,解压tar.gz命令是tar -zxvf xx.tar.gz
;解压tar.bz2的命令是tar -jxvf xx.tar.bz2
接着,编译和安装gcc
1 | cd gcc-5.5.0/../ |
最后,给当前用户添加环境变量:
1 | export PATH=/data4/zhaodali/usr/GCC-5.5.0/bin:$PATH |
GCC与-std编译标准
C 语言为例,发展至今该编程语言已经迭代了诸多个版本,例如 C89(偶尔又称为 C90)、C94(C89 的修订版)、C99、C11、C17,以及当下正在开发的 C2X 新标准。甚至于在这些标准的基础上,GCC 编译器本身还对 C 语言的语法进行了扩展,先后产生了 GNU90、GNU99、GNU11 以及 GNU17 这 4 个版本。
有趣的是,GCC 编译器对 C 语言的很多扩展,往往会被 C 语言标准委员会所采纳,并添加到新的 C 语言标准中。例如,GNU90 中对 C 语言的一些扩展,就融入到了新的 C99 标准中;GNU90、GNU99 中对 C 语言的一些扩展,被融入到了新的 C11 标准中。
C++ 语言的发展也历经了很多个版本,包括 C++98、C++03(C++98 的修订版)、C++11(有时又称为 C++0x)、C++14、C++17,以及即将要发布的 C++20 新标准。和 C 语言类似,GCC 编译器本身也对不同的 C++ 标准做了相应的扩展,比如 GNU++98、GNU++11、GNU++14、GNU++17。
不同版本的 GCC 编译器,默认使用的标准版本也不尽相同。以当前最新的 GCC 10.1.0 版本为例,默认情况下 GCC 编译器会以 GNU11 标准(C11 标准的扩展版)编译 C 语言程序,以 GNU++14 标准(C++14 标准的扩展版)编译 C++ 程序。关于这可以在 GCC 手册中查找。
对于编译 C、C++ 程序来说,借助 -std
选项即可手动控制 GCC 编译程序时所使用的编译标准。也就是说,当使用 gcc
指令编译 C 语言程序时,我们可以借助 -std
选项指定要使用的编译标准;同样,当使用 g++
指令编译 C++ 程序时,也可以借助 -std
选项指定要使用的编译标准。
1 | gcc/g++ -std=编译标准 |
注意,不同版本的 GCC 编译器,所支持使用的 C/C++ 编译标准也是不同的。
下表罗列了常用的 GCC 版本对 C 语言编译标准的支持程度。
注意,表头表示的是各个编译标准的名称,而表格内部的则为 -std 可用的值,例如 -std=c89、-std=c11、-std=gnu90 等(表 2 也是如此)。
下表罗列了常用的 GCC 版本对 C++ 程序编译标准的支持程度。
上面两个表中,有些版本对应的同一编译标准有 2 种表示方式,例如对于 8.4~10.1 版本的 GCC 编译器来说,-std=c89 和 -std=c90 是一样的,使用的都是 C89/C90 标准。另外,GCC 编译器还有其他版本,读者可查阅 GCC文档获得相关信息。
GCC与clang
编译器一般构成
传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd)。
前端解析源码,检查错误,然后编译成指定语言的抽象语法树(Abstract Syntax Tree)。可以选择性地将 AST 转换为新的中间码以进行优化,优化器和后端生成机器码。
优化器负责做各种转化尝试提高代码的执行效率,如消除冗余的计算,优化器通常或多或少地独立于语言和目标机器。后端(也叫代码生成器)负责将代码映射到目标指令集。除了生成正确的代码,它还负责利用目标架构的特殊功能生成性能更好的代码。编译器后端的通用功能包括指令选择、寄存器分配和指令调度。
该模型同样适用于解释器和JIT 编译器。Java 虚拟机(JVM)也是实践了该模型,它使用Java 字节码作为前端和优化器之间的接口。
该设计的优点
当编译器决定支持多语言或多目标架构时,这种经典设计的优势就很明显了。如果编译器在优化时使用一种通用的中间码,那么前端可以用任意的可编译语言编写,且后端可以编译成任何目标机器码。如下图所示。
GCC
GCC(GNU Compiler Collection,GNU编译器套装),是一套由 GNU 开发的编程语言编译器。GCC 原名为 GNU C 语言编译器,因为它原本只能处理 C语言。GCC 快速演进,变得可处理 C++、Fortran、Pascal、Objective-C、Java, 以及 Ada 等他语言。
GCC缺点:GCC的三段式模块必须配套使用,很难做到部分重用。
LLVM
LLVM的提出是为了解决编译器代码重用的问题。LLVM是三段式编译器优化器+后端的SDK集合,提供了一系列对外接口供开发者调用
(1)前端:支持各种组件的前端(Clang、llvm-gcc、GHC),需要遵守LLVM的规则,输出中间代码LLVM IR
(2)优化器:LLVM IR通过一系列分析和优化从而改进代码,然后输入代码生成器生成目标机器码
(3)后端:将优化器优化后的中间代码转换为目标机器的代码
Clang
Clang是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端,底层是由LLVM作为后端。
Clang项目包括Clang前端和Clang静态分析器等,目的是输出代码对应的抽象语法树并将代码编译成LLVM bitcode。接着后端使用LLVM编译成平台相关的机器语言
LLVM/Clang/GCC之间的关系
Clang + LLVM = GCC
开源软件——众所周知,GCC 和 Clang 都是免费的开源软件。但是他们的许可授权很不一样。GCC 是参照 GPL(GNU 公共许可证)授权的,而 Clang/LLVM 是 Apache 许可授权的。比较 GCC 和 Clang 的许可授权,最专业的是律师。
- 支持平台—— GCC 和 Clang 都支持几乎所有的平台。Clang/LLVM 可在 Windows 本机上进行编译,而 GCC 则需要 MinGW 这样的子系统,才能与 Windows 兼容。这样比较 Clang 和 GCC 是不公平的,因为 GCC 没有在本地支持Windows 的计划。
- 代码复杂度—— GCC 是一个非常复杂的软件,有超过 1500 万行代码,耦合很重,很难小粒度复用代码。尽管其前/后端定义清晰明了,但软件在本质上更为单一。对比 GCC,Clang 更多的是模块化架构,将编译后端的算法封装成为了一个个独立的模块并提供对外接口,具有定义良好的扩展点。
- 高效代码生成—— Clang 和 GCC 的代码生成,在空间和时间的复杂度旗鼓相当。因此这种比较毫无意义,因为这两个编译优化工具都基于一种严密的静态分配形式。
- 语言独立的类型系统——在这个标题下对比 Clang 与 GCC 很有意义。由于 Clang/LLVM 对所有兼容语言都使用语言独立的类型系统,因此可以确定指令的确切语义。GCC 则没有语言独立类型系统的设计目标。
- 前端解析器—— GCC 以前有基于 Bison的 LR 解析器,后来转向了手写递归下降解析器。Clang 一直使用手写的确定性递归下降解析器,且可回溯。
- 后端链接器—— GCC 与 Clang 的差异在这个层面最为明显。GCC 使用 ld 作为链接器,支持 ld-gold。Clang 使用 lld 作为链接器。通过一些基准测试,可以看出 lld 比 ld甚至最新的 ld-gold 都快。
- 构建工具—— Clang 与 GCC 的另一个大的区别。GCC 使用 Autotools 和 Make 作为构建工具,而 Clang/LLVM 使用 CMake。
- 调试支持—— GCC 有一个优秀的 GDB 调试器。GDB 历经时间考验,性能优异。Clang 则将 LLDB 调试器构建为 LLVM 上的一组可重用组件。
类别 | GCC | Clang/LLVM |
---|---|---|
许可证 | GNU GPL | Apache 2.0 |
代码模块化 | 一体化架构 | 模块化 |
支持平台 | *inx, Windows (MinGW) | *inx, Natively in Windows |
代码生成 | 高效,有很多编译器选项可以使用 | 高效,LLVM 后端使用了 SSA 表单 |
语言独立类型系统 | 没有 | 有(LLVM的设计初衷) |
构建工具 | 基于 Make | CMake |
解析器 | 最早采用 Bison LR,现在改为递归下解析器 | 手写的递归下降解析器 |
链接器 | LD | lld |
调试器 | GDB | LLDB |
MinGW/MinGW-w64
GCC本身是Linux上的编译器套件,不能在windows上运行,而mingw则是gcc在windows上的移植。
最早的mingw项目只支持编译32位程序,后来分支出的mingw-w64项目则同时支持编译32/64位程序。
mingw-w64项目目前的状况比较复杂,有多个发行分支,具体可以参看官网的下载页。目前windows上最新、最靠谱的发行分支就是MSYS2。
MSYS2
MSYS2(Minimal SYStem 2,下载地址)是与mingw-w64配套的命令行环境,它为windows提供了类似linux的命令和包管理器pacman
,可以直接在命令行查找、安装和卸载各种第三方库和开发工具。
1 | # 比如你想要安装opencv库 |
pacman
同时是ArchLinux的包管理器(就像MacOS上的homebrew
和Ubuntu上的apt
一样),具体使用办法可以查阅ArchWiki(中文))- 实际上MinGW也有一个配套的MSYS,但它没有包管理器
- git bash实际上是一个删减版的MSYS2,在安装文件夹下可以看到MSYS2的目录结构,但它也没有包管理
- pacman本地安装使用
pacman -U + 路径
安装gcc、gdb、cmake
以64为例,32位需要将x86_64
替换为-i686
。
1 | pacman -S mingw-w64-x86_64-toolchain |
安装完毕之后,需要添加环境变量,这里以windows系统为例,MSYS2的安装路径为C:\Program Files\msys64
,需要在系统PATH
变量中添加C:\Program Files\msys64\mingw64\bin
。
参考
centOS系统gcc升级步骤(亲自测试成功)
tar.gz和tar.bz2解压命令
GCC 安装到自定义目录
GCC -std编译标准一览表
【编译原理】GCC/Clang/LLVM的区别与联系
「LLVM」开源软件架构之 LLVM
GCC vs Clang: 两大编译器巨头的龙争虎斗