前言

GCC(GNU Compiler Collection,GNU编译器合集)是linux以及其他类UNIX平台上进行开源项目,软件开发等必不可少的工具链组成之一(工具链的其他成员包括 binutils,Glibc,libstdc++ 等)

另外,对于程序员以及系统管理员而言,经常需要从软件的源码手动编译安装,而不论是configure脚本,还是make工具/makefile文件,最终都需要调用gcc(或者其它编译器)来进行实际的编译工作,因此,经常需要使用gcc的新版特性,并且与旧版gcc共存,根据实际的需求进行调用。


在本篇博文中,我们以centos6.5  32位 系统上已安装的旧版gcc二进制可执行文件以及Glibc C库为基础,从网上下载最新版的gcc源码包手动编译安装,进行简单的测试,并且与make工具整合,从configure脚本进行参数传递,优化编译等。

整个过程简单明了,图文代码并茂,希望能起到抛砖引玉的作用,激发广大爱好者编程与学习的热情。   

                                  

                 《基础知识/先决条件》


软件包名词解释             centos6.5默认有无安装/是否需要安装才能从源码编译安装gcc


Glibc              GNU项目实现的C标准库。

分源码包和二进制RPM包,centos6.5“最小桌面”安装方案,默认已通过RPM包的形式装上,

Glibc是非交叉编译环境下,从源码编译安装gcc必备的。

***** 如果是交叉编译的环境,即在一种硬件架构/操作系统上编译(宿主机),但是生成的二进制可执行文件要在另一种硬件架构/操作系统上运行(目标机),在这种情况下,不能依赖宿主机器上已编译的C库,最好是自行下载glibc的源码并编译。 *****



glibc-static       GNU C标准库的静态版,只有在用于 -static 静态链接时才需要,

在yum软件仓库上只有二进制RPM包,centos6.5“最小桌面”安装方案,默认没有安装,

glibc-static是非交叉编译环境下,从源码编译安装gcc必备的,而且它依赖于Glibc(要先装Glibc)


libstdc++            兼容GCC的C++标准库。

在yum软件仓库上只有二进制RPM包,centos6.5“最小桌面”安装方案,默认已通过RPM包的形式装上,

从源码编译安装gcc时,如果需要编译其组件:c++编译器(g++),则需要依赖 libstdc++,所幸系统已经安装好了


gcc(已安装的旧版)    GNU编译器合集,包含c,c++编译器,还有Fortran,Ada等编译器,

分源码包和二进制RPM包,yum软件仓库上只有二进制RPM包,而且是旧版的(4.4.7版),

centos6.5“最小桌面”安装方案,默认连这个旧版都没有装上,

从源码编译安装新版gcc前,要求系统上已经安装有旧版gcc



gcc-c++         GNU编译器合集的c++增强支持包,它向gcc的c++编译器提供了更多对当前c++标准规范的支持,包含模板和错误处理。

在yum软件仓库上只有二进制RPM包,centos6.5“最小桌面”安装方案,默认没有安装,

经过笔者的测试,如果系统上没有预先安装 gcc-c++,则在编译新版gcc后面的 make 阶段会因为产生错误而退出,并且,gcc-c++ 可能还需要额外的 libstdc++ 支持,

因此最好还是通过yum先把 gcc-c++ 装上。

综上所述,在centos6.5“最小桌面”安装方案前提下,我们需要安装的软件包有:

gcc, gcc-c++, glibc-static


                 准备工作》


首先,分别验证这3个软件包的状态,确保万无一失:

[root@centos6-5 桌面]# rpm -qi gcc
[root@centos6-5 桌面]# locate gcc
[root@centos6-5 桌面]# which gcc
[root@centos6-5 桌面]# whereis gcc
[root@centos6-5 桌面]# rpm -qi gcc-c++
[root@centos6-5 桌面]# locate gcc-c++
[root@centos6-5 桌面]# which gcc-c++
[root@centos6-5 桌面]# whereis gcc-c++
[root@centos6-5 桌面]# rpm -qi glibc-static
[root@centos6-5 桌面]# locate glibc-static
[root@centos6-5 桌面]# which glibc-static
[root@centos6-5 桌面]# whereis glibc-static



wKiom1PXDkzy5MXXAAnSPomFtSo998.jpg



其次,我们可以先了解一下,关于已经安装的2个软件包:Glibc 和 libstdc++ 的详细信息:

