24 July 2012

215. Compiling gcc 4.7.1/gfortran 4.7.1 on Centos 5.6/ROCKS 4.5.3 (and gmp, mpfr, mpc, binutils (ld,as), glibc, libunistring, libtools...)

Update June 2013:
See flakrat's post for a working example: http://flakrat.blogspot.com.au/2013/06/building-gcc-481-on-centos-59.html

I haven't updated this post for a long time, and I haven't been using the GCC I compiled this way. See flakrat's post for an up-to-date working version.

Update(s): This is the first time I compile the GCC and because of this I will like be going back, updating this document over the coming days. Make sure to 1) check back in a week and 2) hit refresh.

Updated (given in Melb./Au time zone): 24/7, 25/7

The reason for this post is the outdated version (4.1) of gcc on our ROCKS 5.4.3/CentOS 5.6 cluster.

I looked at installing GCC 4.4.6 using rpm packages I found online, but I'm not used to the Red Hat way of doing things, and e.g. openmpi-devel was requiring a version of libgomp I wanted to update. Ultimately I got scared of messing up a production cluster and decided that compiling, while slower, is a whole lot safer -- especially if you're not comfortable with the local package manager.

So, here's the alternative route of compiling your own.

I'm really not a friend of CentOS or ROCKS. On the other hand, I freely admit that this is probably in large part due to not being used to it. But...during the course of this compilation my feelings have gone from mild annoyance to active, fiery hate. Mostly it has to do with how old everything is, and the difficult in updating anything in ROCKS.

This is probably my most massive compilation, owing to the number of packages I ended up compiling (a lot of these are probably optional). Guile in particular is very, very demanding.

The order in which things are done is not random

1. Look at 

2. Download and untar all the sources
NOTE: you should, if possible, select mirrors based on where you are. However, sometimes you're stuck in a shell and just need to get those files downloaded.

mkdir ~/tmp/gcc
cd ~/tmp/gcc
wget http://www.netgull.com/gcc/releases/gcc-4.7.1/gcc-4.7.1.tar.gz
wget http://www.mpfr.org/mpfr-current/mpfr-3.1.1.tar.gz
wget ftp://ftp.gmplib.org/pub/gmp-5.0.5/gmp-5.0.5.tar.bz2
wget http://www.multiprecision.org/mpc/download/mpc-1.0.tar.gz

tar xvf gcc-4.7.1.tar.gz
tar xvf gmp-5.0.5.tar.bz2
tar xvf mpfr-3.1.1.tar.gz
tar xvf mpc-1.0.tar.gz

That was the easy bit.

I've also set up a directory called /share/apps/tools/gcc/ with proper permissions already (i.e. whoever is doing the compiling should have write access)

3. Build gmp
cd gmp-5.0.5/
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/gmp --program-suffix=-gcc47
make install
make check

4. Build mpfr
cd ../../mpfr-3.1.1/
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/mpfr --program-suffix=-gcc-4.7 --with-gmp=/share/apps/tools/gcc/gmp
make install

Libraries have been installed in:

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.

make check

It looks like your compile is starting from scratch, but then it ends with:

All 160 tests passed
(1 test was not run)

5. Build mpc
cd ../../mpc-1.0/
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/mpc --program-suffix=-gcc-4.7 --with-gmp=/share/apps/tools/gcc/gmp --with-mpfr=/share/apps/tools/gcc/mpfr
make install
make check

All 64 tests passed

6. Binutils
'Often' (judging from forum postings...) you can use an older version of the binutils (ld, as) with a newer version of GCC. However, I need crt1.o when compilicing, it's part of glibc, and glibc requires newer versions of ld and as. So, here we go.
wget http://ftp.gnu.org/gnu/binutils/binutils-2.22.tar.gz
tar xvf binutils-2.22.tar.gz
cd binutils-2.22/
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/binutils --program-suffix=-gcc-4.7
make install
make check

At some point I did:
cd /share/apps/tools/gcc/binutils/bin
ln -s ld-gcc-4.7 ld
ln -s as-gcc-4.7 as
ln -s ar-gcc-4.7 ar
but I don't think it's essential

7. Build gcc
cd ~/tmp/gcc-4.7.1
mkdir build
cd build/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/share/apps/tools/gcc/gmp/lib:/share/apps/tools/gcc/mpc/lib:/share/apps/tools/gcc/mpfr/lib
.././configure --prefix=/share/apps/tools/gcc/gcc47 --program-suffix=-gcc-4.7 --with-gmp=/share/apps/tools/gcc/gmp --with-mpfr=/share/apps/tools/gcc/mpfr --with-mpc=/share/apps/tools/gcc/mpc LD_FOR_TARGET=ld-gcc-4.7 AS_FOR_TARGET=as-gcc-4.7 --with-ld=/share/apps/tools/gcc/binutils/bin/ld-gcc-4.7 --with-as=/share/apps/tools/gcc/binutils/bin/as-gcc-4.7 --with-ar=/share/apps/tools/gcc/binutils/bin/ar-gcc-4.7 AR_FOR_TARGET=ar-gcc-4.7


