在使用tensorflow的时候,经常会遇到这个:

 /usr/lib64/libstdc++.so.6: version `glibcxx_3.4.17' not found 、ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found ...

归根结底这类问题:由于Linux内核不支持,gcc版本太低!!!!

查看系统、gcc版本:centos6.4 64位、gcc4.4.7

cat /etc/redhat-release
CentOS release 6.4 (Final)

uname -a
。。。。。.el6.x86_64

$ g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

GCC 4.4.7 不支持 C++11,在升级gcc的时候使用yum是无效的,只能下载源码、编译。

$ yum update gcc
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
Setting up Update Process
No Packages marked for Update

1、下载、解压:

cd /usr/local
wget ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.8.5/gcc-4.8.5.tar.bz2

tar jxvf gcc-4.8.5.tar.bz2 -C /usr/local/src

在这里我们直接通过官方下载gcc-4.8.5.tar.bz2(83 MB)。当然,你也可以下载gcc-4.8.5.tar.gz(106 MB),不过该压缩文件要大出不少。官方的下载地址为:ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.8.5/ 直接在浏览器中打开即可。如果需要按照其他的版本,打开上一级目录 ftp://gcc.gnu.org/pub/gcc/releases/,选择对应版本下载即可。

2、编译前准备工作:

想要安装gcc 4.8及以上版本,你需要先安装C标准库和头文件,以及旧版本的c++编译器。如果你的计算机中没有这些,请执行以下命令(当然你也可以使用apt-get等其它方式进行安装,如果已经安装则无需再次安装):

#安装C和C++的静态库
yum install -y glibc-static libstdc++-static
#安装旧版本的gcc、c++编译器
yum install gcc gcc-c++

3、下载一些必要依赖

#转到gcc源程序根目录
cd /usr/local/src/gcc-4.8.5
#下载一些必备的依赖程序
./contrib/download_prerequisites

安装gcc需要下载诸如gmp、mpfr、mpc等依赖文件,执行download_prerequisites将会自动下载这些软件并解压到当前目录(文件不大,总共只有几MB,请耐心等待下载)。如果网络不OK时,可打开 ./contrib/download_prerequisites 文件按照文件中的内容下载对应版本的依赖程序,并解压到/usr/local/src/gcc-4.8.5目录,同时创建对应的软连接,gcc-4.8.5的download_prerequisites如下:

MPFR=mpfr-2.4.2
GMP=gmp-4.3.2
MPC=mpc-0.8.1

wget ftp://gcc.gnu.org/pub/gcc/infrastructure/$MPFR.tar.bz2 || exit 1
tar xjf $MPFR.tar.bz2 || exit 1
ln -sf $MPFR mpfr || exit 1

wget ftp://gcc.gnu.org/pub/gcc/infrastructure/$GMP.tar.bz2 || exit 1
tar xjf $GMP.tar.bz2 || exit 1
ln -sf $GMP gmp || exit 1

wget ftp://gcc.gnu.org/pub/gcc/infrastructure/$MPC.tar.gz || exit 1
tar xzf $MPC.tar.gz || exit 1
ln -sf $MPC mpc || exit 1

rm $MPFR.tar.bz2 $GMP.tar.bz2 $MPC.tar.gz || exit 1

所以需要下载三个依赖程序:mpfr、gmp和mpc,在 ftp://gcc.gnu.org/pub/gcc/infrastructure/ 目录下依次找到对应的三个文件,并下载后放在/usr/local/src/gcc-4.8.5目录下,每个依赖库的目录使用ln -sf做成软连接即可。

4、编译安装gcc:

接着,就可以对gcc进行编译安装了。在此之前,我们先创建一个目录 mkdir /usr/local/build/gcc-4.8.5(你也可以自行指定其他目录)用于存放编译后的程序文件。然后我们依次执行如下命令:

#跳转到编译后的程序文件存放目录
cd /usr/local/build/gcc-4.8.5
#调用gcc源程序的configure(后面的参数选项可根据需要自行修改),用于配置gcc
/usr/local/src/gcc-4.8.5/configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
#编译gcc源程序
make
#安装gcc
make install

其中执行make命令这一过程耗费的时间可能非常多,笔者这里耗费了2个多钟头才编译完成。执行完上述命令后,我们的gcc就已经安装成功了。

GCC 和G++均安装在/usr/local/bin/ 和 /usr/local/lib 目录下,如果需要自己指定安装目录,在configure后面指定参数 --prefix=/your/path 即可。

5、解决GLIBC版本未更新问题:

编译或者运行时,会出现GLIBC版本找不到的问题,如下提示:

/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found

主要是因为升级时,生成的动态库没有替换老版本gcc的动态库导致的,将gcc最新版本的动态库替换系统中老版本的动态库即可解决。运行以下命令检查动态库:

# strings /usr/lib64/libstdc++.so.6 | grep GLIBC

GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBC_2.2.5
GLIBC_2.3
GLIBC_2.4
GLIBC_2.3.2
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH

从以上输出可以看出,gcc的动态库还是旧版本的。说明出现这些问题,是因为升级gcc时,生成的动态库没有替换老版本gcc的动态库。按道理说安装的时候会自动更新动态库,我们可以在根目录手动搜索一下:

# find / -name libstdc++.so.6*  
/usr/lib/libstdc++.so.6.0.13
/usr/lib/libstdc++.so.6
/usr/local/lib64/libstdc++.so.6.0.19-gdb.py
/usr/local/lib64/libstdc++.so.6
/usr/local/lib64/libstdc++.so.6.0.19
/usr/local/build/gcc-4.8.5/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
/usr/local/build/gcc-4.8.5/x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.19
/usr/local/build/gcc-4.8.5/stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
/usr/local/build/gcc-4.8.5/stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.19
/usr/local/build/gcc-4.8.5/prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6
/usr/local/build/gcc-4.8.5/prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.19
/usr/lib64/libstdc++.so.6.0.13
/usr/lib64/libstdc++.so.6

我们发现,gcc安装时把libstdc++.so.6.0.19 安装到了/usr/local/lib64下,但并没有改变/usr/lib64/libstdc++.so.6的链接指向。那么我们将/usr/local/lib64/libstdc++.so.6.0.19手动拷贝到/usr/lib64/,并更新libstdc++.so.6软连接(也可以直接指向/usr/local/lib64/libstdc++.so.6.0.19,不用拷贝, 看各自的文件管理习惯),其中/usr/local/build/gcc-4.8.5/目录下的库文件为都是编译输出文件,stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.19为gcc新版本编译最终生成的lib库文件,和/usr/local/lib64/libstdc++.so.6.0.19是一模一样的。更新lib库的操作命令如下:

cp /usr/local/lib64/libstdc++.so.6.0.19 /usr/lib64 
rm -rf /usr/lib64/libstdc++.so.6
ln -s /usr/lib64/libstdc++.so.6.0.19 /usr/lib64/libstdc++.so.6

注:libc.so.6只是一个软连,删除后可能会导致ls等命令都无法正常使用。这时不要慌张,可以通过LD_PRELOAD环境变量来解决。参考:​​http://devzc.com/post/440​​  例如:

//ls命令
$ LD_PRELOAD=/lib64/libc-2.17.so ls


//重新添加软连
$ LD_PRELOAD=/lib64/libc-2.17.so ln -s /lib64/libc-2.17.so /lib64/libc.so.6

再次检查动态库:

strings /usr/lib64/libstdc++.so.6 | grep GLIBC
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBC_2.3
GLIBC_2.2.5
GLIBC_2.3.2
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH

库更新完毕。我们已经支持到了GLIBCXX_3.4.14-19,此时再进行编译,GLIBCXX的问题是没有了。