[root@centos6-5 桌面]# rpm -qi glibc
[root@centos6-5 桌面]# locate glibc
[root@centos6-5 桌面]# which glibc
[root@centos6-5 桌面]# whereis glibc


[root@centos6-5 桌面]# rpm -qi libstdc++
[root@centos6-5 桌面]# locate libstdc++
[root@centos6-5 桌面]# which libstdc++
[root@centos6-5 桌面]# whereis libstdc++


wKioL1PXEsHBZO8dAAYBOkkdiVQ318.jpg



wKiom1PXFGnhs0qKAAqlDcCRYnA800.jpg



有了上面的基础知识后,就可以用yum 来下载安装二进制形式的旧版gcc以及 glibc-static ,gcc-c++的RPM 软件包:

(顺便一提,yum 上的glibc版本较新,可用于升级系统现有的glibc)



[root@centos6-5 桌面]# yum check-update
[root@centos6-5 桌面]# yum list gcc gcc-c++ glibc-static glibc 
[root@centos6-5 桌面]# yum install glibc-static gcc gcc-c++

wKiom1PXHO3ifybJAAbEqZ7KIt4439.jpg


wKioL1PXJWjST1nyAAzvVOGqtsA782.jpg


wKiom1PXKI_B0rUyAAuSVd7U3dk449.jpg


我们先查询一下安装好的旧版gcc,g++的相关文件路径,后面的阶段会用到这些路径:(用于实现在系统上共存新版和旧版的GCC,根据需求选择性调用)


[root@centos6-5vm 桌面]# which gcc
[root@centos6-5vm 桌面]# which g++
[root@centos6-5vm 桌面]# whereis gcc
[root@centos6-5vm 桌面]# whereis g++
[root@centos6-5vm 桌面]# rpm -ql glibc-static


wKioL1PXMTKTZegTAAcwXuCP6l8102.jpg


从上面的输出得知:

首次在系统安装(旧版的)gcc后,安装在 /usr/bin/gcc  /usr/lib/gcc  /usr/libexec/gcc    /usr/share/man/man1/gcc.1.gz  等路径下,

由此可见,从二进制旧版gcc安装时,系统默认将gcc的

可执行文件(安装到 /usr/bin/gcc),

库文件(安装到 /usr/lib/gcc),

编译器(cc1)/预链接器(collect2)(安装到 /usr/libexec/gcc)

放在不同的目录下,
(头文件放在 /usr/lib/gcc/i686-redhat-linux/4.4.4/include 目录下)


其中,cc1负责对源文件实际的编译工作;collect2进行预链接处理,实际的链接由链接器ld完成;
而centos6.5最小桌面安装默认将汇编器as的可执行文件安装在  /usr/bin/as  ;默认将链接器ld的可执行文件安装在  /usr/bin/ld;


另外, /bin 以及 /sbin 目录下的可执行文件一般供用户在shell中输入指令来调用;/usr/libexec/ 目录下的可执行文件,一般不由用户直接调用,而是由某个程序或工具软件调用,辅助前者完成特定任务


自从gcc4.4.7版本开始,官方推荐使用单独的目录,而不是在解压gcc源码后的目录中进行编译,原因在于:

优化以及生成性能更好的二进制可执行文件;

避免不可预期的错误发生;

避免污染源码所在目录


因此,我们需要在文件系统的根目录 /  下建立3个目录,方便编译过程的管理;

还需要在 /usr/local/ 目录下建立用于存放最终生成的新版gcc的目录,并使用

configure脚本的 --prefix=/usr/local/[自定义的路径名称]  来指定,这样,gcc的可执行文件,库文件,头文件就会井然有序分别存放在相应的子目录下,日后不用时直接 rm -rf 整个安装路径就可以了,因为gcc没有 uninstall的功能进行卸载。


下面这张截图展示了新版gcc层次分明的安装目录结构树,真正实现所有组件集中管理,并且各司其职


wKiom1PZqICBk1k5AAz0HRUjVfs151.jpg


相比旧版本的gcc使用 /usr/bin, /usr/lib  /usr/libexec 目录来存放各自的文件,这种集中管理的办法显得更效率和安全,不会错误的卸载或删除到不相关的文件。


上面的一堆废话,用 shell 命令来表达,如下:


