diff options
author | David Turner <digit@google.com> | 2014-03-12 14:58:19 +0800 |
---|---|---|
committer | Andrew Hsieh <andrewhsieh@google.com> | 2014-03-12 14:58:19 +0800 |
commit | 0c7a4a92c87d84d583b72c20e4fbadea15bca632 (patch) | |
tree | 6d51cfef413a246766efd5aeeda0b174344066d0 | |
parent | 4a94057c37293930d1336a14e3038b429cebd988 (diff) | |
download | x86_64-linux-glibc2.11-4.8-0c7a4a92c87d84d583b72c20e4fbadea15bca632.tar.gz |
Add build script for glibc2.11-based host toolchain
BUG=8187523
Change-Id: Iec27b132d9667010980a36a5b8a9aa13549f0d61
-rw-r--r-- | build-lucid-toolchain.sh | 1811 |
1 files changed, 1811 insertions, 0 deletions
diff --git a/build-lucid-toolchain.sh b/build-lucid-toolchain.sh new file mode 100644 index 0000000..d557fea --- /dev/null +++ b/build-lucid-toolchain.sh @@ -0,0 +1,1811 @@ +#!/bin/bash +# +# Copyright (C) 2010 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This script is used to rebuild the Linux 32-bit cross-toolchain +# that allows you to generate 32-bit binaries that target Ubuntu 8.04 +# (a.k.a. Hardy Heron) instead of the host system (which usually is 10.04, +# a.k.a. Lucid Lynx) +# +# Use --help for complete usage information. +# +# WARNING: At this time, the generated toolchain binaries will *not* run +# with GLibc 2.7, only the machine code it generates. +# + +PROGNAME="`basename \"$0\"`" +PATCHES_DIR="$( cd "$( dirname "$0" )" && pwd )/toolchain-patches" + +########################################################################### +########################################################################### +##### +##### C O N F I G U R A T I O N +##### +########################################################################### +########################################################################### + +panic () +{ + echo "ERROR: $@" + exit 1 +} + +fail_panic () +{ + if [ $? != 0 ] ; then + echo "ERROR: $@" + exit 1 + fi +} + + +# We only support running this script on Linux +OS=$(uname -s) +if [ "$OS" != Linux ]; then + panic "This script can only run on Linux machines!" +fi + +# Used to set the host bitness of the generted toolchain binaries +# First call with the build machine's bitness, and later with 32 +# if --32-bits option is used. +# $1: 32 or 64 +set_host_bits () +{ + HOST_BITS=$1 + GMP_ABI=$1 + case $1 in + 32) + HOST_ARCH=i686 + UBUNTU_ARCH=i386 + GCC_TARGET=i686-linux + GMP_TARGET=i386-linux + ;; + 64) + HOST_ARCH=x86_64 + UBUNTU_ARCH=amd64 + GCC_TARGET=x86_64-linux + GMP_TARGET=x86_64-linux + ;; + *) + panic "Invalid host bitness (32 or 64 expected): $1" + esac +} + +# Determine build machine bitness +BUILD_ARCH=$(uname -m) +case "$BUILD_ARCH" in + x86_64|amd64) + BUILD_BITS=64 + BUILD_ARCH=x86_64 + BUILD_GCC_TARGET=x86_64-linux + set_host_bits 64 + ;; + i?86) + BUILD_BITS=32 + BUILD_ARCH=i686 + BUILD_GCC_TARGET=i686-linux + set_host_bits 32 + ;; + *) + panic "Unknown build CPU architecture: $BUILD_ARCH" +esac + +# Versions of various toolchain components, do not touch unless you know +# what you're doing! + +BINUTILS_VERSION=2.21 +GMP_VERSION=5.0.5 +MPFR_VERSION=3.1.1 +MPC_VERSION=1.0.1 +GCC_VERSION=4.8 +CLOOG_VERSION=0.18.0 +ISL_VERSION=0.11.1 + +GIT_CMD=git +GIT_DATE= +GIT_BRANCH=master +GIT_REFERENCE= +GIT_BASE= +GIT_BASE_DEFAULT=https://android.googlesource.com/toolchain + +# Location where we're going to install the toolchain during the build +# This will depend on the phase of the build. +install_dir () { echo "$WORK_DIR/$PHASE/$TOOLCHAIN_NAME"; } + +# Location where we're going to install the final binaries +# If empty, TOOLCHAIN_ARCHIVE will be generated +PREFIX_DIR= + +# Location of the final sysroot. This must be a sub-directory of INSTALL_DIR +# to ensure that the toolchain binaries are properly relocatable (i.e. can +# be used when moved to another directory). +sysroot_dir () { echo "$(install_dir)/sysroot"; } + +# Try to parallelize the build for faster performance. +JOBS=$(cat /proc/cpuinfo | grep -c processor) + +# The base URL of the Ubuntu mirror we're going to use. +UBUNTU_MIRROR=http://mirrors.us.kernel.org + +# Ubuntu release name we want packages from. Can be a name or a number +# (i.e. "lucid" or "10.04") +UBUNTU_RELEASE=lucid + + +# The list of packages we need to download from the Ubuntu servers and +# extract into the original sysroot +# +# Call add_ubuntu_package <package-name> to add a package to the list, +# which will be processed later. +# +UBUNTU_PACKAGES= + +add_ubuntu_package () +{ + UBUNTU_PACKAGES="$UBUNTU_PACKAGES $@" +} + +# The package files containing kernel headers for Hardy and the C +# library headers and binaries +add_ubuntu_package \ + linux-libc-dev \ + libc6 \ + libc6-dev + +# The X11 headers and binaries (for the emulator) +add_ubuntu_package \ + libx11-6 \ + libx11-dev \ + libxcb1-dev \ + libxau6 \ + libxdmcp6 \ + x11proto-core-dev \ + x11proto-xext-dev \ + x11proto-input-dev \ + x11proto-kb-dev + +# The OpenGL-related headers and libraries (for GLES emulation) +add_ubuntu_package \ + mesa-common-dev \ + libgl1-mesa-dev \ + libgl1-mesa-glx \ + libxxf86vm1 \ + libxext6 \ + libxdamage1 \ + libxfixes3 \ + libdrm2 + +# Audio libraries (required by the emulator) +add_ubuntu_package \ + libasound2 \ + libasound2-dev \ + libesd0-dev \ + libaudiofile-dev \ + libpulse0 \ + libpulse-dev + +# ZLib +add_ubuntu_package \ + zlib1g \ + zlib1g-dev \ + libncurses5 \ + libncurses5-dev + + + +########################################################################### +########################################################################### +##### +##### E N D O F C O N F I G U R A T I O N +##### +########################################################################### +########################################################################### + +# Parse all options +OPTION_HELP=no +VERBOSE=0 +FORCE=no +ONLY_SYSROOT=no +ONLY_TOOLCHAIN_DIR= +BOOTSTRAP= +PARAMETERS= +FORCE_32= +LIST_TASKS= + +for opt do + optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'` + case "$opt" in + --help|-h|-\?) OPTION_HELP=yes + ;; + --verbose) VERBOSE=$(( $VERBOSE + 1 )) + ;; + --force) FORCE="yes" + ;; + --32-bits) FORCE_32=true + ;; + --ubuntu-mirror=*) UBUNTU_MIRROR="$optarg" + ;; + --ubuntu-release=*) UBUNTU_RELEASE="$optarg" + ;; + --prefix=*) PREFIX_DIR="$optarg" + ;; + --work-dir=*) WORK_DIR="$optarg" + ;; + --gcc-version=*) GCC_VERSION="$optarg" + ;; + --binutils-version=*) BINUTILS_VERSION="$optarg" + ;; + --gmp-version=*) GMP_VERSION="$optarg" + ;; + --mpfr-version=*) MPFR_VERSION="$optarg" + ;; + --mpc-version=*) MPC_VERSION="$optarg" + ;; + --isl-version=*) ISL_VERSION="$optarg" + ;; + --cloog-version=*) CLOOG_VERSION="$oparg" + ;; + --git=*) GIT_CMD=$optarg + ;; + --git-date=*) GIT_DATE=$optarg + ;; + --git-branch=*) GIT_BRANCH=$optarg + ;; + --git-base=*) GIT_BASE=$optarg + ;; + --git-reference=*) GIT_REFERENCE=$optarg + ;; + --out-dir=*) OPTION_OUT_DIR="$optarg" + ;; + --cc=*) OPTION_CC="$optarg" + ;; + --jobs=*) JOBS="$optarg" + ;; + -j*) JOBS=`expr "x$opt" : 'x-j\(.*\)'` + ;; + --only-sysroot) ONLY_SYSROOT=yes + ;; + --bootstrap) BOOTSTRAP=yes + ;; + --list-tasks) LIST_TASKS=yes + ;; + -*) + echo "unknown option '$opt', use --help" + exit 1 + ;; + *) + if [ -z "$PARAMETERS" ]; then + PARAMETERS="$opt" + else + PARAMETERS="$PARAMETERS $opt" + fi + esac +done + +if [ "$OPTION_HELP" = "yes" ]; then + cat << EOF + +Usage: $PROGNAME [options] [<path-to-toolchain-sources>] + +This script is used to rebuild a custom Linux host toolchain that targets +GLibc 2.7 or higher. The machine code generated by this toolchain will run +properly on Ubuntu 8.04 or higher. + +If you're running on a 32-bit system, it will generate a 32-bit toolchain. +If you're running on a 64-bit system, it will generate a 64-bit toolchain +unless you use the --32-bits option. + +You can provide the path to a local copy of the toolchain sources repository +as a first parameter. If you don't, the sources will be downloaded and +extracted automatically into your work directory. + +Note that this script will download various binary packages from Ubuntu +servers in order to prepare a compatible "sysroot". + +By default, it generates a package archive ($TOOLCHAIN_ARCHIVE) but you can, +as an alternative, ask for direct installation with --prefix=<path> + +Use the bootstrap option to re-generate the toolchain with itself. This is +useful if you want to ensure that the generated compiler binaries will work +properly on Ubuntu 8.04 or higher. By default, they will only run on systems +that match your build system's C library ABI, or higher. + +Options: [defaults in brackets after descriptions] +EOF + echo "Standard options:" + echo " --help Print this message" + echo " --force Force-rebuild everything" + echo " --prefix=PATH Installation path [$PREFIX_DIR]" + echo " --ubuntu-mirror=URL Ubuntu mirror URL [$UBUNTU_MIRROR]" + echo " --ubuntu-release=NAME Ubuntu release name [$UBUNTU_RELEASE]" + echo " --work-dir=PATH Temporary work directory [/tmp/gcc.<random>]" + echo " --only-sysroot Only dowload and build sysroot packages" + echo " --verbose Verbose output. Can be used twice." + echo " --binutils-version=VERSION Binutils version number [$BINUTILS_VERSION]" + echo " --gcc-version=VERSION GCC version number [$GCC_VERSION]" + echo " --gmp-version=VERSION GMP version number [$GMP_VERSION]" + echo " --mpfr-version=VERSION MPFR version numner [$MPFR_VERSION]" + echo " --mpc-version=VERSION MPC version number [$MPC_VERSION]" + echo " --isl-version=VERSION ISL version number [$ISL_VERSION]" + echo " --cloog-version=VERSION Cloog version number [$CLOOG_VERSION]" + echo " --jobs=COUNT Run COUNT build jobs in parallel [$JOBS]" + echo " -j<COUNT> Same as --jobs=COUNT." + echo " --git=<cmd> Use this version of the git tool [$GIT_CMD]" + echo " --git-date=<date> Specify specific git date when download sources [none]" + echo " --git-branch=<name> Specify which branch to use when downloading the sources [$GIT_BRANCH]" + echo " --git-reference=<path> Use a git reference repository" + echo " --git-base=<url> Use this git repository base [$GIT_BASE]" + echo " --bootstrap Bootstrap toolchain (i.e. compile it with itself)" + echo " --32-bits Generate 32-bit toolchain on 64-bit build system." + echo "" + exit 1 +fi + +if [ "$FORCE_32" ]; then + if [ "$BUILD_BITS" = 64 ]; then + set_host_bits 32 + else + echo "Warning: --32-bits option ignored on 32-bit build machine." + fi +fi + +# Determine root working directory for our script +if [ -z "$WORK_DIR" ]; then + WORK_DIR=$(mktemp -d /tmp/$USER-gcc-$HOST_BITS-XXXXXX) + WORK_DIR_CLEANUP=true +else + mkdir -p "$WORK_DIR" + fail_panic "Could not create directory: $WORK_DIR" + WORK_DIR_CLEANUP=false +fi + +if [ -z "$PARAMETERS" ] ; then + if [ -n "$GIT_REFERENCE" ] ; then + if [ ! -d "$GIT_REFERENCE" -o ! -d "$GIT_REFERENCE/build" ]; then + echo "ERROR: Invalid reference repository directory path: $GIT_REFERENCE" + exit 1 + fi + if [ -n "$GIT_BASE" ]; then + echo "Using git clone reference: $GIT_REFERENCE" + else + # If we have a reference without a base, use it as a download base instead. + GIT_BASE=$GIT_REFERENCE + GIT_REFERENCE= + echo "Using git clone base: $GIT_BASE" + fi + elif [ -z "$GIT_BASE" ]; then + GIT_BASE=$GIT_BASE_DEFAULT + echo "Auto-config: --git-base=$GIT_BASE" + fi + + # Location where we will download the toolchain sources + TOOLCHAIN_SRC_DIR=$WORK_DIR/toolchain-src +else + set_parameters () { + TOOLCHAIN_SRC_DIR="$1" + if [ ! -d "$TOOLCHAIN_SRC_DIR" ]; then + echo "ERROR: Not a directory: $1" + exit 1 + fi + if [ ! -d "$TOOLCHAIN_SRC_DIR/build" ]; then + echo "ERROR: Missing directory: $1/build" + exit 1 + fi + } + + set_parameters $PARAMETERS +fi + +# Location of original sysroot. This is where we're going to extract all +# binary Ubuntu packages. +ORG_SYSROOT_DIR=$WORK_DIR/sysroot + +# Name of the final generated toolchain +TOOLCHAIN_NAME=$GCC_TARGET-glibc2.11-$GCC_VERSION + +# Name of the final toolchain binary tarball that this script will create +TOOLCHAIN_ARCHIVE=/tmp/$TOOLCHAIN_NAME.tar.bz2 + +# A file that will contain details about all the sources used to generate +# the final toolchain. This includes both SHA-1 for toolchain git repositories +# and SHA-1 hashes for downloaded Ubuntu packages. +SOURCES_LIST=$WORK_DIR/SOURCES + +# Determine Make flags +MAKE_FLAGS="-j$JOBS" + +# Create the work directory +mkdir -p "$WORK_DIR" + +# Location where we download packages from the Ubuntu servers +DOWNLOAD_DIR=$WORK_DIR/download + +# Empty the SOURCES file +rm -f "$SOURCES_LIST" && touch "$SOURCES_LIST" + + +if [ "$VERBOSE" -ge 1 ] ; then + run () { + echo "## COMMAND: $@" + $@ + } + log () { + echo "$@" + } + if [ "$VERBOSE" -ge 2 ] ; then + log2 () { + echo "$@" + } + else + log2 () { + return + } + fi +else + run () { + "$@" >>$TMPLOG 2>&1 + } + log () { + return + } + log2 () { + return + } +fi + +# Sanitize a path list, we want to remove empty sub-dirs and +# leading/trailing columns. +sanitize_path_list () +{ + local RESULT + RESULT=$(printf "%s\n" "$*" | tr ':' '\n' | awk '$1 != "" && $1 != "." { print $0; }' | tr '\n' ':') + printf "%s" ${RESULT%:} +} + +OLD_PATH=$(sanitize_path_list "$PATH") +OLD_LD_LIBRARY_PATH=$(sanitize_path_list "$LD_LIBRARY_PATH") + +PATH=$OLD_PATH +LD_LIBRARY_PATH=$OLD_LD_LIBRARY_PATH + +BUILD_DIR=$WORK_DIR/build +mkdir -p $BUILD_DIR + +TMPLOG=$BUILD_DIR/build.log +rm -rf $TMPLOG && touch $TMPLOG + +build_binutils_dir () { echo "$BUILD_DIR/$PHASE/binutils"; } +build_gmp_dir () { echo "$BUILD_DIR/$PHASE/gmp"; } +build_mpfr_dir () { echo "$BUILD_DIR/$PHASE/mpfr"; } +build_mpc_dir () { echo "$BUILD_DIR/$PHASE/mpc"; } +build_cloog_dir () { echo "$BUILD_DIR/$PHASE/cloog"; } +build_isl_dir () { echo "$BUILD_DIR/$PHASE/isl"; } +build_gcc_dir () { echo "$BUILD_DIR/$PHASE/gcc"; } + +TIMESTAMPS_DIR=$BUILD_DIR/timestamps +mkdir -p $TIMESTAMPS_DIR + +stamp_check () { + [ -f "$TIMESTAMPS_DIR/$1" ] +} + +stamp_clear () { + rm -f "$TIMESTAMPS_DIR/$1" +} + +stamp_set () { + touch "$TIMESTAMPS_DIR/$1" +} + +if [ "$FORCE" = "yes" ] ; then + echo "Cleaning up timestamps (forcing the build)." + rm -f $TIMESTAMPS_DIR/* +fi + +if [ "$VERBOSE" = 0 ] ; then + echo "To follow build, run: tail -F $TMPLOG" +fi + +# returns 0 iff the string in $2 matches the pattern in $1 +# $1: pattern +# $2: string +pattern_match () +{ + echo "$2" | grep -q -E -e "$1" +} + +# Find if a given shell program is available. +# We need to take care of the fact that the 'which <foo>' command +# may return either an empty string (Linux) or something like +# "no <foo> in ..." (Darwin). Also, we need to redirect stderr +# to /dev/null for Cygwin +# +# $1: variable name +# $2: program name +# +# Result: set $1 to the full path of the corresponding command +# or to the empty/undefined string if not available +# +find_program () +{ + local PROG + PROG=`which $2 2>/dev/null` + if [ -n "$PROG" ] ; then + if pattern_match '^no ' "$PROG"; then + PROG= + fi + fi + eval $1="$PROG" +} + +# Copy a directory, create target location if needed +# +# $1: source directory +# $2: target directory location +# +copy_directory () +{ + local SRCDIR="$1" + local DSTDIR="$2" + if [ ! -d "$SRCDIR" ] ; then + panic "Can't copy from non-directory: $SRCDIR" + fi + log2 "Directory copy: $SRCDIR -> $DSTDIR" + mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar cf - *) | (tar xf - -C "$DSTDIR") + fail_panic "Cannot copy to directory: $DSTDIR" +} + +find_program CMD_WGET wget +find_program CMD_CURL curl +find_program CMD_SCP scp + +# Download a file with either 'curl', 'wget' or 'scp' +# +# $1: source URL (e.g. http://foo.com, ssh://blah, /some/path) +# $2: target file +download_file () +{ + # Is this HTTP, HTTPS or FTP ? + if pattern_match "^(http|https|ftp):.*" "$1"; then + if [ -n "$CMD_WGET" ] ; then + run $CMD_WGET -O $2 $1 + elif [ -n "$CMD_CURL" ] ; then + run $CMD_CURL -o $2 $1 + else + echo "Please install wget or curl on this machine" + exit 1 + fi + return + fi + + # Is this SSH ? + # Accept both ssh://<path> or <machine>:<path> + # + if pattern_match "^(ssh|[^:]+):.*" "$1"; then + if [ -n "$CMD_SCP" ] ; then + scp_src=`echo $1 | sed -e s%ssh://%%g` + run $CMD_SCP $scp_src $2 + else + echo "Please install scp on this machine" + exit 1 + fi + return + fi + + # Is this a file copy ? + # Accept both file://<path> or /<path> + # + if pattern_match "^(file://|/).*" "$1"; then + cp_src=`echo $1 | sed -e s%^file://%%g` + run cp -f $cp_src $2 + return + fi + + # Unknown schema + echo "ERROR: Unsupported source URI: $1" + exit 1 +} + +# A variant of 'download_file' used to specify the target directory +# $1: source URL +# $2: target directory +download_file_to () +{ + local URL="$1" + local DIR="$2" + local DST="$DIR/`basename $URL`" + mkdir -p $DIR + download_file "$URL" "$DST" +} + +# Pack a given archive +# +# $1: archive file path (including extension) +# $2: source directory for archive content +# $3+: list of files (including patterns), all if empty +pack_archive () +{ + local ARCHIVE="$1" + local SRCDIR="$2" + local SRCFILES + local TARFLAGS ZIPFLAGS + shift; shift; + if [ -z "$1" ] ; then + SRCFILES="*" + else + SRCFILES="$@" + fi + if [ "`basename $ARCHIVE`" = "$ARCHIVE" ] ; then + ARCHIVE="`pwd`/$ARCHIVE" + fi + mkdir -p `dirname $ARCHIVE` + if [ "$VERBOSE" -ge 2 ] ; then + TARFLAGS="vcf" + ZIPFLAGS="-9r" + else + TARFLAGS="cf" + ZIPFLAGS="-9qr" + fi + case "$ARCHIVE" in + *.zip) + (cd $SRCDIR && run zip $ZIPFLAGS "$ARCHIVE" $SRCFILES) + ;; + *.tar) + (cd $SRCDIR && run tar $TARFLAGS "$ARCHIVE" $SRCFILES) + ;; + *.tar.gz) + (cd $SRCDIR && run tar z$TARFLAGS "$ARCHIVE" $SRCFILES) + ;; + *.tar.bz2) + (cd $SRCDIR && run tar j$TARFLAGS "$ARCHIVE" $SRCFILES) + ;; + *) + panic "Unsupported archive format: $ARCHIVE" + ;; + esac +} + +no_trailing_slash () +{ + echo ${1##/} +} + +# Load the Ubuntu packages file. This is a long text file that will list +# each package for a given release. +# +# $1: Ubuntu mirror base URL (e.g. http://mirrors.us.kernel.org/) +# $2: Release name +# +get_ubuntu_packages_list () +{ + local RELEASE=$2 + local BASE="`no_trailing_slash \"$1\"`" + local SRCFILE="$BASE/ubuntu/dists/$RELEASE/main/binary-$UBUNTU_ARCH/Packages.bz2" + local DSTFILE="$DOWNLOAD_DIR/Packages.bz2" + log "Trying to load $SRCFILE" + download_file "$SRCFILE" "$DSTFILE" + fail_panic "Could not download $SRCFILE" + (cd $DOWNLOAD_DIR && bunzip2 -f Packages.bz2) + fail_panic "Could not uncompress $DSTFILE" + + # Write a small awk script used to extract filenames for a given package + cat > $DOWNLOAD_DIR/extract-filename.awk <<EOF +BEGIN { + # escape special characters in package name + gsub("\\\\.","\\\\.",PKG) + gsub("\\\\+","\\\\+",PKG) + FILE = "" + PACKAGE = "" +} + +\$1 == "Package:" { + if (\$2 == PKG) { + PACKAGE = \$2 + } else { + PACKAGE = "" + } +} + +\$1 == "Filename:" && PACKAGE == PKG { + FILE = \$2 +} + +END { + print FILE +} +EOF +} + +# Convert an unversioned package name into a .deb package URL +# +# $1: Package name without version information (e.g. libc6-dev) +# $2: Ubuntu mirror base URL +# +get_ubuntu_package_deb_url () +{ + # The following is an awk command to parse the Packages file and extract + # the filename of a given package. + local BASE="`no_trailing_slash \"$1\"`" + local FILE=`awk -f "$DOWNLOAD_DIR/extract-filename.awk" -v PKG=$1 $DOWNLOAD_DIR/Packages` + if [ -z "$FILE" ]; then + log "Could not find filename for package $1" + exit 1 + fi + echo "$2/ubuntu/$FILE" +} + +# Does the host compiler generate 32-bit machine code? +# If not, add the -m32 flag to the compiler name to ensure this. +# +compute_host_flags () +{ + HOST_CC=${CC:-gcc} + HOST_CXX=${CXX-g++} + if [ -n "$USE_CCACHE" ]; then + echo -n "Checking for ccache..." + find_program CMD_CCACHE ccache + if [ -n "$CMD_CCACHE" ] ; then + echo "$HOST_CC" | tr ' ' '\n' | grep -q -e "ccache" + if [ $? = 0 ] ; then + echo "yes (ignored)" + else + echo "yes" + HOST_CC="ccache $HOST_CC" + HOST_CXX="ccache $HOST_CXX" + fi + else + echo "no" + fi + fi + echo -n "Checking compiler bitness... " + cat > "$BUILD_DIR"/conftest.c << EOF +#include <stdio.h> +int main(void) { + printf("%d\n",sizeof(void*)*8); + return 0; +} +EOF + $HOST_CC -o "$BUILD_DIR"/conftest "$BUILD_DIR"/conftest.c > "$BUILD_DIR"/conftest.log 2>&1 + if [ $? != 0 ] ; then + echo "Could not compile test program!!" + echo "Error log is:" + cat "$BUILD_DIR"/conftest.log + rm "$BUID_DIR"/conftest.log + panic "Need a working build toolchain!" + fi + HOST_CC_BITS=$("$BUILD_DIR"/conftest) + echo -n "$HOST_CC_BITS" + case $HOST_CC_BITS in + 32) # Nothing to do + ;; + 64) # Do we need to force 32-bits + if [ "$FORCE_32" ]; then + echo " (forcing generation of 32-bit binaries)" + HOST_CC=$HOST_CC" -m32" + HOST_CXX=$HOST_CXX" -m32" + fi + ;; + *) + panic "Unknown bitness (32 or 64 expected) !!" + esac + echo "" + echo "Using build C compiler: $HOST_CC" + echo "Using build C++ compiler: $HOST_CXX" + echo "GCC target name: $GCC_TARGET" + echo "GMP target name: $GMP_TARGET" + echo "GMP ABI: $GMP_ABI" + export CC="$HOST_CC" + export CXX="$HOST_CXX" +} + +compute_host_flags + +# Return the value of a given named variable +# $1: variable name +# +# example: +# FOO=BAR +# BAR=ZOO +# echo `var_value $FOO` +# will print 'ZOO' +# +var_value () +{ + eval echo \$$1 +} + +var_list_append () +{ + local VARNAME=$1 + local VARVAL=`var_value $VARNAME` + shift + if [ -z "$VARVAL" ] ; then + eval $VARNAME=\"$@\" + else + eval $VARNAME=\"$VARVAL $@\" + fi +} + +var_list_prepend () +{ + local VARNAME=$1 + local VARVAL=`var_value $VARNAME` + shift + if [ -z "$VARVAL" ] ; then + eval $VARNAME=\"$@\" + else + eval $VARNAME=\"$@ $VARVAL\" + fi +} + +_list_first () +{ + echo $1 +} + +_list_rest () +{ + shift + echo "$@" +} + +_list_reverse () +{ + local I1 I2 I3 I4 I5 I6 I7 I8 I9 REST RET + I1=$1; I2=$2; I3=$3; I4=$I4; I5=$I5; I6=$I6; I7=$I7; I8=$I8; I9=$I9 + shift 9 + RET=$I9${I8:+" "}$I8${I7:+" "}$I7${I6:+" "}$I6${I5:+" "}$I5${I4:+" "}$I4${I3:+" "}$I3${I2:+" "}$I2${I1:+" "}$I1 + REST="$*" + if [ "$REST" ]; then + RET=$(_list_reverse $REST)$RET + fi + echo "$RET" +} + +var_list_pop_first () +{ + local VARNAME=$1 + local VARVAL=`var_value $VARNAME` + local FIRST=`_list_first $VARVAL` + eval $VARNAME=\"`_list_rest $VARVAL`\" + echo "$FIRST" +} + +_list_first () +{ + echo $1 +} + +_list_rest () +{ + shift + echo "$@" +} + +var_list_first () +{ + local VAL=`var_value $1` + _list_first $VAL +} + +var_list_rest () +{ + local VAL=`var_value $1` + _list_rest $VAL +} + +ALL_TASKS= + +# Define a new task for this build script +# $1: Task name (e.g. build_stuff) +# $2: Task description +# $3: Optional: command name (will be cmd_$1 by default) +# +task_define () +{ + local TASK="$1" + local DESCR="$2" + local COMMAND="${3:-cmd_$1}" + + var_list_append ALL_TASKS $TASK + task_set $TASK name "$TASK" + task_set $TASK descr "$DESCR" + task_set $TASK cmd "$COMMAND" + task_set $TASK deps "" +} + +# Variant of task define for dual tasks +# This really defines two tasks named '<task>_1' and '<task>_2" +# $1: Task base name +# $2: Task description +# $3: Optional: command name (will be cmd_$1 by default) +task2_define () +{ + local TASK="$1" + local DESCR="$2" + local COMMAND="${3:-cmd_$1}" + + task_define "${TASK}_1" "$DESCR 1/2" "phase_1 $COMMAND" + task_define "${TASK}_2" "$DESCR 2/2" "phase_2 $COMMAND" +} + +task_set () +{ + local TASK="$1" + local FIELD="$2" + shift; shift; + eval TASK_${TASK}__${FIELD}=\"$@\" +} + +task_get () +{ + var_value TASK_$1__$2 +} + +# return the list of dependencies for a given task +task_get_deps () +{ + task_get $1 deps +} + +task_get_cmd () +{ + task_get $1 cmd +} + +task_get_descr () +{ + task_get $1 descr +} + +# $1: task name +# $2+: other tasks this task depends on. +task_depends () +{ + local TASK="$1" + shift; + var_list_append TASK_${TASK}__deps $@ +} + +# $1: dual task name +# $2+: other non-dual tasks this dual task depends on +task2_depends1 () +{ + local TASK="$1" + shift + var_list_append TASK_${TASK}_1__deps $@ + var_list_append TASK_${TASK}_2__deps $@ +} + +# $1: dual task name +# $2+: other dual tasks this dual task depends on +task2_depends2 () +{ + local TASK="$1" + local DEP + shift + for DEP; do + var_list_append TASK_${TASK}_1__deps ${DEP}_1 + var_list_append TASK_${TASK}_2__deps ${DEP}_2 + done +} + +task_dump () +{ + local TASK + for TASK in $ALL_TASKS; do + local DEPS="`task_get_deps $TASK`" + local CMD="`task_get_cmd $TASK`" + local DESCR="`task_get_descr $TASK`" + echo "TASK $TASK: $DESCR: $CMD" + echo "> $DEPS" + done +} + +task_visit () +{ + task_set $TASK visit 1 +} + +task_unvisit () +{ + task_set $TASK visit 0 +} + +task_is_visited () +{ + [ `task_get $TASK visit` = 1 ] +} + +task_queue_reset () +{ + TASK_QUEUE= +} + +task_queue_push () +{ + var_list_append TASK_QUEUE $1 +} + +task_queue_pop () +{ + local FIRST=`var_list_first TASK_QUEUE` + TASK_QUEUE=`var_list_rest TASK_QUEUE` +} + +do_all_tasks () +{ + local TASK + local TASK_LIST= + task_queue_reset + # Clear visit flags + for TASK in $ALL_TASKS; do + task_unvisit $TASK + done + task_queue_push $1 + while [ -n "$TASK_QUEUE" ] ; do + TASK=`task_queue_pop` + if task_is_visited $TASK; then + continue + fi + # Prepend the task to the list if its timestamp is not set + if stamp_check $TASK; then + var_list_prepend TASK_LIST $TASK + fi + # Add all dependencies to the work-queue + local SUBTASK + for SUBTASK in `task_get_deps $TASK`; do + task_queue_push $SUBTASK + done + task_visit $TASK + done + + # Now, TASK_LIST contains the +} + + +# Return the first item of a space-separated list +list_first () { + set -- "$@" + echo "$1" +} + +# Append an item to a given list +list_append () { + local ITEM=$1 + shift; + echo $@${@:+" "}$1 +} + +# Return the second-to-last items of a space-separated list +list_rest () { + set -- "$@" + shift + echo "$@" +} + +# Reverse a space-separated list +list_reverse () +{ + set -- "$@" + local I1 I2 I3 I4 I5 I6 I7 I8 I9 REST RET + I1=$1; I2=$2; I3=$3; I4=$4; I5=$5; I6=$6; I7=$7; I8=$8; I9=$9 + shift; shift; shift; shift; shift; shift; shift; shift; shift; + RET=$I9${I9:+" "}$I8${I8:+" "}$I7${I7:+" "}$I6${I6:+" "}$I5${I5:+" "}$I4${I4:+" "}$I3${I3:+" "}$I2${I2:+" "}$I1 + REST="$*" + if [ -n "$REST" ]; then + RET=$(list_reverse $REST)" "$RET + fi + echo "$RET" +} + +# Used to build the list of tasks with a tree post-order traversal, i.e. +# the list starts at the leaves and finishes with the top level task, +# so that if task(A) depends on task(B), then A will always appear _after_ +# B in the result. +# +# $1: space-separated list of tasks to visit +# Out: list of all tasks in post-order +# +task_build_postorder_list () +{ + local TASK + local STACK="$1" + local RET="" + for TASK in $ALL_TASKS; do + stamp_clear $TASK.visit + done + while true; do + # Peek at stack + TASK=$(list_first $STACK) + #echo >&2 "STACK: ($TASK) '$STACK'" + if [ -z "$TASK" ]; then + break + fi + HAS_DEPS= + for DEP in $(task_get_deps $TASK); do + #echo >&2 "CHECK: '$DEP'" + if ! stamp_check $DEP.visit; then + STACK=$DEP" "$STACK + #echo >&2 "PUSH: '$DEP' => '$STACK'" + HAS_DEPS=1 + fi + done + + if [ -z "$HAS_DEPS" ]; then + #echo >&2 "ADD: $TASK -> '$RET'" + STACK=$(list_rest $STACK) + if ! stamp_check $TASK.visit; then + RET=$RET${RET:+" "}$TASK + stamp_set $TASK.visit + fi + fi + done + for TASK in $ALL_TASKS; do + stamp_clear $TASK.visit + done + echo "$RET" +} + +run_task () +{ + # Build the list of tasks, in reverse order (from leafs to last) + local TASKS=$(task_build_postorder_list $1) + # Do all tasks + local TASK DEP DESCR + + # Dump list of tasks: +# echo "ALL TASKS:" +# for TASK in $TASKS; do +# echo " $TASK" +# done + + # Clean timestamps of any tasks whose any of its dependents needs + # to be re-done. + # + for TASK in $TASKS; do + for DEP in $(task_get_deps $TASK); do + if ! stamp_check $DEP; then + #echo "Redo: $TASK due to $DEP" + stamp_clear $TASK + break + fi + done + done + + for TASK in $TASKS; do + DESCR=$(task_get_descr $TASK) + if stamp_check $TASK; then + echo "Skipping: $DESCR" + continue + fi + echo "Running: $DESCR" + if [ "$VERBOSE" -ge 1 ] ; then + (eval $(task_get_cmd $TASK)) + else + (eval $(task_get_cmd $TASK)) >> $TMPLOG 2>&1 + fi + if [ $? != 0 ] ; then + echo "ERROR: Cannot $DESCR" + exit 1 + fi + + stamp_set $TASK + done +} + +# This function is used to clone a source repository either from a given +# git base or a git reference. +# $1: project/subdir name +# $2: path to SOURCES file +toolchain_clone () +{ + local GITFLAGS + GITFLAGS= + if [ "$GIT_REFERENCE" ]; then + GITFLAGS="$GITFLAGS --shared --reference $GIT_REFERENCE/$1" + fi + echo "cleaning up toolchain/$1" + rm -rf $1 + fail_panic "Could not clean $(pwd)/$1" + echo "downloading sources for toolchain/$1" + if [ -d "$GIT_BASE/$1" ]; then + log "cloning $GIT_BASE/$1" + run $GIT_CMD clone $GITFLAGS $GIT_BASE/$1 $1 + else + log "cloning $GITPREFIX/$1.git" + run $GIT_CMD clone $GITFLAGS $GIT_BASE/$1.git $1 + fi + fail_panic "Could not clone $GIT_BASE/$1.git ?" + cd $1 + if [ "$GIT_BRANCH" != "master" ] ; then + log "checking out $GIT_BRANCH branch of $1.git" + run $GIT_CMD checkout -b $GIT_BRANCH origin/$GIT_BRANCH + fail_panic "Could not checkout $1 ?" + fi + # If --git-date is used, or we have a default + if [ -n "$GIT_DATE" ] ; then + REVISION=`git rev-list -n 1 --until="$GIT_DATE" HEAD` + echo "Using sources for date '$GIT_DATE': toolchain/$1 revision $REVISION" + run $GIT_CMD checkout $REVISION + fail_panic "Could not checkout $1 ?" + fi + (printf "%-32s " "toolchain/$1.git: " && git log -1 --format=oneline) >> $2 + cd .. +} + +task_define download_toolchain_sources "Download toolchain sources from $GIT_BASE " +cmd_download_toolchain_sources () +{ + local SUBDIRS="binutils build gcc gdb gold gmp mpfr mpc isl cloog" + (mkdir -p $TOOLCHAIN_SRC_DIR && cd $TOOLCHAIN_SRC_DIR && + # Create a temporary SOURCES file for the toolchain sources only + # It's content will be copied to the final SOURCES file later. + SOURCES_LIST=$TOOLCHAIN_SRC_DIR/SOURCES + rm -f $SOURCES_LIST && touch $SOURCES_LIST + for SUB in $SUBDIRS; do + toolchain_clone $SUB $SOURCES_LIST + done + ) +} + +task_define download_ubuntu_packages_list "Download Ubuntu packages list" +cmd_download_ubuntu_packages_list () +{ + mkdir -p $DOWNLOAD_DIR + get_ubuntu_packages_list "$UBUNTU_MIRROR" "$UBUNTU_RELEASE" + fail_panic "Unable to download packages list, try --ubuntu-mirror=<url> to use another archive mirror" +} + +task_define download_packages "Download Ubuntu packages" +task_depends download_packages download_ubuntu_packages_list +cmd_download_packages () +{ + local PACKAGE + + rm -f $DOWNLOAD_DIR/SOURCES && touch $DOWNLOAD_DIR/SOURCES + for PACKAGE in $UBUNTU_PACKAGES; do + echo "Downloading $PACKAGE" + local PKGURL=`get_ubuntu_package_deb_url $PACKAGE $UBUNTU_MIRROR` + echo "URL: $PKGURL" + download_file_to $PKGURL $DOWNLOAD_DIR + fail_panic "Could not download $PACKAGE" + done + sha1sum $DOWNLOAD_DIR/*.deb | while read LINE; do + PACKAGE=$(basename $(echo $LINE | awk '{ print $2;}')) + SHA1=$(echo $LINE | awk '{ print $1; }') + printf "%-64s %s\n" $PACKAGE $SHA1 >> $DOWNLOAD_DIR/SOURCES + done +} + +task_define build_sysroot "Build sysroot" +task_depends build_sysroot download_packages + +cmd_build_sysroot () +{ + local PACKAGE + for PACKAGE in $UBUNTU_PACKAGES; do + local PKGURL=`get_ubuntu_package_deb_url $PACKAGE $UBUNTU_MIRROR` + local SRC_PKG=$DOWNLOAD_DIR/`basename $PKGURL` + echo "Extracting $SRC_PKG" + dpkg -x $SRC_PKG $ORG_SYSROOT_DIR/ + done +} + +# Now, we need to patch libc.so which is actually a linker script +# referencing /lib and /usr/lib. Do the same for libpthread.so +patch_library () +{ + echo "Patching $1" + sed -i -e "s! /lib/! !g" -e "s! /usr/lib/! !g" $1 +} + +# Used to setup phase 1 the run a command +phase_1 () +{ + PHASE=1 + $@ +} + +# Used to setup phase 2 then run a command +phase_2 () +{ + PHASE=1 + BINPREFIX=$(install_dir)/bin/${GCC_TARGET}- + CC=${BINPREFIX}gcc + CXX=${BINPREFIX}g++ + LD=${BINPREFIX}ld + AR=${BINPREFIX}ar + AS=${BINPREFIX}as + RANLIB=${BINPREFIX}ranlib + STRIP=${BINPREFIX}strip + CC_FOR_TARGET=${BINPREFIX}gcc + export CC CXX LD AR AS RANLIB STRIP CC_FOR_TARGET + PHASE=2 + $@ +} + +# Return the list of all symbolic links in a given directory, excluding +# any links in its sub-directories. +# $1: Sub-directory path. +find_symlinks_in () { + (cd $1 && find . -maxdepth 1 -type l) | sed -e 's|^\./||g' +} + +task2_define copy_sysroot "Fix and copy sysroot" +task2_depends1 copy_sysroot build_sysroot +cmd_copy_sysroot () +{ + local SL + + # Copy the content of $BUILD_DIR/lib to $(sysroot_dir)/usr/lib + copy_directory $ORG_SYSROOT_DIR/lib $(sysroot_dir)/usr/lib + copy_directory $ORG_SYSROOT_DIR/usr/lib $(sysroot_dir)/usr/lib + copy_directory $ORG_SYSROOT_DIR/usr/include $(sysroot_dir)/usr/include + + # We need to fix the symlink like librt.so -> /lib/librt.so.1 + # in $(sysroot_dir)/usr/lib, they should point to librt.so.1 instead now. + SYMLINKS=$(find_symlinks_in $(sysroot_dir)/usr/lib) + cd $(sysroot_dir)/usr/lib + for SL in $SYMLINKS; do + # convert /lib/libfoo.so.<n> into 'libfoo.so.<n>' for the target + local DST=$(readlink $SL 2>/dev/null) + local DST2=${DST##/lib/} + if [ "$DST2" != "$DST" ]; then + echo "Fixing symlink $SL --> $DST" + rm $SL && ln -s $DST2 $SL + fi + done + +# # Also deal with a few direct symlinks that don't use the /lib/ prefix +# # we simply copy them. Useful for libGL.so -> libGL.so.1 for example. +# SYMLINKS=$(find_symlinks_in $(sysroot_dir)/usr/lib) +# cd $(sysroot_dir)/usr/lib +# for SL in $SYMLINKS; do +# # convert /lib/libfoo.so.<n> into 'libfoo.so.<n>' for the target +# local DST=$(readlink $SL 2>/dev/null) +# # convert libfoo.so.<n> into libfoo.so for the source +# local SRC=`echo $DST | sed -e 's!\.[0-9]*$!!g'` +# if [ "$DST" != "$SRC" ]; then +# echo "Copying symlink $SRC --> $DST" +# ln -sf $DST $SRC +# fi +# done + + patch_library $(sysroot_dir)/usr/lib/libc.so + patch_library $(sysroot_dir)/usr/lib/libpthread.so +} + +task_define patch_toolchain_sources "Patch toolchain sources." +task_depends patch_toolchain_sources download_toolchain_sources +cmd_patch_toolchain_sources () +{ + log "PATCHES_DIR = $PATCHES_DIR" + if [ ! -d "$PATCHES_DIR" ]; then + log "$PATCHES_DIR doesn't exist" + return 0 + fi + + local PATCHES=`(cd $PATCHES_DIR && find . -name "*.patch" | sort ) 2> /dev/null` + if [ -z "$PATCHES" ] ; then + log "No patches files in $PATCHES_DIR" + return 0 + fi + + PATCHES=`echo $PATCHES | sed -e s%^\./%%g` + for PATCH in $PATCHES; do + PATCHDIR=`dirname $PATCH` + PATCHNAME=`basename $PATCH` + log "Applying $PATCHNAME into $TOOLCHAIN_SRC_DIR/$PATCHDIR" + (cd $TOOLCHAIN_SRC_DIR/$PATCHDIR && patch -p1 < $PATCHES_DIR/$PATCH) + fail_panic "Patch failure!! Please check your patches directory!" + done + + log "Done patching." +} + +task_define prepare_toolchain_sources "Prepare toolchain sources." +if [ -n "$GIT_BASE" -o -n "$GIT_REFERENCE" ]; then + task_depends prepare_toolchain_sources patch_toolchain_sources +fi +cmd_prepare_toolchain_sources () +{ + return +} + +task2_define configure_binutils "Configure binutils-$BINUTILS_VERSION" +task2_depends1 configure_binutils prepare_toolchain_sources +task2_depends2 configure_binutils copy_sysroot +cmd_configure_binutils () +{ + OUT_DIR=$(build_binutils_dir) + mkdir -p $OUT_DIR && cd $OUT_DIR && + $TOOLCHAIN_SRC_DIR/binutils/binutils-$BINUTILS_VERSION/configure \ + --prefix=$(install_dir) \ + --with-sysroot=$(sysroot_dir) \ + --target=$GCC_TARGET +} + +task2_define build_binutils "Build binutils-$BINUTILS_VERSION" +task2_depends2 build_binutils configure_binutils +cmd_build_binutils () +{ + cd $(build_binutils_dir) && + make $MAKE_FLAGS +} + +task2_define install_binutils "Install binutils-$BINUTILS_VERSION" +task2_depends2 install_binutils build_binutils +cmd_install_binutils () +{ + cd $(build_binutils_dir) && + make install +} + +task2_define extract_gmp "Extract sources for gmp-$GMP_VERSION" +task2_depends1 extract_gmp prepare_toolchain_sources +cmd_extract_gmp () +{ + OUT_DIR=$(build_gmp_dir) + GMP_TARBALL=$TOOLCHAIN_SRC_DIR/gmp/gmp-$GMP_VERSION.tar.bz2 + if [ ! -f "$GMP_TARBALL" ]; then + GMP_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/gmp-$GMP_VERSION.tar.bz2 + if [ ! -f "$GMP_TARBALL" ]; then + panic "Can't find gmp-$GMP_VERSION sources!!" + fi + fi + mkdir -p $OUT_DIR && cd $OUT_DIR && + tar xjf "$GMP_TARBALL" +} + +task2_define configure_gmp "Configure gmp-$GMP_VERSION" +task2_depends2 configure_gmp extract_gmp install_binutils +cmd_configure_gmp () +{ + export ABI=$GMP_ABI && + cd $(build_gmp_dir) && mkdir -p build && cd build && + ../gmp-$GMP_VERSION/configure \ + --prefix=$(install_dir) \ + --host=$GMP_TARGET \ + --with-sysroot=$(install_dir) \ + --disable-shared +} + +task2_define build_gmp "Build gmp-$GMP_VERSION" +task2_depends2 build_gmp configure_gmp +cmd_build_gmp () +{ + export ABI=$GMP_ABI && + cd $(build_gmp_dir)/build && + make $MAKE_FLAGS +} + +task2_define install_gmp "Install gmp-$GMP_VERSION" +task2_depends2 install_gmp build_gmp +cmd_install_gmp () +{ + cd $(build_gmp_dir)/build && + make install +} + +# Third, build mpfr +task2_define extract_mpfr "Extract sources from mpfr-$MPFR_VERSION" +task2_depends1 extract_mpfr prepare_toolchain_sources +cmd_extract_mpfr () +{ + OUT_DIR=$(build_mpfr_dir) + MPFR_TARBALL=$TOOLCHAIN_SRC_DIR/mpfr/mpfr-$MPFR_VERSION.tar.bz2 + if [ ! -f "$MPFR_TARBALL" ]; then + MPFR_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/mpfr-$MPFR_VERSION.tar.bz2 + if [ ! -f "$MPFR_TARBALL" ]; then + panic "Can't find mpfr-$MPFR_VERSION sources!!" + fi + fi + mkdir -p $OUT_DIR && cd $OUT_DIR && + tar xjf "$MPFR_TARBALL" +} + +task2_define configure_mpfr "Configure mpfr-$MPFR_VERSION" +task2_depends2 configure_mpfr extract_mpfr install_gmp +cmd_configure_mpfr () +{ + cd $(build_mpfr_dir) && mkdir -p build && cd build && + run ../mpfr-$MPFR_VERSION/configure \ + --prefix=$(install_dir) \ + --host=$GMP_TARGET \ + --with-gmp=$(install_dir) \ + --with-sysroot=$(sysroot_dir) \ + --disable-shared +} + +task2_define build_mpfr "Build mpfr-$MPFR_VERSION" +task2_depends2 build_mpfr configure_mpfr +cmd_build_mpfr () +{ + cd $(build_mpfr_dir)/build && + run make $MAKE_FLAGS +} + +task2_define install_mpfr "Install mpfr-$MPFR_VERSION" +task2_depends2 install_mpfr build_mpfr +cmd_install_mpfr () +{ + cd $(build_mpfr_dir)/build && + run make install +} + +task2_define extract_mpc "Extract sources for mpc-$MPC_VERSION" +task2_depends1 extract_mpc prepare_toolchain_sources +cmd_extract_mpc () +{ + OUT_DIR=$(build_mpc_dir) + MPC_TARBALL=$TOOLCHAIN_SRC_DIR/mpc/mpc-$MPC_VERSION.tar.gz + if [ ! -f "$MPC_TARBALL" ]; then + MPC_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/mpc-$MPC_VERSION.tar.gz + if [ ! -f "$MPC_TARBALL" ]; then + panic "Can't find mpc-$MPC_VERSION sources!!" + fi + fi + mkdir -p $OUT_DIR && cd $OUT_DIR && + tar xzf "$MPC_TARBALL" +} + +task2_define configure_mpc "Configure mpc-$MPC_VERSION" +task2_depends2 configure_mpc extract_mpc install_mpfr +cmd_configure_mpc () +{ + cd $(build_mpc_dir) && mkdir -p build && cd build && + run ../mpc-$MPC_VERSION/configure \ + --prefix=$(install_dir) \ + --host=$GMP_TARGET \ + --with-gmp=$(install_dir) \ + --with-mpfr=$(install_dir) \ + --disable-shared +} + +task2_define build_mpc "Build mpc-$MPC_VERSION" +task2_depends2 build_mpc configure_mpc +cmd_build_mpc () +{ + cd $(build_mpc_dir)/build && + run make $MAKE_FLAGS +} + +task2_define install_mpc "Install mpc-$MPC_VERSION" +task2_depends2 install_mpc build_mpc +cmd_install_mpc () +{ + cd $(build_mpc_dir)/build && + run make install +} + +task2_define extract_isl "Extract sources for isl-$ISL_VERSION" +task2_depends2 extract_isl prepare_toolchain_sources +cmd_extract_isl () +{ + OUT_DIR=$(build_isl_dir) + ISL_TARBALL=$TOOLCHAIN_SRC_DIR/isl/isl-$ISL_VERSION.tar.bz2 + if [ ! -f "$ISL_TARBALL" ]; then + panic "Can't find isl-$ISL_VERSION sources!!" + fi + mkdir -p $OUT_DIR && cd $OUT_DIR && + tar xf "$ISL_TARBALL" +} + +task2_define configure_isl "Configuring isl-$ISL_VERSION" +task2_depends2 configure_isl extract_isl install_gmp +cmd_configure_isl () +{ + cd $(build_isl_dir) && mkdir -p build && cd build && + run ../isl-$ISL_VERSION/configure \ + --prefix=$(install_dir) \ + --host=$GMP_TARGET \ + --with-gmp-prefix=$(install_dir) \ + --with-sysroot=$(sysroot_dir) \ + --disable-shared +} + +task2_define build_isl "Building isl-$ISL_VERSION" +task2_depends2 build_isl configure_isl +cmd_build_isl () +{ + cd $(build_isl_dir)/build && + run make $MAKE_FLAGS +} + +task2_define install_isl "Installing isl-$ISL_VERSION" +task2_depends2 install_isl build_isl +cmd_install_isl () +{ + cd $(build_isl_dir)/build && + make install +} + +# task2_define extract_cloog "Extract sources for Cloog-$CLOOG_VERSION" +# task2_depends2 extract_cloog prepare_toolchain_sources +# cmd_extract_cloog () +# { +# OUT_DIR=$(build_cloog_dir) +# CLOOG_TARBALL=$TOOLCHAIN_SRC_DIR/cloog/cloog-$CLOOG_VERSION.tar.gz +# if [ ! -f "$CLOOG_TARBALL" ]; then +# CLOOG_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/cloog-$CLOOG_VERSION.tar.gz +# if [ ! -f "$CLOOG_TARBALL" ]; then +# panic "Can't find cloog-$CLOOG_VERSION sources!!" +# fi +# fi +# mkdir -p $OUT_DIR && cd $OUT_DIR && +# tar xzf "$CLOOG_TARBALL" +# } +# +task2_define configure_cloog "Configure Cloog-$CLOOG_VERSION" +task2_depends2 configure_cloog prepare_toolchain_sources install_gmp install_isl +cmd_configure_cloog () { + mkdir -p $(build_cloog_dir)/build && cd $(build_cloog_dir)/build && + run $TOOLCHAIN_SRC_DIR/cloog/cloog-$CLOOG_VERSION/configure \ + --prefix=$(install_dir) \ + --host=$GMP_TARGET \ + --with-gmp-prefix=$(install_dir) \ + --with-sysroot=$(sysroot_dir) \ + --disable-shared +} + +task2_define build_cloog "Building Cloog-$CLOOG_VERSION" +task2_depends2 build_cloog configure_cloog +cmd_build_cloog () +{ + cd $(build_cloog_dir)/build && + run make $MAKE_FLAGS +} + +task2_define install_cloog "Installing Cloog-$CLOOG_VERSION" +task2_depends2 install_cloog build_cloog +cmd_install_cloog () +{ + cd $(build_cloog_dir)/build && + run make install +} + +# Fourth, the compiler itself +task2_define configure_gcc "Configure gcc-$GCC_VERSION" +task2_depends1 configure_gcc prepare_toolchain_sources +task2_depends2 configure_gcc install_binutils install_gmp install_mpfr install_mpc install_cloog +cmd_configure_gcc () +{ + OUT_DIR=$(build_gcc_dir) + mkdir -p $OUT_DIR && cd $OUT_DIR && + export PATH=$(install_dir)/bin:$OLD_PATH && + export CC=$HOST_CC && + export CC_FOR_TARGET="$HOST_CC" && + export LD_LIBRARY_PATH=$(install_dir)/lib:$OLD_LD_LIBRARY_PATH && + export LDFLAGS="-L$(install_dir)/lib" && + run $TOOLCHAIN_SRC_DIR/gcc/gcc-$GCC_VERSION/configure \ + --prefix=$(install_dir) \ + --with-sysroot=$(sysroot_dir) \ + --disable-nls \ + --with-gmp=$(install_dir) \ + --with-mpfr=$(install_dir) \ + --with-mpc=$(install_dir) \ + --with-cloog=$(install_dir) \ + --target=$GCC_TARGET \ + --disable-plugin \ + --disable-docs \ + --disable-multilib \ + --disable-bootstrap \ + --disable-libgomp \ + --disable-libmudflap \ + --disable-libquadmath \ + --enable-target-optspace \ + --enable-gold=default \ + --enable-languages=c,c++ +} + +task2_define build_gcc "Build gcc-$GCC_VERSION" +task2_depends2 build_gcc configure_gcc +cmd_build_gcc () +{ + export PATH=$(install_dir)/bin:$OLD_PATH && + export LD_LIBRARY_PATH=$(install_dir)/lib:$OLD_LD_LIBRARY_PATH && + cd $(build_gcc_dir) && + make $MAKE_FLAGS +} + +task2_define install_gcc "Install gcc-$GCC_VERSION" +task2_depends2 install_gcc build_gcc +cmd_install_gcc () +{ + export PATH=$(install_dir)/bin:$OLD_PATH && + export LD_LIBRARY_PATH=$(install_dir)/lib:$OLD_LD_LIBRARY_PATH && + cd $(build_gcc_dir) && + make install +} + +task2_define cleanup_toolchain "Cleanup toolchain" +task2_depends2 cleanup_toolchain install_gcc +cmd_cleanup_toolchain () +{ + # Remove un-needed directories and files + rm -rf $(install_dir)/share + rm -rf $(install_dir)/man + rm -rf $(install_dir)/info + rm -rf $(install_dir)/lib32 + rm -rf $(install_dir)/lib64 + rm -rf $(install_dir)/libexec/*/*/install-tools + #rm -rf $(install_dir)/$GCC_TARGET/bin + + (strip $(install_dir)/bin/*) + (strip $(install_dir)/libexec/gcc/$GCC_TARGET/*/*) + true +} + +task2_define package_toolchain "Package final toolchain" +task2_depends2 package_toolchain cleanup_toolchain +cmd_package_toolchain () +{ + # Copy this script to the install directory + cp -f $0 $(install_dir) + fail_panic "Could not copy build script to install directory" + + if [ -d "$PATCHES_DIR" ]; then + # Copy patches to the install directory + cp -rf "$PATCHES_DIR" $(install_dir) + fail_panic "Could not copy patch directory to install directory" + fi + + # Copy the SOURCES file as well + cp $DOWNLOAD_DIR/SOURCES $(install_dir)/PACKAGE_SOURCES && + cp $TOOLCHAIN_SRC_DIR/SOURCES $(install_dir)/TOOLCHAIN_SOURCES + fail_panic "Could not copy SOURCES files to install directory" + + # Package everything + pack_archive $TOOLCHAIN_ARCHIVE "`dirname $(install_dir)`" "`basename $(install_dir)`" +} + +task2_define install_toolchain "Install final toolchain" +task2_depends2 install_toolchain cleanup_toolchain +cmd_install_toolchain () +{ + copy_directory "$(install_dir)" "$PREFIX_DIR/$TOOLCHAIN_NAME" + cp -f $0 "$PREFIX_DIR/$TOOLCHAIN_NAME/" +} + +# Make sure that the second toolchain depends on the first one +task_depends configure_binutils_2 install_gcc_1 + +if [ "$ONLY_SYSROOT" = "yes" ]; then + MAIN_TASK=copy_sysroot + COMPLETION_TEXT="Done, see sysroot files in $(sysroot_dir)" +elif [ -n "$PREFIX_DIR" ]; then + if [ -z "$BOOTSTRAP" ]; then + MAIN_TASK=install_toolchain_1 + else + MAIN_TASK=install_toolchain_2 + fi + COMPLETION_TEXT="Done, see $PREFIX_DIR/$TOOLCHAIN_NAME" +else + if [ -z "$BOOTSTRAP" ]; then + MAIN_TASK=package_toolchain_1 + else + MAIN_TASK=package_toolchain_2 + fi + COMPLETION_TEXT="Done, see $TOOLCHAIN_ARCHIVE" +fi + +if [ "$LIST_TASKS" ]; then + task_dump +else + run_task $MAIN_TASK + echo "$COMPLETION_TEXT" +fi |