This takes A LONG TIME.

make install

To do 'make check' you need to have done the compilations of the optional packages (autogen and dependencies) below.
make check

You now have a shiny new compiler.

Using it is another matter. I'm working on that post at the moment...
You may find the following informative:

gcc-gcc-4.7 --print-search-dirs

install: /share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/

programs: =/share/apps/tools/gcc/gcc47/libexec/gcc/x86_64-unknown-linux-gnu/4.7.1/:/share/apps/tools/gcc/gcc47/libexec/gcc/x86_64-unknown-linux-gnu/4.7.1/:/share/apps/tools/gcc/gcc47/libexec/gcc/x86_64-unknown-linux-gnu/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu/4.7.1/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../x86_64-unknown-linux-gnu/bin/

libraries: =/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../x86_64-unknown-linux-gnu/lib/x86_64-unknown-linux-gnu/4.7.1/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../x86_64-unknown-linux-gnu/lib/../lib64/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../x86_64-unknown-linux-gnu/4.7.1/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../lib64/:/lib/x86_64-unknown-linux-gnu/4.7.1/:/lib/../lib64/:/usr/lib/x86_64-unknown-linux-gnu/4.7.1/:/usr/lib/../lib64/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../../x86_64-unknown-linux-gnu/lib/:/share/apps/tools/gcc/gcc47/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/../../../:/lib/:/usr/lib/

8. glibc
cd ~/tmp/gcc
wget http://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.gz
tar xvf blic-2.14.tar.gz
cd glibc-2.14/
mkdir build
cd build/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/share/apps/tools/gcc/mpc/lib:/share/apps/tools/gcc/mpfr/lib:/share/apps/tools/gcc/gmp/lib
.././configure --prefix=/share/apps/tools/gcc/glibc CC=gcc-gcc-4.7 --with-headers=/usr/src/kernels/2.6.18-238.19.1.el5-x86_64/include
make install

Using the current glibc 2.16 requires kernel>2.6.19 which is why I used 2.14. I don't want to fiddle with installing a new kernel on a production system which is shared between several users (and time zones...):
configure: error: GNU libc requires kernel header files from
Linux 2.6.19 or later to be installed before configuring.
The kernel header files are found usually in /usr/include/asm and
/usr/include/linux; make sure these directories use files from
Linux 2.6.19 or later.  This check uses <linux/version.h>, so
make sure that file was built correctly when installing the kernel header
files.  To use kernel headers not from /usr/include/linux, use the
configure option --with-headers.

Optional -- libtool, libunistring, libffi, bdw-gc, autogen and guile

I'm still stuck on Guile.

If you want to run make check on your gcc build, you need autogen, which needs guile, which needs libtool and libunistring

cd ~/tmp/gcc
wget http://ftpmirror.gnu.org/libtool/libtool-2.4.2.tar.gz
tar xvf libtool-2.4.2.tar.gz
cd libtool-2.4.2/
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/libtool --program-suffix=-2.4.2
make install

make check
(this is very slow)
All 122 tests passed
(2 tests were not run)
## ------------- ##
## Test results. ##
## ------------- ##

104 tests behaved as expected.
22 tests were skipped.

cd ~/tmp/gcc
wget http://ftp.gnu.org/gnu/libunistring/libunistring-0.9.3.tar.gz
tar xvf libunistring-0.9.3.tar.gz 
cd libunistring-0.9.3/
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/libunistring
make install

make check
All 418 tests passed

cd ~/tmp/gcc
wget ftp://sourceware.org/pub/libffi/libffi-3.0.11.tar.gz
tar xvf libffi-3.0.11.tar.gz 
cd libffi-3.0.11/
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/libffi
make install
cp include -R /share/apps/tools/gcc/libffi/
cp ../src/x86/ffitarget.h /share/apps/tools/gcc/libffi/include/

cd ~/tmp/gcc
wget http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc.tar.gz
tar xvf gc.tar.gz
cd gc-7.2/
mkdir build
cd build/
 .././configure --prefix=/share/apps/tools/gcc/bdw-gc

make check
All 10 tests passed

wget ftp://ftp.gnu.org/gnu/guile/guile-2.0.6.tar.gz
tar xvf guile-2.0.6.tar.gz
cd guile-2.0.6
mkdir build
cd build/
.././configure --prefix=/share/apps/tools/gcc/guile --with-libltdl-prefix=/share/apps/tools/gcc/libtool --with-libgmp-prefix=/share/apps/tools/gcc/gmp --with-libunistring-prefix=/share/apps/tools/gcc/libunistring LIBFFI_CFLAGS=-I/share/apps/tools/gcc/libffi/include LIBFFI_LIBS=-L/share/apps/tools/gcc/libffi/lib BDW_GC_CFLAGS=-I/share/apps/tools/gcc/bdw-gc/include BDW_GC_LIBS=-L/share/apps/tools/gcc/bdw-gc/lib


