centos6 升级gcc 4.9.2 支持c++11
一、gcc源码安装步骤
1.按网上方式下载了gmp mpfr mpc库指定版本并安装
安装mpfr过程遇到如下问题:
error while loading shared libraries: libgmp.so.10
表示找不到XXX库,通过find找到库所有的目录,添加到环境变量
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/
export LD_LIBRARY_PATH
2.下载 gcc-4.9.2 并安装
2.1 解压后进入解压目录,执行如下命令生成Makefile文件
./configure --prefix=/usr/gcc-4.9.2 --enable-threads=posix --disable-checking --disable-multilib --enable-languages=c,c++
上面的--prefix=/usr/gcc-4.9.2 表示你要将gcc安装到gcc-4.9.2的目录下,其它的选项可以自行去查阅configure了解
2.2 生成Makefile后,执行make -j4编译
make的过程当中遇到错误。网上找了资料说是内存不足free -m,通过增加swap文件分区,问题解决(期间还是出现过一次错误,和增加swap分区前的错误一样,我查看了一下内存,发现swap分区还是有很多剩余。所以不管它,接着make -j4,竟然莫名的好了)。
2.3 make完之后,执行make install安装
二、多个版本编译器之间的切换方法
安装好之后,我们通过gcc -v查看gcc版本,发现还是4.4.7的版本。为了执行编译命令的时候,系统使用4.9.2版本进行编译。需要将系统默认使用的gcc,从4.4.7版本切换到4.9.2版本,切换方法如下
当linux终端在接收到 gcc/g++ 命令时,shell就会到系统默认的/usr/bin目录下去找这两个执行程序(执行shell 命令,实际上是通过shell去调用一个可执行程序的,并且会为每个可执行程序产生一个新进程)。
所以,只需要我们将/usr/bin下的gcc和g++两个4.4.7的可执行程序,通过软链接,重定向到我们新安装的4.9.2版本的可执行程序上就可以了。上面我们通过--prefix选项指定了gcc-4.9.2的安装目录为/usr/gcc-4.9.2(如果忘记了上面选项设置的路径,可以通过find来找一下,这个比较简单,此处不多说),具体操作如下:
cd /usr/bin
mv {gcc,g++} gcc-4.4.7 //先将旧版本的gcc备份起来,以免新版本出错无法使用,备份是一个好习惯
ln -s /usr/gcc-4.9.2/bin/gcc /usr/bin/gcc
ln -s /usr/gcc-4.9.2/bin/g++ /usr/bin/g++
此时,我们再通过gcc -v查看gcc版本,已经是我们新安装的gcc-4.9.2版本了。
安装过程挺久挺烦人的,终于大功告成,聪明的你先happy一下吧。
gcc多个版本之间的切换,都可以使用这个方法,在/usr/bin目录下建立一个软链接指向你想要使用的版本(除了系统默认的gcc版本,因为系统默认的gcc版本,目录结构的组织是/usr/bin/gcc这种形式的,它依赖的一些库在/usr/lib /usr/lib64当中,所以它必须得在/usr/bin目录下,所以通过软链接来使用系统默认的版本,编译链接的时候可能会出现一些找不到xxx库的错误!)。
通过以上的处理,去建立一个简单的程序,我们就可以使用新版本gcc进行编译了,也可以学习c++11了,但是还有一个非常重要的设置。那就是,通过以上设置,在引用一些特定库的时候,编译时还是会存在链接报错的情况。比如我,使用了stl中的list,报了如下错误。
gcc -g .obj/boostthreadexample.o .obj/charBuffer.o .obj/mysqlprogram.o .obj/structureinit.o .obj/xdbc.o -L/alidata/server/mysql-5.6.15/lib -lmysqlclient -L../common/lib -lxdbc -lbase -lboost_thread -o test
../common/lib/libxdbc.a(connpool.o): In function `std::list<xConnection*, std::allocator<xConnection*> >::_M_insert(std::_List_iterator<xConnection*>, xConnection* const&)':
/usr/gcc/include/c++/4.9.2/bits/stl_list.h:1681: undefined reference to `std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)'
collect2: error: ld returned 1 exit status
make: *** [MAINTARGET] Error
错误提示找不到`std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)这个符号,原因是:gcc-4.9.2版本编译链接的时候,还是链接到/usr/lib目录下的旧的库(gcc-4.4.7所依赖的库的路径,而这个库或许做了改动,添加了内容,并且gcc-4.9.2需要使用到这些新内容,在旧的库找不到新增的符号,是很正常的),导致出现找不到符号的错误。我们在编译的时候遇到这类型错误,都可以尝试考虑一下是否是这个原因。在这里,解决这个问题,有两个方法。
1、找到这个符号所在的库,在编译的时候明确使用它,这种方案有两个缺点,我们要找到符号所在的库文件不容易,特别是一些不常见的符号;二是,以后还可能会遇到另外的符号找不到的,又需要去找库,在编译的时候指定。
2、仔细想想,既然gcc-4.9.2使用到了这个符号,那么它在安装的时候,是不是会连带着将这个新的库也安装了呢,非常有可能,赶紧去尝试一把,将gcc-4.9.2的lib目录,添加到LD_LIBRARY_PATH环境变量,顺便说下LD_LIBRARY_PATH环境变量的作用:编译器查找库的顺序,是先到LD_LIBRARY_PATH环境变量指定的目录下去找,找不到之后再到系统默认目录(通过PATH环境变量指定)去找,也就是说,即使我们在系统默认的目录下和我们通过LD_LIBRARY_PATH指定的目录下,存在同名的库,链接的时候是使用LD_LIBRARY_PATH指定目录下的库而非系统默认目录的库,想要了解更多编译器查询库的顺序,可以自行去百度。
此处使用第二种方法,操作如下
在 .bash_profile文件(设置环境变量的文件,CentOS版的linux发布,其它版本的发布,名字或许不太一样)中加入以下内容,注意将gcc-4.9.2替换成你自己安装gcc-4.9.2版本的目录。
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/gcc-4.9.2/lib:/usr/gcc-4.9.2/lib64
export LD_LIBRARY_PATH
这个方法通常可以用来解决编译时库的兼容性问题
保存并重启终端,make,编译成功。