GCC(GNU Compiler Collection,GNU编译器合集)是linux以及其余类UNIX平台上进行开源项目,软件开发等必不可少的工具链组成之一。(其余的还有clang以及llvm等编译器)linux
对于程序员以及系统管理员而言,常常须要从软件的源码进行手动编译安装,c++
不管是configure脚本,仍是make工具,最终都须要调用gcc(或者其它编译器)来进行实际的编译工做。程序员
另外,各类软件也常常须要使用gcc的新版特性,而且与旧版gcc共存,根据实际的需求进行调用。bootstrap
实验环境:VMware Workstation Pro 14(试用版) 系统平台: CentOS release 6.9 (Final) 内核 2.6.32-696.el6.x86_64 软件包:minimal最小化安装
glibcvim
GNU C Library https://www.gnu.org/ GNU C库项目提供了 GNU系统和GNU / Linux系统的核心库,以及许多其余使用Linux做为内核的系统。glibc是Linux系统中最底层的API,几乎其它任何的运行库都要依赖glibc。这些库提供了关键的API, 包括ISO C11,POSIX.1-2008,BSD,操做系统特定的API等等。这些API包括open, read,write,malloc,printf, getaddrinfo,dlopen,pthread_create, crypt,login,exit等基础设施。 GNU C库被设计成一个向后兼容、便携、高性能的ISO C库。它旨在遵循全部相关标准,包括ISO C11,POSIX.1-2008和IEEE 754-2008。 该项目始于1988年,已有近30年的历史。 没有这个软件包,Linux系统将不能正常工做。 默认最小化安装已经随系统安装好 #ldd --version ldd (GNU libc) 2.12 #rpm -qa|grep glibc glibc-common-2.12-1.209.el6.x86_64 glibc-2.12-1.209.el6.x86_64 glibc-headers-2.12-1.209.el6.x86_64 glibc-devel-2.12-1.209.el6.x86_64
Glibc是非交叉编译环境下,从源码编译安装gcc必备的。centos
若是是交叉编译的环境,即在一种硬件架构/操做系统上编译(宿主机),可是生成的二进制可执行文件要在另外一种硬件架构/操做系统上运行(目标机),架构
在这种状况下,不能依赖宿主机器上已编译的C库,最好是自行下载glibc的源码并编译。app
glibc-static编辑器
GNU C标准库的静态版,只有在用于 -static 静态连接时才须要, glibc-static是非交叉编译环境下,从源码编译安装gcc必备的,并且它依赖于Glibc(要先装Glibc) 默认最小化安装并不会预装glibc-static
libstdc++ide
兼容GCC的C++标准库 libc++是针对clang编译器特别重写的C++标准库,那libstdc++天然就是gcc的事儿了。libstdc++与gcc的关系就像clang与libc++。 默认最小化安装已经随系统安装好 #rpm -qa|grep libstdc++ libstdc++-4.4.7-18.el6.x86_64 libstdc++-devel-4.4.7-18.el6.x86_64 #rpm -ql libstdc++-4.4.7-18.el6.x86_64 /usr/lib64/libstdc++.so.6 /usr/lib64/libstdc++.so.6.0.13
gcc
由于它本来只能处理C语言。GCC在发布后很快地获得扩展,变得可处理C++。以后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,Go与其余语言。 许多操做系统,包括许多类Unix系统,如Linux及BSD家族都采用GCC做为标准编译器。 默认最小化安装并不会预装gcc 从源码编译安装新版gcc前,要求系统上已经安装有旧版gcc
gcc-c++
GNU编译器合集的c++加强支持包,它向gcc的c++编译器提供了更多对当前c++标准规范的支持,包含模板和错误处理。 默认最小化安装并不会预装gcc-c++ gcc-c++ 还须要额外的 libstdc++ 支持
为了能顺利的yum安装,从新配置了光盘和aliyun的yum源
请自行参考 https://mirrors.aliyun.com/help/centos
所以,编译安装新版本的gcc组件,须要准备如下3个软件包
gcc gcc-c++ glibc-static
#yum install gcc gcc-c++ glibc-static
会自动解决依赖关系
验证这3个软件包的状态
#rpm -qa|grep gcc;rpm -qa|grep glibc-static libgcc-4.4.7-18.el6.x86_64 gcc-4.4.7-18.el6.x86_64 gcc-c++-4.4.7-18.el6.x86_64 glibc-static-2.12-1.209.el6_9.2.x86_64 #which gcc;which g++ /usr/bin/gcc /usr/bin/g++ #rpm -ql glibc-static /usr/lib64/libBrokenLocale.a /usr/lib64/libanl.a /usr/lib64/libc.a /usr/lib64/libc_stubs.a /usr/lib64/libcrypt.a /usr/lib64/libdl.a /usr/lib64/libm.a /usr/lib64/libnsl.a /usr/lib64/libpthread.a /usr/lib64/libresolv.a /usr/lib64/librt.a /usr/lib64/libutil.a
编译器( cc1 )预连接器( collect2 )连接器 ( ld ) 汇编器 ( as )
cc1负责对源文件实际的编译工做;
collect2进行预连接处理,实际的连接由连接器ld完成;
安装到如下路径
#ls /usr/libexec/gcc/x86_64-redhat-linux/4.4.7 cc1 cc1plus collect2 #which ld /usr/bin/ld
头文件在如下目录
#ls /usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/ abmintrin.h bmmintrin.h f16cintrin.h iso646.h mmintrin.h pmmintrin.h stdbool.h tbmintrin.h wmmintrin.h ammintrin.h cpuid.h float.h limits.h mm_malloc.h popcntintrin.h stddef.h tmmintrin.h x86intrin.h avxintrin.h cross-stdarg.h fma4intrin.h lwpintrin.h nmmintrin.h smmintrin.h stdfix.h unwind.h xmmintrin.h bmiintrin.h emmintrin.h immintrin.h mm3dnow.h omp.h stdarg.h syslimits.h varargs.h xopintrin.h
gcc4.4.7版本开始,官方推荐使用单独的目录,而不是在解压gcc源码后的目录中进行编译,
缘由在于:
优化以及生成性能更好的二进制可执行文件;
避免不可预期的错误发生;
避免污染源码所在目录;
所以,咱们须要在文件系统的指定目录下创建1个用于编译的目录
并使用configure脚本的 --prefix=/usr/local/[自定义的路径名称] 来指定安装目录,这样,gcc的可执行文件,库文件,头文件就会井井有理分别存放在相应的子目录下,
之后不用时直接 rm -rf 整个安装路径就能够了。这就是编译安装的好处,你清晰的知道全部产生的文件来自哪里。
如下操做如无特殊说明 ,所有在/app/sdb目录操做。 #mkdir gcc-build
CentOS 7 使用4.8.5,通常状况下这个版本的编译器已经知足须要了。
考虑到与Centos 7的兼容性,这里选择了gcc 4.8.5
去官网下载gcc4.8.5源码包
ftp://gcc.gnu.org/pub/gcc/releases
对应版本的目录下会有md5.sum等校验信息文件,下载到本地后,运行md5sum进行比对,若是值不同,则说明下载过程当中有错误,须要从新下载。 #md5sum gcc-4.8.5.tar.gz bfe56e74d31d25009c8fb55fd3ca7e01 gcc-4.8.5.tar.gz
编译安装 GCC 须要依赖 cloog gmp mpc mpfr isl
其中 isl 并非编译gcc必需,可是能够优化生成的可执行文件,所以推荐下载。
特别提醒:
不一样版本软件的相互组合,可能并不会预期的正常编译,致使后面的make第一阶段make退出。下面是我测试了几种组合获得的结果,尽量的使用了高版本。
联合编译时间较长,但愿这表能帮助你节约时间。
GNU软件均可以到如下网址下载,isl不是GNU项目,只能到官方网下载 https://ftp.gnu.org/ mpfr https://ftp.gnu.org/gnu/mpfr/ gmp https://gmplib.org/ mpc http://www.multiprecision.org/mpc/ cloog http://www.cloog.org/ isl http://isl.gforge.inria.fr/
所有下载好了 #tree . ├── gcc-build └── src ├── cloog-0.18.4.tar.gz ├── gcc-4.8.5.tar.gz ├── gmp-6.1.2.tar.xz ├── isl-0.14.tar.gz ├── mpc-1.0.3.tar.gz └── mpfr-3.1.4.tar.gz
#tar xvf src/gcc-4.8.5.tar.gz -C /app/sdb/
将这5个依赖库的源码包,解压到gcc源码目录下,因为gcc编译规则只能识别不带版本号的子目录名称,
所以,还须要将其重命名。这样在gcc编译的时候,会自动编译相关的组件
#tar xvf src/cloog-0.18.4.tar.gz -C gcc-4.8.5/ #tar xvf src/gmp-6.1.2.tar.xz -C gcc-4.8.5/ #tar xvf src/isl-0.14.tar.gz -C gcc-4.8.5/ #tar xvf src/mpc-1.0.3.tar.gz -C gcc-4.8.5/ #tar xvf src/mpfr-3.1.4.tar.bz2 -C gcc-4.8.5/ #mv gcc-4.8.5/cloog-0.18.4 gcc-4.8.5/cloog #mv gcc-4.8.5/gmp-6.1.2/ gcc-4.8.5/gmp #mv gcc-4.8.5/isl-0.14/ gcc-4.8.5/isl #mv gcc-4.8.5/mpc-1.0.3/ gcc-4.8.5/mpc #mv gcc-4.8.5/mpfr-3.1.4/ gcc-4.8.5/mpfr 完成以后,目录结构应该是相似如下的: gcc-4.8.5/ ├── cloog ├── gmp ├── isl ├── mpc ├── mpfr
因为以前使用yum安装gcc旧版本编译器的时候,安装了一些与编译依赖包相同的包,会不会产生冲突?
结论是:不会,由于这5个依赖库是编译gcc源码时才须要的,并且使用单独的编译目录来存储中间编译好的文件,就是为了不这种问题。
固然,还有更简单的方法,运行源码包中的contrib/download_prerequisites这个脚本,会自动下载相应的依赖包。能够查看这个脚本内容。通常来讲,较新的源码包会下载较新的依赖包。
不过,下载速度真的是慢,建议自行下载吧。
至此,准备工做就绪。
--prefix=/usr/local/gcc-4.8.5 新版本最终安装的目录 --with-pkgversion=version 指定一个标识你的包的字符串。您可能但愿包含内部版本号或生成日期。这个版本的字符串将被包含在输出中gcc --version。这个后缀不会替换默认的版本字符串,只会替代'GCC'部分。 默认值是'GCC”。 --enable-bootstrap 也就是进行冗余的编译检查工做。非交叉编译环境下,默认已经将该值设为 enable,能够不用显式指定;交叉编译环境下,须要显式将其值设为 disable。 --enable-checking=release 以软件发布版的标准来对编译时生成的代码进行一致性检查;设置该选项为enable并不会改变编译器生成的二进制结果, 可是会致使编译的时间增长;该选项仅支持gcc编译器; 整体而言,对于上面这个选项,机器的硬件配置较低,以及不肯等待过久编译时间的童鞋,能够设置为 disable;可是这会增长产生未预期的错误的风险,因此应该慎用。 能够同时设置 --disable-bootstrap 与 --disable-checking,这对编译过程的提速颇有帮助。 --enable-languages=c,c++ 目前,可使用任何以下: all,default,ada,c,c++,fortran,go,jit,lto,objc,obj-c++。若是 all被指定,则全部可用的语言都被创建。 jit语言是一个例外 的语言。这里按需只开启了c和c++,由于支持的语言越多,就须要安装越多的相应静态与动态库,还有五花八门的依赖库,这会让管理变得困难,体积也会变得庞大。 --disable-multilib 生成多个平台的代码,好比:64bit机器,同时能够产生32和64两种格式;若是你的操做系统是64位,默认就已经设置为 enable,这意味着用gcc编译其它源文件时能够经过 -m32 选项来决定是否生成32位机器代码。若是在64位系统上,要禁止生成32位代码, 设置 --disable-multilib。 --enable-gather-detailed-mem-stats 容许收集详细的内存使用信息,若是设置该参数为 enable,则未来编译好的gcc可执行程序,能够经过 -fmem-report 选项来输出编译其它程序时的实时内存使用状况。 --with-long-double-128 指定long double类型的默认值是128位。若是使用--without-long-double-128, long double将默认64位,与double类型相同。 若是使用GNU C Library 2.4或更高版本,则默认为128位。
#cd gcc-build/ #/app/sdb/gcc-4.8.5/configure --prefix=/usr/local/gcc-4.8.5 --enable-checking=release --enable-bootstrap --enable-languages=c,c++ --disable-multilib --enable-gather-detailed-mem-stats --with-long-double-128 会在gcc-build目录生成如下4个文件 #ls config.log config.status Makefile serdep.tmp
使用vim等编辑工具打开config.log,查找error关键字,搜索configure检测到的潜在配置错误和警告,这对后面的make阶段可否正常编译相当重要,所以要谨慎对待。若是没有任何与error相关的警告信息,那么就认为能够执行 make 命令。
conftest.cpp:11:2: error: #error -static-libstdc++ not implemented 忽略它也能正常编译,未能找到解决的方法。
若是须要从新configure或make中途出错退出,最好把当前目录下的全部东西都删除干净。
也能够执行下面指令清空 编译目录下的相关文件,包括makefile
# make distclean
make命令中的-j 指定同时开启的进程数,要充分发挥多核处理器的并行执行优点,这个值应该是处理器芯片上物理核心的2倍。CPU给不给力就看这个了。
#lscpu |grep -A 1 'Model name' Model name: Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz Stepping: 4
这条指令重点是make -j 8 ,先后加的date指令是为了统计编译时间的。 #date +%F-%T >> /app/time.txt && make -j 8 && date +%F-%T >> /app/time.txt
若是看到如下相似字样,恭喜你,编译经过了。 make[4]: Leaving directory `/app/sdb/gcc-build/x86_64-unknown-linux-gnu/libmudflap' make[3]: Leaving directory `/app/sdb/gcc-build/x86_64-unknown-linux-gnu/libmudflap' make[2]: Leaving directory `/app/sdb/gcc-build/x86_64-unknown-linux-gnu/libmudflap' make[1]: Leaving directory `/app/sdb/gcc-build'
最终整个编译目录占用了2.7GB空间,消耗的时间在40~50分钟内
# make install
根据编译前的设定,在指定目录生成了对应的gcc文件夹
#ls /usr/local/gcc-4.8.5/ bin include lib lib64 libexec share
查验版本
#/usr/local/gcc-4.8.5/bin/gcc -dumpversion 4.8.5 #/usr/local/gcc-4.8.5/bin/g++ -dumpversion 4.8.5 #/usr/local/gcc-4.8.5/bin/c++ -dumpversion 4.8.5
须要将新版gcc的库文件安装路径,添加到“库的搜索路径”(LD_LIBRARY_PATH)这个环境变量中,前面在make install结束时,系统也给出了相似的提示信息(参考前面的截图):
临时生效:
#export LD_LIBRARY_PATH="/usr/local/gcc-4.8.5/lib64:$LD_LIBRARY_PATH"
永久生效:
不建议直接修改ld.so.conf,推荐的作法是在ld.so.conf.d目录下按程序名创建以.conf结尾的文件,把库路径写入便可。 #echo '/usr/local/gcc-4.8.5/lib64' > /etc/ld.so.conf.d/gcc4.8.5.conf #ldconfig 更新加载动态库cache 出现如下提示,把这个文件删除了或忽略它 ldconfig: /usr/local/gcc-4.8.5/lib64/libstdc++.so.6.0.19-gdb.py is not an ELF file - it has the wrong magic bytes at the start. 在我实际使用中,到这一步都已经能够正常编译安装mariadb 10.2.12了。并不须要添加新gcc的环境变量。
#vim /etc/profile.d/env.sh PATH=/usr/local/gcc-4.8.5/bin:$PATH #source /etc/profile.d/env.sh
到这里,系统会优先根据PATH路径的前后顺序直接加载使用最新版本的gcc工具。已经能够正常工做了。能够查看后面的测试章节。
若是是须要gcc多版本共存的状况,请直接跳至下面的 多版本gcc共存 开始阅读。
make这种自动编译大型项目的工具只会使用cc做为编辑器,而cc则是指向旧的gcc程序,
#make -p|grep "CC =" CC = cc #ll /usr/bin/cc lrwxrwxrwx. 1 root root 3 Jan 27 10:07 /usr/bin/cc -> gcc
如下是网上说的更新某个动态库,我并无这么作,也能正常的把mariadb 10.2.12编译成功。留着备用吧。
这里的操做未执行: #strings /usr/lib64/libstdc++.so.6 | grep GLIBC 看最后一个,这个与libstdc++.so.6.0.13的尾号是相对应的 GLIBCXX_3.4.13 #ln -sf /usr/local/gcc-4.8.5/lib64/libstdc++.so.6.0.19 /usr/lib64/libstdc++.so.6
至此,前面生成的一些编译目录和源码相关文件均可以按你的须要进行清理了。
有时候因为各类缘由须要将不一样版本的gcc编译器都同时存在系统中,方便进行调用。若是只是开发单独在编译的时候须要的话,仅仅将对应版本路径直接执行就能够了,我的单独配置LD_LIBRARY_PATH。
当是以系统级别总体切换的时候,那就须要用到一个小工具了。
alternatives是dpkg的实用工具,用来维护系统命令的符号连接,以决定系统默认使用什么命令。
使用此工具管理命令时,必需要配置环境变量的PATH路径。如:/usr/local/gcc-4.8.5/bin
alternatives [options] --install link name path priority [--slave link name path]... [--initscript service] alternatives [options] --remove name path alternatives [options] --set name path alternatives [options] --auto name alternatives [options] --display name alternatives [options] --config name 具体用法,请man #ll /usr/sbin/update-alternatives lrwxrwxrwx. 1 root root 12 Dec 13 20:15 /usr/sbin/update-alternatives -> alternatives
语法说明:
#gcc -v gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
#mv /usr/bin/gcc /usr/bin/gcc-4.4.7 #mv /usr/bin/g++ /usr/bin/g++-4.4.7 #mv /usr/bin/c++ /usr/bin/c++-4.4.7
#alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.4.7 50 #alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.4.7 50 #alternatives --install /usr/bin/c++ c++ /usr/bin/c++-4.4.7 50
#alternatives --install /usr/bin/gcc gcc /usr/local/gcc-4.8.5/bin/gcc 60 #alternatives --install /usr/bin/g++ g++ /usr/local/gcc-4.8.5/bin/g++ 60 #alternatives --install /usr/bin/c++ c++ /usr/local/gcc-4.8.5/bin/c++ 60
#alternatives --display gcc #gcc就是上面定义的名称 gcc - status is auto. #当前使用的模式 link currently points to /usr/local/gcc-4.8.5/bin/gcc #当前使用的连接 /usr/bin/gcc-4.4.7 - priority 50 #版本1的连接 /usr/local/gcc-4.8.5/bin/gcc - priority 60 #版本2的连接 Current `best' version is /usr/local/gcc-4.8.5/bin/gcc. #优先级高的选项
自动切换配合--auto动做,并设置好优先级数字,数字越大,优先级越高。手动方式切换后,将会取消自动切换。
从手动切换回自动,alternatives --auto gcc
#alternatives --config gcc There are 2 programs which provide 'gcc'. Selection Command ----------------------------------------------- *+ 1 /usr/bin/gcc-4.4.7 2 /usr/local/gcc-4.8.5/bin/gcc Enter to keep the current selection[+], or type selection number: 2 --- #alternatives --config g++ There are 2 programs which provide 'g++'. Selection Command ----------------------------------------------- *+ 1 /usr/bin/g++-4.4.7 2 /usr/local/gcc-4.8.5/bin/g++ Enter to keep the current selection[+], or type selection number: 2 --- #alternatives --config c++ There are 2 programs which provide 'c++'. Selection Command ----------------------------------------------- *+ 1 /usr/bin/c++-4.4.7 2 /usr/local/gcc-4.8.5/bin/c++ Enter to keep the current selection[+], or type selection number: 2
#gcc -dumpversion 4.8.5 #g++ -dumpversion 4.8.5 #c++ -dumpversion 4.8.5
这是使用系统旧版本4.4.7 gcc编译cmake时的提示,而且报错退出。
#../cmake-3.10.2/configure --prefix=/usr/local/cmake-3.10.2 --------------------------------------------- CMake 3.10.2, Copyright 2000-2017 Kitware, Inc. and Contributors Found GNU toolchain C compiler on this system is: gcc --------------------------------------------- Error when bootstrapping CMake: Cannot find a C++ compiler supporting C++11 on this system. Please specify one using environment variable CXX. See cmake_bootstrap.log for compilers attempted.
这是使用新版本4.8.5 gcc编译cmake时的提示,已经没有报错了
#../cmake-3.10.2/configure --prefix=/usr/local/cmake-3.10.2 --------------------------------------------- CMake 3.10.2, Copyright 2000-2017 Kitware, Inc. and Contributors Found GNU toolchain C compiler on this system is: gcc C++ compiler on this system is: g++ -std=gnu++1y Makefile processor on this system is: gmake g++ has setenv g++ has unsetenv g++ does not have environ in stdlib.h g++ has stl wstring g++ has <ext/stdio_filebuf.h>
编译MariaDB 10.2.12,由于这个版本明确指名须要使用gcc 的 c++11特性 能够明确的看到版本号而且调用成功 -- Running cmake version 3.10.2 -- The C compiler identification is GNU 4.8.5 -- The CXX compiler identification is GNU 4.8.5 -- Check for working C compiler: /usr/bin/gcc -- Check for working C compiler: /usr/bin/gcc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Looking for SHM_HUGETLB -- Looking for SHM_HUGETLB - found -- MariaDB 10.2.12