../.././libguile/finalizers.c:167: error: static declaration of 'GC_set_finalizer_notifier' follows non-static declaration
/share/apps/tools/gcc/bdw-gc/include/gc/gc.h:177: error: previous declaration of 'GC_set_finalizer_notifier' was here
make[3]: *** [libguile_2.0_la-finalizers.lo] Error 1
make[3]: *** Waiting for unfinished jobs....
make[3]: Leaving directory `/home/me/tmp/gcc/guile-2.0.6/build/libguile'
make: *** [all] Error 2

wget http://ftp.gnu.org/gnu/autogen/rel5.16/autogen-5.16.tar.gz
tar xvf autogen-5.16.tar.gz
cd autogen-5.16/
mkdir build
cd build/

checking for x86_64-unknown-linux-gnu-gcc... /home/me/tmp/gcc/gcc-4.7.1/build/./gcc/xgcc -B/home/me/tmp/gcc/gcc-4.7.1/build/./gcc/ -B/share/apps/tools/gcc/gcc47/x86_64-unknown-linux-gnu/bin/ -B/share/apps/tools/gcc/gcc47/x86_64-unknown-linux-gnu/lib/ -isystem /share/apps/tools/gcc/gcc47/x86_64-unknown-linux-gnu/include -isystem /share/apps/tools/gcc/gcc47/x86_64-unknown-linux-gnu/sys-include
checking for suffix of object files... configure: error: in `/home/me/tmp/gcc/gcc-4.7.1/build/x86_64-unknown-linux-gnu/libgcc':
configure: error: cannot compute suffix of object files: cannot compile
See `config.log' for more details.
make[2]: *** [configure-stage1-target-libgcc] Error 1
make[2]: Leaving directory `/home/me/tmp/gcc/gcc-4.7.1/build'
make[1]: *** [stage1-bubble] Error 2
make[1]: Leaving directory `/home/me/tmp/gcc/gcc-4.7.1/build'
make: *** [all] Error 2

Solution: export LD_LIBRARY_PATH to include the mpc, mpfr and gmp lib dirs (see above)

Links to this post:


  1. Thanks for that ... I was able to get a functioning compiler at the end of step 7.

    Have attached a modulesfile (http://modules.sourceforge.net/) to setup the environment to use the compiler so that it doesn't interfere with existing packages.

    ## mymodule modulefile
    ## Sets up the 4.7.1 compilation environment
    proc ModulesHelp { } {
    puts stderr "\tSets up the 4.7.1 compilation environment"

    ## Create a whatis file. Not nessecary but cool.
    module-whatis "Sets the 4.7.1 compilation environment"

    set base /home/pkg/gcc_4.7.1
    set package gcc
    set version 4.7.1

    ## Add my bin directory to the path
    prepend-path PATH $base/gcc47/bin
    prepend-path PATH $base/binutils/bin

    prepend-path LD_LIBRARY_PATH $base/mpfr/lib
    prepend-path LD_LIBRARY_PATH $base/mpc/lib
    prepend-path LD_LIBRARY_PATH $base/gmp/lib
    prepend-path LD_LIBRARY_PATH $base/binutils/lib
    prepend-path LD_LIBRARY_PATH $base/binutils/lib64
    prepend-path LD_LIBRARY_PATH $base/gcc47/lib
    prepend-path LD_LIBRARY_PATH $base/gcc47/lib64

    setenv CC $base/gcc47/bin/gcc-gcc-4.7
    setenv CXX $base/gcc47/bin/g++-gcc-4.7

    # Set a few personal aliases
    set-alias "gcc" "gcc-gcc-4.7"
    set-alias "g++" "g++-gcc-4.7"
    set-alias "gfortran" "gfortran-gcc-4.7"
    set-alias "nm" "gcc-nm-gcc-4.7"
    set-alias "ranlib" "gcc-ranlib-gcc-4.7"
    set-alias "ar" "gcc-ar-gcc-4.7"
    set-alias "c++" "c++-gcc-4.7"
    set-alias "cpp" "cpp-gcc-4.7"

    if { [ module-info mode load ] } {
    puts stderr "Note: $package $version environment loaded."

    1. Mark,
      thanks a lot for the modules script!

  2. FYI, guile is packaged in the CentOS base repository in CentOS5. If you didn't use the CentOS DVD during Rocks install, the packages may not be present in your Rocks yum repo. In that case, you may want to do some googling to find out how to get the full CentOS DVD into the repo.

    At any rate:
    sudo yum install guile guile-devel
    sudo rocks run host "yum -y install guile guile-devel"

    1. Thanks for the suggestion. I abandoned this some time ago, but it might be time to revive it.

    2. This comment has been removed by a blog administrator.

    3. FlakRat, I accidentally deleted your post (another reason I don't like tablets), and from what I can see blogspot doesn't offer any way of recovering deleted comments...

      Anyway, I've added the link to your post above -- I used the full blogspot URL: http://flakrat.blogspot.com/2013/06/building-gcc-481-on-centos-59.html