[root@centos6-5vm 桌面]# cd /
[root@centos6-5vm /]# mkdir {downloaded-src-dir,extracted-src-dir,compile-dir}
[root@centos6-5vm /]# cd /usr/local
[root@centos6-5vm local]# mkdir new-exec-gcc-4.9.1
[root@centos6-5vm local]# cd new-exec-gcc-4.9.1/
[root@centos6-5vm new-exec-gcc-4.9.1]# pwd
/usr/local/new-exec-gcc-4.9.1


downloaded-src-dir    存放从网上下载的新版gcc源码包,以及其它依赖包的目录

extracted-src-dir     存放解压后的新版gcc源码的目录

compile-dir           单独的用于编译新版gcc源码的目录



所有的前置工作都完成后,接着,我们从GNU的gcc项目的官方 ftp 下载站点:


ftp://gcc.gnu.org/pub/gcc/releases/


来下载最新版的gcc源码包。权威的信息和版本更新说明,安装指南可以从这里获取:

https://gcc.gnu.org/


GNU项目的所有开源软件项目的×××站点(FTP服务器),有最新版的Glibc源码:

http://ftp.gnu.org/



wKiom1PXlviC-zNIABRxoxG7s6k891.jpg


用firefox浏览器或者wget等命令行工具,将gcc4.9.1的源码包下载到上面创建的

downloaded-src-dir  目录下,

注意,一同站点web路径下的md5.sum文件,保存了这两个源码包的md5校验和信息,下载到本地后,运行md5sum,与站点上提供的值进行比对,如果值不一样,则说明下载过程中有错误,需要重新下载,对于体积较大的 gcc-4.9.1.tar.gz 源码包而言(112M),这个检查是必要的。


[root@centos6-5 桌面]# cd /downloaded-src-dir/
[root@centos6-5 桌面]# ls -al
[root@centos6-5 桌面]# md5sum gcc-4.9.1.tar.gz


wKiom1PXnlzCwLafAAZPqWCBKDw722.jpg


把源码包解压到前面创建的 extracted-src-dir 目录下:

[root@centos6-5vm downloaded-src-dir]# pwd
/downloaded-src-dir
[root@centos6-5vm downloaded-src-dir]# tar -zxvf gcc-4.9.1.tar.gz -C /extracted-src-dir/


先别急着编译。

我们知道,要从源码编译安装gcc,需要5个基础的依赖库,为了保证不在configure脚本以及make过程中发生错误而退出,应该预先把这5个库的二进制RPM包安装好,然后在gcc的configure脚本中,添加

--with-[依赖包名称]=[依赖包安装到的绝对路径]  这种形式的参数,例如

--with-mpfr=/usr/local/mpfr-2.4.2

但是,由于要分别安装,指定这5个依赖库,所以重复的工作量大,而且容易发生操作错误,因此,我们可以先下载这5个依赖库的源码包,然后解压到gcc的源码目录下,根据gcc的编译规则,在编译时如果在gcc源码目录检测到这5个依赖库的子目录,那么在make的阶段也会自动编译这5个依赖库,这样,就不需要在

configure脚本中手动指定安装目录,避免遗漏指定或指定错误从而导致make错误退出。

有童鞋可能会问了:

前面我们在安装旧版gcc时,yum解析并安装了其中的2个依赖库的RPM包:cloog的ppl支持和旧版的mpfr RPM包,这里再通过make自动编译安装,难道不会产生冲突?

经过笔者测试,结论是:不会,因为这5个依赖库是编译gcc源码时才需要的,而且我们用单独的 compile-dir 目录来存储中间编译好的文件,就是为了避免这种问题。


ftp://gcc.gnu.org/pub/gcc/infrastructure/

可以找到这5个依赖库的下载链接,需要注意,GNU站点上的这些资源都过于老旧了,虽然它们属于GNU项目,但是在其各自的官方站点上面总是提供当前的最新版本源码包下载。对于编译最新版的gcc而言,当然应该也用这些最新版的依赖包,进而避免

发生相关的兼容性问题,例如“make提示某某依赖包的版本太旧,编译gcc需要最新版的依赖包”等等。


讲了上面一堆废话,这5个依赖库分别是:


 

依赖库               官方站点            最新版/gcc.gnu.org上的版本对比


MPFR        http://www.mpfr.org/         mpfr-3.1.2.tar.gz/bz2  
                                         mpfr-2.4.2.tar.bz2

GMP         https://gmplib.org/          gmp-6.0.0a.tar.bz2 
                                         gmp-4.3.2.tar.bz2 
                                         
MPC        http://www.multiprecision.org/        mpc-1.0.2.tar.gz  
                                                 mpc-0.8.1.tar.gz 
                                                 
