Skip to content

Instantly share code, notes, and snippets.

@jchia
Created November 11, 2012 04:49
Show Gist options
  • Save jchia/4053755 to your computer and use it in GitHub Desktop.
Save jchia/4053755 to your computer and use it in GitHub Desktop.
Build gcc 4.7.2 and boost 1.51 (all libraries) on CentOS 6, adapted from someone else's script
#!/bin/bash
#
# $Id: bld.sh,v 1.2 2012/09/22 16:04:19 jlinoff Exp jlinoff $
#
# Author: Joe Linoff
#
# This script downloads, builds and installs the gcc-4.7.2 compiler
# and boost 1.51. It takes handles the dependent packages like
# gmp-5.0.5, mpfr-3.1.1, ppl-1.0 and cloog-0.17.0.
#
# To install gcc-4.7.2 in ~/tmp/gcc-4.7.2/rtf/bin you would run this
# script as follows:
#
# % # Install in ~/tmp/gcc-4.7.2/rtf/bin
# % bld.sh ~/tmp/gcc-4.7.2 2>&1 | tee bld.log
#
# If you do not specify a directory, then it will install in the
# current directory which means that following command will also
# install in ~/tmp/gcc-4.7.2/rtf/bin:
#
# % # Install in ~/tmp/gcc-4.7.2/rtf/bin
# % mkdir -p ~/tmp/gcc-4.7.2
# % cd ~/tmp/gcc-4.7.2
# % bld.sh 2>&1 | tee bld.log
#
# This script creates 4 subdirectories:
#
# Directory Description
# ========= ==================================================
# archives This is where the package archives are downloaded.
# src This is where the package source is located.
# bld This is where the packages are built from source.
# rtf This is where the packages are installed.
#
# When the build is complete you can safely remove the archives, bld
# and src directory trees to save disk space.
#
# Copyright (C) 2012 Joe Linoff
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ================================================================
# Trim a string, remove internal spaces, convert to lower case.
# ================================================================
function get-platform-trim {
local s=$(echo "$1" | tr -d '[ \t]' | tr 'A-Z' 'a-z')
echo $s
}
# ================================================================
# Get the platform root name.
# ================================================================
function get-platform-root
{
if which uname >/dev/null 2>&1 ; then
# Greg Moeller reported that the original code didn't
# work because the -o option is not available on solaris.
# I modified the script to correctly identify that
# case and recover by using the -s option.
if uname -o >/dev/null 2>&1 ; then
# Linux distro
uname -o | tr 'A-Z' 'a-z'
elif uname -s >/dev/null 2>&1 ; then
# Solaris variant
uname -s | tr 'A-Z' 'a-z'
else
echo "unkown"
fi
else
echo "unkown"
fi
}
# ================================================================
# Get the platform identifier.
#
# The format of the output is:
# <plat>-<dist>-<ver>-<arch>
# ^ ^ ^ ^
# | | | +----- architecture: x86_64, i86pc, etc.
# | | +----------- version: 5.5, 4.7
# | +------------------ distribution: centos, rhel, nexentaos
# +------------------------- platform: linux, sunos
#
# ================================================================
function get-platform
{
plat=$(get-platform-root)
case "$plat" in
"gnu/linux")
d=$(get-platform-trim "$(lsb_release -i)" | awk -F: '{print $2;}')
r=$(get-platform-trim "$(lsb_release -r)" | awk -F: '{print $2;}')
m=$(get-platform-trim "$(uname -m)")
if [[ "$d" == "redhatenterprise"* ]] ; then
# Need a little help for Red Hat because
# they don't make the minor version obvious.
d="rhel_${d:16}" # keep the tail (e.g., es or client)
x=$(get-platform-trim "$(lsb_release -c)" | \
awk -F: '{print $2;}' | \
sed -e 's/[^0-9]//g')
r="$r.$x"
fi
echo "linux-$d-$r-$m"
;;
"cygwin")
x=$(get-platform-trim "$(uname)")
echo "linux-$x"
;;
"sunos")
d=$(get-platform-trim "$(uname -v)")
r=$(get-platform-trim "$(uname -r)")
m=$(get-platform-trim "$(uname -m)")
echo "sunos-$d-$r-$m"
;;
"unknown")
echo "unk-unk-unk-unk"
;;
*)
echo "$plat-unk-unk-unk"
;;
esac
}
# Execute command with decorations and status testing.
# Usage : docmd $ar <cmd>
# Example: docmd $ar ls -l
function docmd {
local ar=$1
shift
local cmd=($*)
echo
echo " # ================================================================"
if [[ "$ar" != "" ]] ; then
echo " # Archive: $ar"
fi
echo " # PWD: "$(pwd)
echo " # CMD: "${cmd[@]}
echo " # ================================================================"
${cmd[@]}
local st=$?
echo "STATUS = $st"
if (( $st != 0 )) ; then
exit $st;
fi
}
# Report an error and exit.
# Usage : doerr <line1> [<line2> .. <line(n)>]
# Example: doerr "line 1 msg"
# Example: doerr "line 1 msg" "line 2 msg"
function doerr {
local prefix="ERROR: "
for ln in "$@" ; do
echo "${prefix}${ln}"
prefix=" "
done
exit 1
}
# Extract archive information.
# Usage : ard=( $(extract-ar-info $ar) )
# Example: ard=( $(extract-ar-info $ar) )
# fn=${ard[1]}
# ext=${ard[2]}
# d=${ard[3]}
function extract-ar-info {
local ar=$1
local fn=$(basename $ar)
local ext=$(echo $fn | awk -F. '{print $NF}')
local d=${fn%.*tar.$ext}
echo $ar
echo $fn
echo $ext
echo $d
}
# Print a banner for a new section.
# Usage : banner STEP $ar
# Example: banner "DOWNLOAD" $ar
# Example: banner "BUILD" $ar
function banner {
local step=$1
local ard=( $(extract-ar-info $2) )
local ar=${ard[0]}
local fn=${ard[1]}
local ext=${ard[2]}
local d=${ard[3]}
echo
echo '# ================================================================'
echo "# Step : $step"
echo "# Archive: $ar"
echo "# File : $fn"
echo "# Ext : $ext"
echo "# Dir : $d"
echo '# ================================================================'
}
# Make a group directories
# Usage : mkdirs <dir1> [<dir2> .. <dir(n)>]
# Example: mkdirs foo bar spam spam/foo/bar
function mkdirs {
local ds=($*)
#echo "mkdirs"
for d in ${ds[@]} ; do
#echo " testing $d"
if [ ! -d $d ] ; then
#echo " creating $d"
mkdir -p $d
fi
done
}
# ================================================================
# Check the current platform to see if it is in the tested list,
# if it isn't, then issue a warning.
# ================================================================
function check-platform
{
local plat=$(get-platform)
local tested_plats=(
'linux-centos-5.5-x86_64'
'linux-centos-5.8-x86_64'
'linux-centos-6.3-x86_64')
local plat_found=0
echo "PLATFORM: $plat"
for tested_plat in ${tested_plats[@]} ; do
if [[ "$plat" == "$tested_plat" ]] ; then
plat_found=1
break
fi
done
if (( $plat_found == 0 )) ; then
echo "WARNING: This platform ($plat) has not been tested."
fi
}
# ================================================================
# DATA
# ================================================================
# List of archives
# The order is important.
ARS=(
http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
ftp://ftp.gmplib.org/pub/gmp-5.0.5/gmp-5.0.5.tar.bz2
http://www.mpfr.org/mpfr-current/mpfr-3.1.1.tar.bz2
http://www.multiprecision.org/mpc/download/mpc-1.0.tar.gz
http://bugseng.com/products/ppl/download/ftp/releases/1.0/ppl-1.0.tar.bz2
http://www.bastoul.net/cloog/pages/download/cloog-0.17.0.tar.gz
http://ftp.gnu.org/gnu/gcc/gcc-4.7.2/gcc-4.7.2.tar.bz2
http://ftp.gnu.org/gnu/binutils/binutils-2.22.tar.bz2
http://sourceforge.net/projects/boost/files/boost/1.51.0/boost_1_51_0.tar.bz2
#
# Why glibc is disabled (for now).
#
# glibc does not work on CentOS because the versions of the shared
# libraries we are building are not compatiable with installed
# shared libraries.
#
# This is the run-time error: ELF file OS ABI invalid that I see
# when I try to run binaries compiled with the local glibc-2.15.
#
# Note that the oldest supported ABI for glibc-2.15 is 2.2. The
# CentOS 5.5 ABI is 0.
# http://ftp.gnu.org/gnu/glibc/glibc-2.15.tar.bz2
)
# ================================================================
# MAIN
# ================================================================
umask 0
check-platform
export PATH="${PREFIXDIR}/bin:${PATH}"
export LD_LIBRARY_PATH="${PREFIXDIR}/lib:${LD_LIBRARY_PATH}"
# Read the command line argument, if it exists.
ROOTDIR=$(readlink -f .)
PREFIXDIR=/usr/local
if (( $# == 1 )) ; then
PREFIXDIR=$(readlink -f $1)
elif (( $# > 1 )) ; then
doerr "too many command line arguments ($#), only zero or one is allowed" "foo"
fi
# Setup the directories.
ARDIR="$ROOTDIR/archives"
SRCDIR="$ROOTDIR/src"
BLDDIR="$ROOTDIR/bld"
TSTDIR="$SRCDIR/LOCAL-TEST"
echo
echo "# ================================================================"
echo '# Version : $Id: bld.sh,v 1.2 2012/09/22 16:04:19 jlinoff Exp jlinoff $'
echo "# PerfixDir : $PREFIXDIR"
echo "# ArchiveDir : $ARDIR"
echo "# RtfDir : $PREFIXDIR"
echo "# SrcDir : $SRCDIR"
echo "# BldDir : $BLDDIR"
echo "# TstDir : $TSTDIR"
echo "# Gcc : "$(which gcc)
echo "# GccVersion : "$(gcc --version | head -1)
echo "# Hostname : "$(hostname)
echo "# O/S : "$(uname -s -r -v -m)
echo "# Date : "$(date)
echo "# ================================================================"
mkdirs $ARDIR $PREFIXDIR $SRCDIR $BLDDIR
# ================================================================
# Download
# ================================================================
for ar in ${ARS[@]} ; do
banner 'DOWNLOAD' $ar
ard=( $(extract-ar-info $ar) )
fn=${ard[1]}
ext=${ard[2]}
d=${ard[3]}
if [ -f "${ARDIR}/$fn" ] ; then
echo "skipping $fn"
else
# get
docmd $ar wget $ar -O "${ARDIR}/$fn"
fi
done
# ================================================================
# Extract
# ================================================================
for ar in ${ARS[@]} ; do
banner 'EXTRACT' $ar
ard=( $(extract-ar-info $ar) )
fn=${ard[1]}
ext=${ard[2]}
d=${ard[3]}
sd="$SRCDIR/$d"
if [ -d $sd ] ; then
echo "skipping $fn"
else
# unpack
pushd $SRCDIR
case "$ext" in
"bz2")
docmd $ar tar jxf ${ARDIR}/$fn
;;
"gz")
docmd $ar tar zxf ${ARDIR}/$fn
;;
"tar")
docmd $ar tar xf ${ARDIR}/$fn
;;
*)
doerr "unrecognized extension: $ext" "Can't continue."
;;
esac
popd
if [ ! -d $sd ] ; then
# Some archives (like gcc-g++) overlay. We create a dummy
# directory to avoid extracting them every time.
mkdir -p $sd
fi
fi
done
# ================================================================
# Build
# ================================================================
for ar in ${ARS[@]} ; do
banner 'BUILD' $ar
ard=( $(extract-ar-info $ar) )
fn=${ard[1]}
ext=${ard[2]}
d=${ard[3]}
sd="$SRCDIR/$d"
bd="$BLDDIR/$d"
if [ -d $bd ] ; then
echo "skipping $sd"
else
# Build
if [ $(expr match "$fn" 'gcc-g++') -ne 0 ] ; then
# Don't build/configure the gcc-g++ package explicitly because
# it is part of the regular gcc package.
echo "skipping $sd"
# Dummy
continue
fi
# Set the CONF_ARGS
in_bld=1 # build in the bld area
run_conf=1
run_bootstrap=0
case "$d" in
binutils-*)
# Binutils will not compile with strict error
# checking on so I disabled -Werror by setting
# --disable-werror.
CONF_ARGS=(
--disable-cloog-version-check
--disable-werror
--enable-cloog-backend=isl
--enable-lto
--enable-libssp
--enable-gold
--prefix=${PREFIXDIR}
--with-cloog=${PREFIXDIR}
--with-gmp=${PREFIXDIR}
--with-mlgmp=${PREFIXDIR}
--with-mpc=${PREFIXDIR}
--with-mpfr=${PREFIXDIR}
--with-ppl=${PREFIXDIR}
CC=${PREFIXDIR}/bin/gcc
CXX=${PREFIXDIR}/bin/g++
)
# We need to make a special fix here to the configure
# script because it chokes on ppl 1.x.
src="$sd/configure"
if [ -f $src ] ; then
if [ ! -f $src.orig ] ; then
mv $src $src.orig
sed -e 's/#if PPL_VERSION_MAJOR != 0 || PPL_VERSION_MINOR < 11/#if PPL_VERSION_MAJOR != 1/' \
$src.orig > $src
chmod a+x $src
fi
fi
;;
boost_*)
# The boost configuration scheme requires
# that the build occur in the source directory.
run_conf=0
run_bootstrap=1
in_bld=0
CONF_ARGS=(
--prefix=${PREFIXDIR}
--with-libraries=all
--with-icu
--with-python=python3.2
--with-python-version=3.2
)
# Special fix for Boost bug where bootstrap.sh is not using
#proper Python 3 syntax.
src="$sd/bootstrap.sh"
if [ -f $src ] ; then
if [ ! -f $src.orig ] ; then
cp --preserve=all $src $src.orig
sed -i 's/print sys.prefix/print (sys.prefix)/' \
$src
fi
fi
;;
cloog-*)
GMPDIR=$(ls -1d ${BLDDIR}/gmp-*)
CONF_ARGS=(
--prefix=${PREFIXDIR}
--with-gmp-builddir=${GMPDIR}
--with-gmp=build
## --with-isl=system
)
;;
gcc-*)
# We are using a newer version of CLooG (0.17.0).
# I have also made stack protection available
# (similar to DEP in windows).
CONF_ARGS=(
--disable-cloog-version-check
--disable-ppl-version-check
--enable-cloog-backend=isl
--enable-gold
--enable-languages='c,c++'
--enable-lto
--enable-libssp
--prefix=${PREFIXDIR}
--with-cloog=${PREFIXDIR}
--with-gmp=${PREFIXDIR}
--with-mlgmp=${PREFIXDIR}
--with-mpc=${PREFIXDIR}
--with-mpfr=${PREFIXDIR}
--with-ppl=${PREFIXDIR}
)
# We need to make a special fix here to the configure
# script because it chokes on ppl 1.x.
src="$sd/configure"
if [ -f $src ] ; then
if [ ! -f $src.orig ] ; then
mv $src $src.orig
sed -e 's/#if PPL_VERSION_MAJOR != 0 || PPL_VERSION_MINOR < 11/#if PPL_VERSION_MAJOR != 1/' \
$src.orig > $src
chmod a+x $src
fi
fi
;;
glibc-*)
CONF_ARGS=(
--enable-static-nss=no
--prefix=${PREFIXDIR}
--with-binutils=${PREFIXDIR}
--with-elf
CC=${PREFIXDIR}/bin/gcc
CXX=${PREFIXDIR}/bin/g++
)
;;
gmp-*)
CONF_ARGS=(
--enable-cxx
--prefix=${PREFIXDIR}
)
;;
libiconv-*)
CONF_ARGS=(
--prefix=${PREFIXDIR}
)
;;
mpc-*)
CONF_ARGS=(
--prefix=${PREFIXDIR}
--with-gmp=${PREFIXDIR}
--with-mpfr=${PREFIXDIR}
)
;;
mpfr-*)
CONF_ARGS=(
--prefix=${PREFIXDIR}
--with-gmp=${PREFIXDIR}
)
;;
ppl-*)
CONF_ARGS=(
--prefix=${PREFIXDIR}
--with-gmp=${PREFIXDIR}
)
;;
*)
doerr "unrecognized package: $d"
;;
esac
if (( $in_bld )) ; then
mkdir -p $bd
pushd $bd
else
echo "NOTE: This package must be built in the source directory."
pushd $sd
fi
if (( $run_conf )) ; then
docmd $ar $sd/configure --help
docmd $ar $sd/configure ${CONF_ARGS[@]}
docmd $ar make -j4
docmd $ar make install
fi
if (( $run_bootstrap )) ; then
docmd $ar which g++
docmd $ar $sd/bootstrap.sh --help
docmd $ar $sd/bootstrap.sh ${CONF_ARGS[@]}
docmd $ar ./b2 -j4 release
docmd $ar ./b2 install
fi
# Redo the tests if anything changed.
if [ -d $TSTDIR ] ; then
rm -rf $TSTDIR
fi
popd
fi
done
# ================================================================
# Test
# ================================================================
if [ -d $TSTDIR ] ; then
echo "skipping tests"
else
docmd "MKDIR" mkdir -p $TSTDIR
pushd $TSTDIR
docmd "LOCAL TEST 1" which g++
docmd "LOCAL TEST 2" which gcc
docmd "LOCAL TEST 3" which c++
docmd "LOCAL TEST 4" g++ --version
# Simple aliveness test.
cat >test1.cc <<EOF
#include <iostream>
using namespace std;
int main()
{
cout << "IO works" << endl;
return 0;
}
EOF
docmd "LOCAL TEST 5" g++ -O3 -Wall -o test1.bin test1.cc
docmd "LOCAL TEST 6" ./test1.bin
docmd "LOCAL TEST 7" g++ -g -Wall -o test1.dbg test1.cc
docmd "LOCAL TEST 8" ./test1.dbg
# Simple aliveness test for boost.
cat >test2.cc <<EOF
#include <iostream>
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
int main()
{
string s1(" hello world! ");
cout << "value : '" << s1 << "'" <<endl;
to_upper(s1);
cout << "to_upper() : '" << s1 << "'" <<endl;
trim(s1);
cout << "trim() : '" << s1 << "'" <<endl;
return 0;
}
EOF
docmd "LOCAL TEST 9" g++ -O3 -Wall -o test2.bin test2.cc
docmd "LOCAL TEST 10" ./test2.bin
docmd "LOCAL TEST 11" g++ -g -Wall -o test2.dbg test2.cc
docmd "LOCAL TEST 12" ./test2.dbg
docmd "LOCAL TEST" ls -l
popd
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment