0%

记一段差点被Gcc逼疯的历程

在Windows下,或是像Ubuntu、Arch这些拥有出色的软件包管理器的Linux发行版下,似乎从来都是不需要怎么考虑如何安装Gcc的问题。几个键就好了。

有一天,需要在没有root权限、然后还不能用包管理器的情况下安装Gcc时,就可能遇上各种奇怪的问题。

我需要在多个Linux服务器集群上测试OpenFOAM这个软件,要用Gcc来编译安装。OpenFOAM要求编译用的Gcc版本要高于4.5.0,而测试用的几个服务器上装的是稳定性比较好的比如CentOS和SUSE这样的系统,尤其CentOS中默认的最高版本Gcc也只有4.4.7。因此需要手动编译安装更高版本的Gcc。

之前在2个服务器上使用OpenFOAM提供的安装脚本装过Gcc,中间虽然也不太顺利,最后还是成功装上了。今天又有在一台新系统上测试的工作需要,上面装的是CentOS 6.7,而且似乎系统上的环境不太完整,折腾了安装脚本快一整天都没把Gcc装上…-_-。

最后让师兄捣鼓了一下,似乎还是有问题,只好决定放弃OpenFOAM提供的脚本,自己手动安装Gcc,成功之后再好好分析一下脚本里面到底有什么问题。

写这篇博客的时候,还连着ssh在服务器上编译中。

依赖问题

Gcc官网的说明文档中详细地介绍了编译Gcc需要的依赖工具、库等等。参考目前常见的Linux系统来看,需要准备的最基本的东西有gcc、mpc、mpfr、
gmp的源码包、一个低版本的Gcc,以及一些其他需要的依赖库例如glibc、zlib等。

通常一些基本的工具,例如flex、bison等等基础编译工具包,应该在大部分的系统环境中都是有的,没有它们Gcc仍然可以编译,但是之后使用Gcc时可能因为缺少它们而产生各种奇怪的错误,不知道编译时是不是会对它们添加一些依赖什么的,最好还是装上。

如果安装时还发现缺了其他什么东西的话,只能一个一个补上了。

在编译或者安装时做好日志记录非常重要,这样一旦发生错误,可以在结束后马上从log文件中查到报错的原因,然后针对错误来进行修复。养成加log的习惯,在运行命令后面加上:

1
$ xxxx 2>&1 | tee log

即可,2>&1是把错误输出跟正常输出导到一起,然后通过tee写入log文件,同时在屏幕上继续输出。

编译安装

Gcc的三大件前面已经提到过了,而它们在安装时也存在依赖关系,mpfr需要依赖gmp,mpc则是依赖gmp和mpfr,因此安装的顺序是gmp,mpfr,最后才是mpc。

这部分的安装一般不会有什么问题,按照顺序编译安装、并且注意指定上一个依赖的位置即可。

  • gmp
1
2
3
4
5
$ tar jxf gmp-5.1.2.tar.bz2
$ cd gmp-5.1.2
$ ./configure --prefix=$HOME/opt/gmp
$ make
$ make install
  • mpfr
1
2
3
4
5
$ tar jxf mpfr-3.1.2.tar.bz2
$ cd mpfr-3.1.2
$ ./configure --prefix=$HOME/opt/mpfr --with-gmp-lib=$HOME/opt/gmp/lib --with-gmp-include=$HOME/opt/gmp/include
$ make
$ make install
  • mpc
1
2
3
4
5
$ tar zxf mpc-1.0.1.tar.gz
$ cd mpc-1.0.1
$ ./configure --prefix=$HOME/opt/mpc --with-gmp-lib=$HOME/opt/gmp/lib --with-gmp-include=$HOME/opt/gmp/include --with-mpfr-lib=$HOME/opt/mpfr/lib --with-mpfr-include=$HOME/opt/mpfr/include
$ make
$ make install

然后需要在LD_LIBRARY_PATH的路径中把gmp、mpfr、mpc的动态库地址加上,虽然下面gcc的configure里面也需要指定3个依赖软件的位置,但是不加的话会出现各种奇怪的错误。

1
$ export LD_LIBRARY_PATH=$HOME/opt/gmp/lib:$HOME/opt/mpfr/lib:$HOME/opt/mpc/lib:$LD_LIBRARY_PATH
  • gcc
1
2
3
4
5
$ tar zxf gcc-4.8.4-tar.gz
$ cd gcc-4.8.4
$ ./configure --prefix=$HOME/opt/gcc --with-gmp=$HOME/opt/gmp --with-mpfr=$HOME/opt/mpfr --with-mpc=$HOME/opt/mpc --enable-languages=c,c++ --disable-multilib --enable-threads=posix --disable-checking
$ make -j4 # Gcc相对比较大,最好采用并行编译,否则会需要很长时间来完成
$ make install

如果没有错误的话,之后将gcc的目录加到环境变量中即可使用。

编译过程中可能报的各种错

最常见的大概是找不到-lz、找不到libc等等,需要根据情况补装zlib和glibc的库。

有时候zlib的64位和32位库都可能会缺,因此都需要补上。

虽然没有root权限无法调用yum来进行快速安装,但是yum库还是可以使用的,比如要找一个zlib的64位库:

1
$ yumdownloader zlib.x86_64

会将yum软件库中的zlib-1.2.3-29.el6.x86_64.rpm包下载到当前目录,然后使用rpm2cpio命令可以将这个包直接解压到当前目录下:

1
$ rpm2cpio zlib-1.2.3-29.el6.x86_64.rpm | cpio -idvm

将解出来的例如lib64、usr/lib64等等目录添加到环境变量中即可。

OpenFOAM中的Gcc安装脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#
# Build GCC
# might need 32-bit glibc-devel headers to compile
# E.g. on ubuntu install g++-multilib
#
echo "---------------"
if [ -d $GCC_ARCH_PATH ]
then
echo "Already built: $gccPACKAGE"
else
echo "Starting build: $gccPACKAGE"
echo
(
sourceDIR=$WM_THIRD_PARTY_DIR/$gccPACKAGE
buildDIR=$buildBASE/$gccPACKAGE

cd $sourceDIR || exit 1
make distclean 2>/dev/null

unset withMpc
[ -d "$MPC_ARCH_PATH" ] && withMpc="--with-mpc=$MPC_ARCH_PATH"

rm -rf $buildDIR
mkdir -p $buildDIR
cd $buildDIR

set -x
$sourceDIR/configure \
--prefix=$GCC_ARCH_PATH \
--with-gmp=$GMP_ARCH_PATH \
--with-mpfr=$MPFR_ARCH_PATH \
$withMpc \
--with-pkgversion=OpenFOAM \
--enable-languages=c,c++ \
--enable-__cxa_atexit \
--enable-libstdcxx-allocator=new \
--with-system-zlib \
MAKEINFO=missing \
&& make -j $WM_NCOMPPROCS \
&& make install \
&& echo "Built: $gccPACKAGE"
) || {
echo "Error building: $gccPACKAGE"
exit 1
}
fi

看上去应该没有什么特别的问题,大概关键就在configure那里的几个我没见过的参数上面吧,下次详细分析一下Gcc安装目录下面的configure文件再补充。