CLOOG      http://www.cloog.org/          cloog-0.18.1.tar.gz
                                          cloog-0.18.1.tar.gz 
                                          
                                          
ISL        http://isl.gforge.inria.fr/    isl-0.13.tar.gz
                                          isl-0.12.2.tar.bz2

 

(ISL并非GNU项目,不是编译gcc必需,但是可以优化生成的可执行文件,因此推荐下载,

特别提醒,不要使用ISL官网的0.13.tar.gz版本,这会导致后面的make第一阶段调用gcc编译cloog源码时,错误提示某个C源文件的函数和变量未定义,导致make退出。这个应该属于非稳定版本,有相同症状的童鞋可以向官网回报相关的bug信息,人数多才会引起开发社区的重视)


我们用最新版的依赖库进行测试:用firefox浏览器或者wget等命令行工具,依序访问上面5个官方站点提供的下载链接,下载到本地的 downloaded-src-dir 目录下。



wKiom1PXwvKSjzKBAATNBYXGGbY776.jpg

 

wKioL1PXxSjRcsEbAAT5Lz-kYqA129.jpg


wKioL1PXxwXCkg9mAAsDhEzk7X0050.jpg

                                                                  


wKiom1PXxumg0uxHAAZsnQI9Vwc516.jpg


wKioL1PXzLax69LcAAp7C_Ilspw655.jpg


进入 downloaded-src-dir 目录,将这5个依赖库的源码包,解压到新版gcc源码目录下,这会自动在其下创建带有各自版本号的子目录,但是,由于gcc编译规则只能识别不带版本号的子目录名称,因此,还需要将其重命名。


[root@centos6-5vm /]# cd /downloaded-src-dir/
[root@centos6-5vm downloaded-src-dir]# ls -al
总用量 122656
drwxr-xr-x.  2 root root      4096 7月  29 23:46 .
dr-xr-xr-x. 27 root root      4096 7月  29 23:20 ..
-rw-r--r--.  1 root root   3857324 7月  29 23:44 cloog-0.18.1.tar.gz
-rw-r--r--.  1 root root 115590790 7月  29 23:26 gcc-4.9.1.tar.gz
-rw-r--r--.  1 root root   2319400 7月  29 23:36 gmp-6.0.0a.tar.bz2
-rw-r--r--.  1 root root   1559548 7月  29 23:46 isl-0.13.tar.gz
-rw-r--r--.  1 root root    633173 7月  29 23:39 mpc-1.0.2.tar.gz
-rw-r--r--.  1 root root   1621228 7月  29 23:34 mpfr-3.1.2.tar.gz

[root@centos6-5vm downloaded-src-dir]# tar -zxf cloog-0.18.1.tar.gz -C /extracted-src-dir/gcc-4.9.1/
[root@centos6-5vm downloaded-src-dir]# tar -jxf gmp-6.0.0a.tar.bz2 -C /extracted-src-dir/gcc-4.9.1/
[root@centos6-5vm downloaded-src-dir]# tar -zxf isl-0.13.tar.gz -C /extracted-src-dir/gcc-4.9.1/
[root@centos6-5vm downloaded-src-dir]# tar -zxf mpc-1.0.2.tar.gz -C /extracted-src-dir/gcc-4.9.1/
[root@centos6-5vm downloaded-src-dir]# tar -zxf mpfr-3.1.2.tar.gz -C /extracted-src-dir/gcc-4.9.1/


[root@centos6-5vm downloaded-src-dir]# cd /extracted-src-dir/
[root@centos6-5vm extracted-src-dir]# cd gcc-4.9.1/
[root@centos6-5vm gcc-4.9.1]# pwd
/extracted-src-dir/gcc-4.9.1
[root@centos6-5vm gcc-4.9.1]# mv cloog-0.18.1/ cloog
[root@centos6-5vm gcc-4.9.1]# mv gmp-6.0.0/ gmp
[root@centos6-5vm gcc-4.9.1]# mv isl-0.13/ isl
[root@centos6-5vm gcc-4.9.1]# mv mpc-1.0.2/ mpc
[root@centos6-5vm gcc-4.9.1]# mv mpfr-3.1.2/ mpfr

wKioL1PYR1ySbEpbAAnl9L4jV9s929.jpg



至此,

所有准备工作已就定位,可以正式开始从源码编译安装gcc了,请看第二部分内容的博文。