Home | History | Annotate | Download | only in x86_64-linux-glibc2.11-4.8
      1 #!/bin/bash
      2 #
      3 # Copyright (C) 2010 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 
     18 # This script is used to rebuild the Linux 32-bit cross-toolchain
     19 # that allows you to generate 32-bit binaries that target Ubuntu 8.04
     20 # (a.k.a. Hardy Heron) instead of the host system (which usually is 10.04,
     21 # a.k.a. Lucid Lynx)
     22 #
     23 # Use --help for complete usage information.
     24 #
     25 # WARNING: At this time, the generated toolchain binaries will *not* run
     26 #          with GLibc 2.11, only the machine code it generates.
     27 #
     28 
     29 PROGNAME="`basename \"$0\"`"
     30 PATCHES_DIR="$( cd "$( dirname "$0" )" && pwd )/toolchain-patches"
     31 
     32 ###########################################################################
     33 ###########################################################################
     34 #####
     35 #####  C O N F I G U R A T I O N
     36 #####
     37 ###########################################################################
     38 ###########################################################################
     39 
     40 panic ()
     41 {
     42     echo "ERROR: $@"
     43     exit 1
     44 }
     45 
     46 fail_panic ()
     47 {
     48     if [ $? != 0 ] ; then
     49         echo "ERROR: $@"
     50         exit 1
     51     fi
     52 }
     53 
     54 
     55 # We only support running this script on Linux
     56 OS=$(uname -s)
     57 if [ "$OS" != Linux ]; then
     58     panic "This script can only run on Linux machines!"
     59 fi
     60 
     61 UBUNTU_ARCHS="i386 amd64"
     62 
     63 # Used to set the host bitness of the generted toolchain binaries
     64 # First call with the build machine's bitness, and later with 32
     65 # if --32-bits option is used.
     66 # $1: 32 or 64
     67 set_host_bits ()
     68 {
     69     HOST_BITS=$1
     70     GMP_ABI=$1
     71     case $1 in
     72         32)
     73             HOST_ARCH=i686
     74             GCC_TARGET=i686-linux
     75             GMP_TARGET=i386-linux
     76             ;;
     77         64)
     78             HOST_ARCH=x86_64
     79             GCC_TARGET=x86_64-linux
     80             GMP_TARGET=x86_64-linux
     81             ;;
     82         *)
     83             panic "Invalid host bitness (32 or 64 expected): $1"
     84     esac
     85 }
     86 
     87 # Determine build machine bitness
     88 BUILD_ARCH=$(uname -m)
     89 case "$BUILD_ARCH" in
     90     x86_64|amd64)
     91         BUILD_BITS=64
     92         BUILD_ARCH=x86_64
     93         BUILD_GCC_TARGET=x86_64-linux
     94         set_host_bits 64
     95         ;;
     96     i?86)
     97         BUILD_BITS=32
     98         BUILD_ARCH=i686
     99         BUILD_GCC_TARGET=i686-linux
    100         set_host_bits 32
    101         ;;
    102     *)
    103         panic "Unknown build CPU architecture: $BUILD_ARCH"
    104 esac
    105 
    106 # Versions of various toolchain components, do not touch unless you know
    107 # what you're doing!
    108 
    109 BINUTILS_VERSION=2.23
    110 GMP_VERSION=5.0.5
    111 MPFR_VERSION=3.1.1
    112 MPC_VERSION=1.0.1
    113 GCC_VERSION=4.6
    114 CLOOG_VERSION=0.18.0
    115 ISL_VERSION=0.11.1
    116 
    117 GLIBC_VERSION=2.11
    118 
    119 GIT_CMD=git
    120 GIT_DATE=
    121 GIT_BRANCH=master
    122 GIT_REFERENCE=
    123 GIT_BASE=
    124 GIT_BASE_DEFAULT=https://android.googlesource.com/toolchain
    125 
    126 # Location where we're going to install the toolchain during the build
    127 # This will depend on the phase of the build.
    128 install_dir () { echo "$WORK_DIR/$PHASE/$TOOLCHAIN_NAME"; }
    129 
    130 # Given an input string that looks like <major>.<minor>.<patch>
    131 # Return <major>.<minor> only.
    132 major_minor_only () {
    133    local MAJOR=$(echo -n "$1" | cut -f1 -d.)
    134    local MINOR=$(echo -n "$1" | cut -f2 -d.)
    135    echo "$MAJOR.$MINOR"
    136 }
    137 
    138 # Location where we're going to install the final binaries
    139 # If empty, TOOLCHAIN_ARCHIVE will be generated
    140 PREFIX_DIR=
    141 
    142 # Location of the final sysroot. This must be a sub-directory of INSTALL_DIR
    143 # to ensure that the toolchain binaries are properly relocatable (i.e. can
    144 # be used when moved to another directory).
    145 sysroot_dir () { echo "$(install_dir)/sysroot"; }
    146 
    147 # Try to parallelize the build for faster performance.
    148 JOBS=$(cat /proc/cpuinfo | grep -c processor)
    149 
    150 # The base URL of the Ubuntu mirror we're going to use.
    151 UBUNTU_MIRROR=http://old-releases.ubuntu.com/
    152 
    153 # Ubuntu release name we want packages from. Can be a name or a number
    154 # (i.e. "lucid" or "10.04")
    155 UBUNTU_RELEASE=lucid
    156 
    157 
    158 # The list of packages we need to download from the Ubuntu servers and
    159 # extract into the original sysroot
    160 #
    161 # Call add_ubuntu_package <package-name> to add a package to the list,
    162 # which will be processed later.
    163 #
    164 UBUNTU_PACKAGES=
    165 
    166 add_ubuntu_package ()
    167 {
    168     UBUNTU_PACKAGES="$UBUNTU_PACKAGES $@"
    169 }
    170 
    171 # The package files containing kernel headers for Hardy and the C
    172 # library headers and binaries
    173 add_ubuntu_package \
    174     linux-libc-dev \
    175     libc6 \
    176     libc6-dev \
    177     libcap2 \
    178     libcap-dev \
    179     libattr1 \
    180     libattr1-dev \
    181     libacl1 \
    182     libacl1-dev \
    183 
    184 # The X11 headers and binaries (for the emulator)
    185 add_ubuntu_package \
    186     libx11-6 \
    187     libx11-dev \
    188     libxau6 \
    189     libxcb1-dev \
    190     libxdmcp6 \
    191     libxext-dev \
    192     libxfixes-dev \
    193     libxi-dev \
    194     x11proto-core-dev \
    195     x11proto-fixes-dev \
    196     x11proto-xext-dev \
    197     x11proto-input-dev \
    198     x11proto-kb-dev
    199 
    200 # The OpenGL-related headers and libraries (for GLES emulation)
    201 add_ubuntu_package \
    202     mesa-common-dev \
    203     libgl1-mesa-dev \
    204     libgl1-mesa-glx \
    205     libxxf86vm1 \
    206     libxext6 \
    207     libxdamage1 \
    208     libxfixes3 \
    209     libdrm2
    210 
    211 # Audio libraries (required by the emulator)
    212 add_ubuntu_package \
    213     libasound2 \
    214     libasound2-dev \
    215     libesd0-dev \
    216     libaudiofile-dev \
    217     libpulse0 \
    218     libpulse-dev
    219 
    220 # ZLib and others.
    221 add_ubuntu_package \
    222     zlib1g \
    223     zlib1g-dev \
    224     libncurses5 \
    225     libncurses5-dev
    226 
    227 
    228 
    229 ###########################################################################
    230 ###########################################################################
    231 #####
    232 #####  E N D   O F   C O N F I G U R A T I O N
    233 #####
    234 ###########################################################################
    235 ###########################################################################
    236 
    237 # Parse all options
    238 OPTION_HELP=no
    239 VERBOSE=0
    240 FORCE=no
    241 ONLY_SYSROOT=no
    242 ONLY_TOOLCHAIN_DIR=
    243 BOOTSTRAP=
    244 PARAMETERS=
    245 FORCE_32=
    246 LIST_TASKS=
    247 
    248 for opt do
    249   optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
    250   case $opt in
    251   --help|-h|-\?) OPTION_HELP=yes
    252   ;;
    253   --verbose) VERBOSE=$(( $VERBOSE + 1 ))
    254   ;;
    255   --force) FORCE="yes"
    256   ;;
    257   --32-bits) FORCE_32=true
    258   ;;
    259   --ubuntu-mirror=*) UBUNTU_MIRROR=$optarg
    260   ;;
    261   --ubuntu-release=*) UBUNTU_RELEASE=$optarg
    262   ;;
    263   --prefix=*) PREFIX_DIR=$optarg
    264   ;;
    265   --work-dir=*) WORK_DIR=$optarg
    266   ;;
    267   --gcc-version=*) GCC_VERSION=$optarg
    268   ;;
    269   --binutils-version=*) BINUTILS_VERSION=$optarg
    270   ;;
    271   --gmp-version=*) GMP_VERSION=$optarg
    272   ;;
    273   --mpfr-version=*) MPFR_VERSION=$optarg
    274   ;;
    275   --mpc-version=*) MPC_VERSION=$optarg
    276   ;;
    277   --isl-version=*) ISL_VERSION=$optarg
    278   ;;
    279   --cloog-version=*) CLOOG_VERSION=$oparg
    280   ;;
    281   --git=*) GIT_CMD=$optarg
    282   ;;
    283   --git-date=*) GIT_DATE=$optarg
    284   ;;
    285   --git-branch=*) GIT_BRANCH=$optarg
    286   ;;
    287   --git-base=*) GIT_BASE=$optarg
    288   ;;
    289   --git-reference=*) GIT_REFERENCE=$optarg
    290   ;;
    291   --out-dir=*) OPTION_OUT_DIR=$optarg
    292   ;;
    293   --cc=*) OPTION_CC=$optarg
    294   ;;
    295   --jobs=*) JOBS=$optarg
    296   ;;
    297   -j*) JOBS=${opt#-j}
    298   ;;
    299   --only-sysroot) ONLY_SYSROOT=yes
    300   ;;
    301   --bootstrap) BOOTSTRAP=yes
    302   ;;
    303   --list-tasks) LIST_TASKS=yes
    304   ;;
    305   -*)
    306     echo "unknown option '$opt', use --help"
    307     exit 1
    308     ;;
    309   *)
    310     if [ -z "$PARAMETERS" ]; then
    311         PARAMETERS=$opt
    312     else
    313         PARAMETERS="$PARAMETERS $opt"
    314     fi
    315   esac
    316 done
    317 
    318 if [ "$OPTION_HELP" = "yes" ]; then
    319     cat << EOF
    320 
    321 Usage: $PROGNAME [options] [<path-to-toolchain-sources>]
    322 
    323 This script is used to rebuild a custom Linux host toolchain that targets
    324 GLibc $GLIBC_VERSION or higher. The machine code generated by this toolchain
    325 will run properly on Ubuntu $UBUNTU_RELEASE or higher.
    326 
    327 If you're running on a 32-bit system, it will generate a 32-bit toolchain.
    328 If you're running on a 64-bit system, it will generate a 64-bit toolchain
    329 unless you use the --32-bits option.
    330 
    331 You can provide the path to a local copy of the toolchain sources repository
    332 as a first parameter. If you don't, the sources will be downloaded and
    333 extracted automatically into your work directory.
    334 
    335 Note that this script will download various binary packages from Ubuntu
    336 servers in order to prepare a compatible "sysroot".
    337 
    338 By default, it generates a package archive ($TOOLCHAIN_ARCHIVE) but you can,
    339 as an alternative, ask for direct installation with --prefix=<path>
    340 
    341 Use the bootstrap option to re-generate the toolchain with itself. This is
    342 useful if you want to ensure that the generated compiler binaries will work
    343 properly on Ubuntu 8.04 or higher. By default, they will only run on systems
    344 that match your build system's C library ABI, or higher.
    345 
    346 Options: [defaults in brackets after descriptions]
    347 EOF
    348     echo "Standard options:"
    349     echo "  --help                        Print this message"
    350     echo "  --force                       Force-rebuild everything"
    351     echo "  --prefix=PATH                 Installation path [$PREFIX_DIR]"
    352     echo "  --ubuntu-mirror=URL           Ubuntu mirror URL [$UBUNTU_MIRROR]"
    353     echo "  --ubuntu-release=NAME         Ubuntu release name [$UBUNTU_RELEASE]"
    354     echo "  --work-dir=PATH               Temporary work directory [/tmp/gcc.<random>]"
    355     echo "  --only-sysroot                Only download and build sysroot packages"
    356     echo "  --verbose                     Verbose output. Can be used twice."
    357     echo "  --binutils-version=VERSION    Binutils version number [$BINUTILS_VERSION]"
    358     echo "  --gcc-version=VERSION         GCC version number [$GCC_VERSION]"
    359     echo "  --gmp-version=VERSION         GMP version number [$GMP_VERSION]"
    360     echo "  --mpfr-version=VERSION        MPFR version numner [$MPFR_VERSION]"
    361     echo "  --mpc-version=VERSION         MPC version number [$MPC_VERSION]"
    362     echo "  --isl-version=VERSION         ISL version number [$ISL_VERSION]"
    363     echo "  --cloog-version=VERSION       Cloog version number [$CLOOG_VERSION]"
    364     echo "  --jobs=COUNT                  Run COUNT build jobs in parallel [$JOBS]"
    365     echo "  -j<COUNT>                     Same as --jobs=COUNT."
    366     echo "  --git=<cmd>                   Use this version of the git tool [$GIT_CMD]"
    367     echo "  --git-date=<date>             Specify specific git date when download sources [none]"
    368     echo "  --git-branch=<name>           Specify which branch to use when downloading the sources [$GIT_BRANCH]"
    369     echo "  --git-reference=<path>        Use a git reference repository"
    370     echo "  --git-base=<url>              Use this git repository base [$GIT_BASE]"
    371     echo "  --bootstrap                   Bootstrap toolchain (i.e. compile it with itself)"
    372     echo "  --32-bits                     Generate 32-bit toolchain on 64-bit build system."
    373     echo ""
    374     exit 1
    375 fi
    376 
    377 if [ "$FORCE_32" ]; then
    378     if [ "$BUILD_BITS" = 64 ]; then
    379         set_host_bits 32
    380     else
    381        echo "Warning: --32-bits option ignored on 32-bit build machine."
    382     fi
    383 fi
    384 
    385 # Determine root working directory for our script
    386 if [ -z "$WORK_DIR" ]; then
    387     WORK_DIR=$(mktemp -d /tmp/$USER-gcc-$HOST_BITS-XXXXXX)
    388     WORK_DIR_CLEANUP=true
    389 else
    390     mkdir -p "$WORK_DIR"
    391     fail_panic "Could not create directory: $WORK_DIR"
    392     WORK_DIR_CLEANUP=false
    393 fi
    394 
    395 if [ -z "$PARAMETERS" ] ; then
    396     if [ -n "$GIT_REFERENCE" ] ; then
    397         if [ ! -d "$GIT_REFERENCE" -o ! -d "$GIT_REFERENCE/build" ]; then
    398             echo "ERROR: Invalid reference repository directory path: $GIT_REFERENCE"
    399             exit 1
    400         fi
    401         if [ -n "$GIT_BASE" ]; then
    402             echo "Using git clone reference: $GIT_REFERENCE"
    403         else
    404             # If we have a reference without a base, use it as a download base instead.
    405             GIT_BASE=$GIT_REFERENCE
    406             GIT_REFERENCE=
    407             echo "Using git clone base: $GIT_BASE"
    408         fi
    409     elif [ -z "$GIT_BASE" ]; then
    410         GIT_BASE=$GIT_BASE_DEFAULT
    411         echo "Auto-config: --git-base=$GIT_BASE"
    412     fi
    413 
    414     # Location where we will download the toolchain sources
    415     TOOLCHAIN_SRC_DIR=$WORK_DIR/toolchain-src
    416 else
    417     set_parameters () {
    418         TOOLCHAIN_SRC_DIR="$1"
    419         if [ ! -d "$TOOLCHAIN_SRC_DIR" ]; then
    420             echo "ERROR: Not a directory: $1"
    421             exit 1
    422         fi
    423         if [ ! -d "$TOOLCHAIN_SRC_DIR/build" ]; then
    424             echo "ERROR: Missing directory: $1/build"
    425             exit 1
    426         fi
    427     }
    428 
    429     set_parameters $PARAMETERS
    430 fi
    431 
    432 # Location of original sysroot. This is where we're going to extract all
    433 # binary Ubuntu packages.
    434 ORG_SYSROOT_DIR=$WORK_DIR/sysroot
    435 
    436 # Name of the final generated toolchain
    437 TOOLCHAIN_NAME=$GCC_TARGET-glibc$GLIBC_VERSION-$(major_minor_only $GCC_VERSION)
    438 
    439 # Name of the final toolchain binary tarball that this script will create
    440 TOOLCHAIN_ARCHIVE=/tmp/$TOOLCHAIN_NAME.tar.bz2
    441 
    442 # A file that will contain details about all the sources used to generate
    443 # the final toolchain. This includes both SHA-1 for toolchain git repositories
    444 # and SHA-1 hashes for downloaded Ubuntu packages.
    445 SOURCES_LIST=$WORK_DIR/SOURCES
    446 
    447 # Determine Make flags
    448 MAKE_FLAGS="-j$JOBS"
    449 
    450 # Create the work directory
    451 mkdir -p "$WORK_DIR"
    452 mkdir -p "$TOOLCHAIN_SRC_DIR"
    453 
    454 # Location where we download packages from the Ubuntu servers
    455 DOWNLOAD_DIR=$WORK_DIR/download
    456 
    457 # Empty the SOURCES file
    458 rm -f "$SOURCES_LIST" && touch "$SOURCES_LIST"
    459 
    460 
    461 if [ "$VERBOSE" -ge 1 ] ; then
    462     run () {
    463         echo "## COMMAND: $@"
    464         $@
    465     }
    466     log () {
    467         echo "$@"
    468     }
    469     if [ "$VERBOSE" -ge 2 ] ; then
    470         log2 () {
    471             echo "$@"
    472         }
    473     else
    474         log2 () {
    475             return
    476         }
    477     fi
    478 else
    479     run () {
    480         "$@" >>$TMPLOG 2>&1
    481     }
    482     log () {
    483         return
    484     }
    485     log2 () {
    486         return
    487     }
    488 fi
    489 
    490 # Sanitize a path list, we want to remove empty sub-dirs and
    491 # leading/trailing columns.
    492 sanitize_path_list ()
    493 {
    494   local RESULT
    495   RESULT=$(printf "%s\n" "$*" | tr ':' '\n' | awk '$1 != "" && $1 != "." { print $0; }' | tr '\n' ':')
    496   printf "%s" ${RESULT%:}
    497 }
    498 
    499 PATH=$(sanitize_path_list $PATH)
    500 LD_LIBRARY_PATH=$(sanitize_path_list $LD_LIBRARY_PATH)
    501 
    502 BUILD_DIR=$WORK_DIR/build
    503 mkdir -p $BUILD_DIR
    504 
    505 TMPLOG=$BUILD_DIR/build.log
    506 rm -rf $TMPLOG && touch $TMPLOG
    507 
    508 build_dir_for () { echo "$BUILD_DIR/$PHASE/$1"; }
    509 
    510 TIMESTAMPS_DIR=$BUILD_DIR/timestamps
    511 mkdir -p $TIMESTAMPS_DIR
    512 
    513 stamp_check () {
    514     [ -f "$TIMESTAMPS_DIR/$1" ]
    515 }
    516 
    517 stamp_clear () {
    518     rm -f "$TIMESTAMPS_DIR/$1"
    519 }
    520 
    521 stamp_set () {
    522     touch "$TIMESTAMPS_DIR/$1"
    523 }
    524 
    525 if [ "$FORCE" = "yes" ] ; then
    526     echo "Cleaning up timestamps (forcing the build)."
    527     rm -f $TIMESTAMPS_DIR/*
    528 fi
    529 
    530 if [ "$VERBOSE" = 0 ] ; then
    531     echo "To follow build, run: tail -F $TMPLOG"
    532 fi
    533 
    534 # returns 0 iff the string in $2 matches the pattern in $1
    535 # $1: pattern
    536 # $2: string
    537 pattern_match ()
    538 {
    539     echo "$2" | grep -q -E -e "$1"
    540 }
    541 
    542 # Find if a given shell program is available.
    543 # We need to take care of the fact that the 'which <foo>' command
    544 # may return either an empty string (Linux) or something like
    545 # "no <foo> in ..." (Darwin). Also, we need to redirect stderr
    546 # to /dev/null for Cygwin
    547 #
    548 # $1: variable name
    549 # $2: program name
    550 #
    551 # Result: set $1 to the full path of the corresponding command
    552 #         or to the empty/undefined string if not available
    553 #
    554 find_program ()
    555 {
    556     local PROG
    557     PROG=`which $2 2>/dev/null`
    558     if [ -n "$PROG" ] ; then
    559         if pattern_match '^no ' "$PROG"; then
    560             PROG=
    561         fi
    562     fi
    563     eval $1="$PROG"
    564 }
    565 
    566 # Copy a directory, create target location if needed
    567 #
    568 # $1: source directory
    569 # $2: target directory location
    570 #
    571 copy_directory ()
    572 {
    573     local SRCDIR="$1"
    574     local DSTDIR="$2"
    575     if [ ! -d "$SRCDIR" ] ; then
    576         panic "Can't copy from non-directory: $SRCDIR"
    577     fi
    578     log2 "Directory copy: $SRCDIR -> $DSTDIR"
    579     mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar cf - *) | (tar xf - -C "$DSTDIR")
    580     fail_panic "Cannot copy to directory: $DSTDIR"
    581 }
    582 
    583 find_program CMD_WGET wget
    584 find_program CMD_CURL curl
    585 find_program CMD_SCP  scp
    586 
    587 # Download a file with either 'curl', 'wget' or 'scp'
    588 #
    589 # $1: source URL (e.g. http://foo.com, ssh://blah, /some/path)
    590 # $2: target file
    591 download_file ()
    592 {
    593     # Is this HTTP, HTTPS or FTP ?
    594     if pattern_match "^(http|https|ftp):.*" "$1"; then
    595         if [ -n "$CMD_WGET" ] ; then
    596             run $CMD_WGET -O $2 $1
    597         elif [ -n "$CMD_CURL" ] ; then
    598             run $CMD_CURL -o $2 $1
    599         else
    600             echo "Please install wget or curl on this machine"
    601             exit 1
    602         fi
    603         return
    604     fi
    605 
    606     # Is this SSH ?
    607     # Accept both ssh://<path> or <machine>:<path>
    608     #
    609     if pattern_match "^(ssh|[^:]+):.*" "$1"; then
    610         if [ -n "$CMD_SCP" ] ; then
    611             scp_src=`echo $1 | sed -e s%ssh://%%g`
    612             run $CMD_SCP $scp_src $2
    613         else
    614             echo "Please install scp on this machine"
    615             exit 1
    616         fi
    617         return
    618     fi
    619 
    620     # Is this a file copy ?
    621     # Accept both file://<path> or /<path>
    622     #
    623     if pattern_match "^(file://|/).*" "$1"; then
    624         cp_src=`echo $1 | sed -e s%^file://%%g`
    625         run cp -f $cp_src $2
    626         return
    627     fi
    628 
    629     # Unknown schema
    630     echo "ERROR: Unsupported source URI: $1"
    631     exit 1
    632 }
    633 
    634 # A variant of 'download_file' used to specify the target directory
    635 # $1: source URL
    636 # $2: target directory
    637 download_file_to ()
    638 {
    639     local URL="$1"
    640     local DIR="$2"
    641     local DST="$DIR/`basename $URL`"
    642     mkdir -p $DIR
    643     download_file "$URL" "$DST"
    644 }
    645 
    646 # Pack a given archive
    647 #
    648 # $1: archive file path (including extension)
    649 # $2: source directory for archive content
    650 # $3+: list of files (including patterns), all if empty
    651 pack_archive ()
    652 {
    653     local ARCHIVE="$1"
    654     local SRCDIR="$2"
    655     local SRCFILES
    656     local TARFLAGS ZIPFLAGS
    657     shift; shift;
    658     if [ -z "$1" ] ; then
    659         SRCFILES="*"
    660     else
    661         SRCFILES="$@"
    662     fi
    663     if [ "`basename $ARCHIVE`" = "$ARCHIVE" ] ; then
    664         ARCHIVE="`pwd`/$ARCHIVE"
    665     fi
    666     mkdir -p `dirname $ARCHIVE`
    667     if [ "$VERBOSE" -ge 2 ] ; then
    668         TARFLAGS="vcf"
    669         ZIPFLAGS="-9r"
    670     else
    671         TARFLAGS="cf"
    672         ZIPFLAGS="-9qr"
    673     fi
    674     case "$ARCHIVE" in
    675         *.zip)
    676             (cd $SRCDIR && run zip $ZIPFLAGS "$ARCHIVE" $SRCFILES)
    677             ;;
    678         *.tar)
    679             (cd $SRCDIR && run tar $TARFLAGS "$ARCHIVE" $SRCFILES)
    680             ;;
    681         *.tar.gz)
    682             (cd $SRCDIR && run tar z$TARFLAGS "$ARCHIVE" $SRCFILES)
    683             ;;
    684         *.tar.bz2)
    685             (cd $SRCDIR && run tar j$TARFLAGS "$ARCHIVE" $SRCFILES)
    686             ;;
    687         *)
    688             panic "Unsupported archive format: $ARCHIVE"
    689             ;;
    690     esac
    691 }
    692 
    693 no_trailing_slash ()
    694 {
    695     echo ${1##/}
    696 }
    697 
    698 # Load the Ubuntu packages file. This is a long text file that will list
    699 # each package for a given release.
    700 #
    701 # $1: Ubuntu mirror base URL (e.g. http://mirrors.us.kernel.org/)
    702 # $2: Release name
    703 #
    704 get_ubuntu_packages_list ()
    705 {
    706     local RELEASE=$2
    707     local BASE="`no_trailing_slash \"$1\"`"
    708     local SRCFILE DSTFILE
    709     for UA in $UBUNTU_ARCHS; do
    710         SRCFILE="$BASE/ubuntu/dists/$RELEASE/main/binary-$UA/Packages.bz2"
    711         DSTFILE="$DOWNLOAD_DIR/Packages-$UA.bz2"
    712         log "Trying to load $SRCFILE"
    713         download_file "$SRCFILE" "$DSTFILE"
    714         fail_panic "Could not download $SRCFILE"
    715         (cd $DOWNLOAD_DIR && bunzip2 -cf Packages-$UA.bz2 > Packages-$UA)
    716         fail_panic "Could not uncompress $DSTFILE to Packages-$UA"
    717     done
    718 
    719     # Write a small awk script used to extract filenames for a given package
    720     cat > $DOWNLOAD_DIR/extract-filename.awk <<EOF
    721 BEGIN {
    722     # escape special characters in package name
    723     gsub("\\\\.","\\\\.",PKG)
    724     gsub("\\\\+","\\\\+",PKG)
    725     FILE = ""
    726     PACKAGE = ""
    727 }
    728 
    729 \$1 == "Package:" {
    730     if (\$2 == PKG) {
    731         PACKAGE = \$2
    732     } else {
    733         PACKAGE = ""
    734     }
    735 }
    736 
    737 \$1 == "Filename:" && PACKAGE == PKG {
    738     FILE = \$2
    739 }
    740 
    741 END {
    742     print FILE
    743 }
    744 EOF
    745 }
    746 
    747 # Convert an unversioned package name into a .deb package URL
    748 #
    749 # $1: Package name without version information (e.g. libc6-dev)
    750 # $2: Ubuntu mirror base URL
    751 # $3: Ubuntu arch ("i386" or "amd64")
    752 #
    753 get_ubuntu_package_deb_url ()
    754 {
    755     # The following is an awk command to parse the Packages file and extract
    756     # the filename of a given package.
    757     local BASE="`no_trailing_slash \"$1\"`"
    758     local FILE=`awk -f "$DOWNLOAD_DIR/extract-filename.awk" -v PKG=$1 $DOWNLOAD_DIR/Packages-$3`
    759     if [ -z "$FILE" ]; then
    760         log "Could not find filename for package $1"
    761         exit 1
    762     fi
    763     echo "$2/ubuntu/$FILE"
    764 }
    765 
    766 # Does the host compiler generate 32-bit machine code?
    767 # If not, add the -m32 flag to the compiler name to ensure this.
    768 #
    769 compute_host_flags ()
    770 {
    771     HOST_CC=${CC:-gcc}
    772     HOST_CXX=${CXX-g++}
    773     if [ -n "$USE_CCACHE" ]; then
    774         echo -n "Checking for ccache..."
    775         find_program CMD_CCACHE ccache
    776         if [ -n "$CMD_CCACHE" ] ; then
    777             echo "$HOST_CC" | tr ' ' '\n' | grep -q -e "ccache"
    778             if [ $? = 0 ] ; then
    779                 echo "yes (ignored)"
    780             else
    781                 echo "yes"
    782                 HOST_CC="ccache $HOST_CC"
    783                 HOST_CXX="ccache $HOST_CXX"
    784             fi
    785         else
    786             echo "no"
    787         fi
    788     fi
    789     echo -n "Checking compiler bitness... "
    790     cat > "$BUILD_DIR"/conftest.c << EOF
    791 #include <stdio.h>
    792 int main(void) {
    793     printf("%d\n",sizeof(void*)*8);
    794     return 0;
    795 }
    796 EOF
    797     $HOST_CC -o "$BUILD_DIR"/conftest "$BUILD_DIR"/conftest.c > "$BUILD_DIR"/conftest.log 2>&1
    798     if [ $? != 0 ] ; then
    799         echo "Could not compile test program!!"
    800         echo "Error log is:"
    801         cat "$BUILD_DIR"/conftest.log
    802         rm "$BUID_DIR"/conftest.log
    803         panic "Need a working build toolchain!"
    804     fi
    805     HOST_CC_BITS=$("$BUILD_DIR"/conftest)
    806     echo -n "$HOST_CC_BITS"
    807     case $HOST_CC_BITS in
    808         32) # Nothing to do
    809             ;;
    810         64) # Do we need to force 32-bits
    811             if [ "$FORCE_32" ]; then
    812                 echo " (forcing generation of 32-bit binaries)"
    813                 HOST_CC=$HOST_CC" -m32"
    814                 HOST_CXX=$HOST_CXX" -m32"
    815             fi
    816             ;;
    817         *)
    818             panic "Unknown bitness (32 or 64 expected) !!"
    819     esac
    820     echo ""
    821     echo "Using build C compiler: $HOST_CC"
    822     echo "Using build C++ compiler: $HOST_CXX"
    823     echo "GCC target name: $GCC_TARGET"
    824     echo "GMP target name: $GMP_TARGET"
    825     echo "GMP ABI: $GMP_ABI"
    826     export CC="$HOST_CC"
    827     export CXX="$HOST_CXX"
    828 }
    829 
    830 compute_host_flags
    831 
    832 # Return the value of a given named variable
    833 # $1: variable name
    834 #
    835 # example:
    836 #    FOO=BAR
    837 #    BAR=ZOO
    838 #    echo `var_value $FOO`
    839 #    will print 'ZOO'
    840 #
    841 var_value ()
    842 {
    843     eval echo \$$1
    844 }
    845 
    846 var_list_append ()
    847 {
    848     local VARNAME=$1
    849     local VARVAL=`var_value $VARNAME`
    850     shift
    851     if [ -z "$VARVAL" ] ; then
    852         eval $VARNAME=\"$@\"
    853     else
    854         eval $VARNAME=\"$VARVAL $@\"
    855     fi
    856 }
    857 
    858 var_list_prepend ()
    859 {
    860     local VARNAME=$1
    861     local VARVAL=`var_value $VARNAME`
    862     shift
    863     if [ -z "$VARVAL" ] ; then
    864         eval $VARNAME=\"$@\"
    865     else
    866         eval $VARNAME=\"$@ $VARVAL\"
    867     fi
    868 }
    869 
    870 _list_first ()
    871 {
    872     echo $1
    873 }
    874 
    875 _list_rest ()
    876 {
    877     shift
    878     echo "$@"
    879 }
    880 
    881 _list_reverse ()
    882 {
    883     local I1 I2 I3 I4 I5 I6 I7 I8 I9 REST RET
    884     I1=$1; I2=$2; I3=$3; I4=$I4; I5=$I5; I6=$I6; I7=$I7; I8=$I8; I9=$I9
    885     shift 9
    886     RET=$I9${I8:+" "}$I8${I7:+" "}$I7${I6:+" "}$I6${I5:+" "}$I5${I4:+" "}$I4${I3:+" "}$I3${I2:+" "}$I2${I1:+" "}$I1
    887     REST="$*"
    888     if [ "$REST" ]; then
    889         RET=$(_list_reverse $REST)$RET
    890     fi
    891     echo "$RET"
    892 }
    893 
    894 var_list_pop_first ()
    895 {
    896     local VARNAME=$1
    897     local VARVAL=`var_value $VARNAME`
    898     local FIRST=`_list_first $VARVAL`
    899     eval $VARNAME=\"`_list_rest $VARVAL`\"
    900     echo "$FIRST"
    901 }
    902 
    903 _list_first ()
    904 {
    905     echo $1
    906 }
    907 
    908 _list_rest ()
    909 {
    910     shift
    911     echo "$@"
    912 }
    913 
    914 var_list_first ()
    915 {
    916     local VAL=`var_value $1`
    917     _list_first $VAL
    918 }
    919 
    920 var_list_rest ()
    921 {
    922     local VAL=`var_value $1`
    923     _list_rest $VAL
    924 }
    925 
    926 ALL_TASKS=
    927 
    928 # Define a new task for this build script
    929 # $1: Task name (e.g. build_stuff)
    930 # $2: Task description
    931 # $3: Optional: command name (will be cmd_$1 by default)
    932 #
    933 task_define ()
    934 {
    935     local TASK="$1"
    936     local DESCR="$2"
    937     local COMMAND="${3:-cmd_$1}"
    938 
    939     var_list_append ALL_TASKS $TASK
    940     task_set $TASK name "$TASK"
    941     task_set $TASK descr "$DESCR"
    942     task_set $TASK cmd "$COMMAND"
    943     task_set $TASK deps ""
    944 }
    945 
    946 # Variant of task define for dual tasks
    947 # This really defines two tasks named '<task>_1' and '<task>_2"
    948 # $1: Task base name
    949 # $2: Task description
    950 # $3: Optional: command name (will be cmd_$1 by default)
    951 task2_define ()
    952 {
    953     local TASK="$1"
    954     local DESCR="$2"
    955     local COMMAND="${3:-cmd_$1}"
    956 
    957     task_define "${TASK}_1" "$DESCR 1/2" "phase_1 $COMMAND"
    958     task_define "${TASK}_2" "$DESCR 2/2" "phase_2 $COMMAND"
    959 }
    960 
    961 task_set ()
    962 {
    963     local TASK="$1"
    964     local FIELD="$2"
    965     shift; shift;
    966     eval TASK_${TASK}__${FIELD}=\"$@\"
    967 }
    968 
    969 task_get ()
    970 {
    971     var_value TASK_$1__$2
    972 }
    973 
    974 # return the list of dependencies for a given task
    975 task_get_deps ()
    976 {
    977     task_get $1 deps
    978 }
    979 
    980 task_get_cmd ()
    981 {
    982     task_get $1 cmd
    983 }
    984 
    985 task_get_descr ()
    986 {
    987     task_get $1 descr
    988 }
    989 
    990 # $1: task name
    991 # $2+: other tasks this task depends on.
    992 task_depends ()
    993 {
    994     local TASK="$1"
    995     shift;
    996     var_list_append TASK_${TASK}__deps $@
    997 }
    998 
    999 # $1: dual task name
   1000 # $2+: other non-dual tasks this dual task depends on
   1001 task2_depends1 ()
   1002 {
   1003     local TASK="$1"
   1004     shift
   1005     var_list_append TASK_${TASK}_1__deps $@
   1006     var_list_append TASK_${TASK}_2__deps $@
   1007 }
   1008 
   1009 # $1: dual task name
   1010 # $2+: other dual tasks this dual task depends on
   1011 task2_depends2 ()
   1012 {
   1013     local TASK="$1"
   1014     local DEP
   1015     shift
   1016     for DEP; do
   1017         var_list_append TASK_${TASK}_1__deps ${DEP}_1
   1018         var_list_append TASK_${TASK}_2__deps ${DEP}_2
   1019     done
   1020 }
   1021 
   1022 task_dump ()
   1023 {
   1024     local TASK
   1025     for TASK in $ALL_TASKS; do
   1026         local DEPS="`task_get_deps $TASK`"
   1027         local CMD="`task_get_cmd $TASK`"
   1028         local DESCR="`task_get_descr $TASK`"
   1029         echo "TASK $TASK: $DESCR: $CMD"
   1030         echo ">  $DEPS"
   1031     done
   1032 }
   1033 
   1034 task_visit ()
   1035 {
   1036     task_set $TASK visit 1
   1037 }
   1038 
   1039 task_unvisit ()
   1040 {
   1041     task_set $TASK visit 0
   1042 }
   1043 
   1044 task_is_visited ()
   1045 {
   1046     [ `task_get $TASK visit` = 1 ]
   1047 }
   1048 
   1049 task_queue_reset ()
   1050 {
   1051     TASK_QUEUE=
   1052 }
   1053 
   1054 task_queue_push ()
   1055 {
   1056     var_list_append TASK_QUEUE $1
   1057 }
   1058 
   1059 task_queue_pop ()
   1060 {
   1061     local FIRST=`var_list_first TASK_QUEUE`
   1062     TASK_QUEUE=`var_list_rest TASK_QUEUE`
   1063 }
   1064 
   1065 do_all_tasks ()
   1066 {
   1067     local TASK
   1068     local TASK_LIST=
   1069     task_queue_reset
   1070     # Clear visit flags
   1071     for TASK in $ALL_TASKS; do
   1072         task_unvisit $TASK
   1073     done
   1074     task_queue_push $1
   1075     while [ -n "$TASK_QUEUE" ] ; do
   1076         TASK=`task_queue_pop`
   1077         if task_is_visited $TASK; then
   1078             continue
   1079         fi
   1080         # Prepend the task to the list if its timestamp is not set
   1081         if stamp_check $TASK; then
   1082             var_list_prepend TASK_LIST $TASK
   1083         fi
   1084         # Add all dependencies to the work-queue
   1085         local SUBTASK
   1086         for SUBTASK in `task_get_deps $TASK`; do
   1087             task_queue_push $SUBTASK
   1088         done
   1089         task_visit $TASK
   1090     done
   1091 
   1092     # Now, TASK_LIST contains the
   1093 }
   1094 
   1095 
   1096 # Return the first item of a space-separated list
   1097 list_first () {
   1098     set -- "$@"
   1099     echo "$1"
   1100 }
   1101 
   1102 # Append an item to a given list
   1103 list_append () {
   1104     local ITEM=$1
   1105     shift;
   1106     echo $@${@:+" "}$1
   1107 }
   1108 
   1109 # Return the second-to-last items of a space-separated list
   1110 list_rest () {
   1111     set -- "$@"
   1112     shift
   1113     echo "$@"
   1114 }
   1115 
   1116 # Reverse a space-separated list
   1117 list_reverse ()
   1118 {
   1119     set -- "$@"
   1120     local I1 I2 I3 I4 I5 I6 I7 I8 I9 REST RET
   1121     I1=$1; I2=$2; I3=$3; I4=$4; I5=$5; I6=$6; I7=$7; I8=$8; I9=$9
   1122     shift; shift; shift; shift; shift; shift; shift; shift; shift;
   1123     RET=$I9${I9:+" "}$I8${I8:+" "}$I7${I7:+" "}$I6${I6:+" "}$I5${I5:+" "}$I4${I4:+" "}$I3${I3:+" "}$I2${I2:+" "}$I1
   1124     REST="$*"
   1125     if [ -n "$REST" ]; then
   1126         RET=$(list_reverse $REST)" "$RET
   1127     fi
   1128     echo "$RET"
   1129 }
   1130 
   1131 # Used to build the list of tasks with a tree post-order traversal, i.e.
   1132 # the list starts at the leaves and finishes with the top level task,
   1133 # so that if task(A) depends on task(B), then A will always appear _after_
   1134 # B in the result.
   1135 #
   1136 # $1: space-separated list of tasks to visit
   1137 # Out: list of all tasks in post-order
   1138 #
   1139 task_build_postorder_list ()
   1140 {
   1141     local TASK
   1142     local STACK="$1"
   1143     local RET=""
   1144     for TASK in $ALL_TASKS; do
   1145         stamp_clear $TASK.visit
   1146     done
   1147     while true; do
   1148         # Peek at stack
   1149         TASK=$(list_first $STACK)
   1150         #echo >&2 "STACK: ($TASK) '$STACK'"
   1151         if [ -z "$TASK" ]; then
   1152             break
   1153         fi
   1154         HAS_DEPS=
   1155         for DEP in $(task_get_deps $TASK); do
   1156             #echo >&2 "CHECK: '$DEP'"
   1157             if ! stamp_check $DEP.visit; then
   1158                 STACK=$DEP" "$STACK
   1159                 #echo >&2 "PUSH: '$DEP' => '$STACK'"
   1160                 HAS_DEPS=1
   1161             fi
   1162         done
   1163 
   1164         if [ -z "$HAS_DEPS" ]; then
   1165             #echo >&2 "ADD: $TASK -> '$RET'"
   1166             STACK=$(list_rest $STACK)
   1167             if ! stamp_check $TASK.visit; then
   1168                 RET=$RET${RET:+" "}$TASK
   1169                 stamp_set $TASK.visit
   1170             fi
   1171         fi
   1172     done
   1173     for TASK in $ALL_TASKS; do
   1174         stamp_clear $TASK.visit
   1175     done
   1176     echo "$RET"
   1177 }
   1178 
   1179 run_task ()
   1180 {
   1181     # Build the list of tasks, in reverse order (from leafs to last)
   1182     local TASKS=$(task_build_postorder_list $1)
   1183     # Do all tasks
   1184     local TASK DEP DESCR
   1185 
   1186     # Dump list of tasks:
   1187 #     echo "ALL TASKS:"
   1188 #     for TASK in $TASKS; do
   1189 #         echo "  $TASK"
   1190 #     done
   1191 
   1192     # Clean timestamps of any tasks whose any of its dependents needs
   1193     # to be re-done.
   1194     #
   1195     for TASK in $TASKS; do
   1196        for DEP in $(task_get_deps $TASK); do
   1197             if ! stamp_check $DEP; then
   1198                 #echo "Redo: $TASK due to $DEP"
   1199                 stamp_clear $TASK
   1200                 break
   1201             fi
   1202        done
   1203     done
   1204 
   1205     for TASK in $TASKS; do
   1206         DESCR=$(task_get_descr $TASK)
   1207         if stamp_check $TASK; then
   1208             echo "Skipping: $DESCR"
   1209             continue
   1210         fi
   1211         echo "Running: $DESCR"
   1212         if [ "$VERBOSE" -ge 1 ] ; then
   1213             (eval $(task_get_cmd $TASK))
   1214         else
   1215             (eval $(task_get_cmd $TASK)) >> $TMPLOG 2>&1
   1216         fi
   1217         if [ $? != 0 ] ; then
   1218             echo "ERROR: Cannot $DESCR"
   1219             exit 1
   1220         fi
   1221 
   1222         stamp_set $TASK
   1223     done
   1224 }
   1225 
   1226 # This function is used to clone a source repository either from a given
   1227 # git base or a git reference.
   1228 # $1: project/subdir name
   1229 # $2: path to SOURCES file
   1230 toolchain_clone ()
   1231 {
   1232     local GITFLAGS
   1233     GITFLAGS=
   1234     if [ "$GIT_REFERENCE" ]; then
   1235         GITFLAGS="$GITFLAGS --shared --reference $GIT_REFERENCE/$1"
   1236     fi
   1237     echo "cleaning up toolchain/$1"
   1238     rm -rf $1
   1239     fail_panic "Could not clean $(pwd)/$1"
   1240     echo "downloading sources for toolchain/$1"
   1241     if [ -d "$GIT_BASE/$1" ]; then
   1242         log "cloning $GIT_BASE/$1"
   1243         run $GIT_CMD clone $GITFLAGS $GIT_BASE/$1 $1
   1244     else
   1245         log "cloning $GITPREFIX/$1.git"
   1246         run $GIT_CMD clone $GITFLAGS $GIT_BASE/$1.git $1
   1247     fi
   1248     fail_panic "Could not clone $GIT_BASE/$1.git ?"
   1249     cd $1
   1250     if [ "$GIT_BRANCH" != "master" ] ; then
   1251         log "checking out $GIT_BRANCH branch of $1.git"
   1252         run $GIT_CMD checkout -b $GIT_BRANCH origin/$GIT_BRANCH
   1253         fail_panic "Could not checkout $1 ?"
   1254     fi
   1255     # If --git-date is used, or we have a default
   1256     if [ -n "$GIT_DATE" ] ; then
   1257         REVISION=`git rev-list -n 1 --until="$GIT_DATE" HEAD`
   1258         echo "Using sources for date '$GIT_DATE': toolchain/$1 revision $REVISION"
   1259         run $GIT_CMD checkout $REVISION
   1260         fail_panic "Could not checkout $1 ?"
   1261     fi
   1262     (printf "%-32s " "toolchain/$1.git: " && git log -1 --format=oneline) >> $2
   1263     cd ..
   1264 }
   1265 
   1266 task_define download_toolchain_sources "Download toolchain sources from $GIT_BASE "
   1267 cmd_download_toolchain_sources ()
   1268 {
   1269     local SUBDIRS="binutils build gcc gdb gold gmp mpfr mpc isl cloog"
   1270     (mkdir -p $TOOLCHAIN_SRC_DIR && cd $TOOLCHAIN_SRC_DIR &&
   1271     # Create a temporary SOURCES file for the toolchain sources only
   1272     # It's content will be copied to the final SOURCES file later.
   1273     SOURCES_LIST=$TOOLCHAIN_SRC_DIR/SOURCES
   1274     rm -f $SOURCES_LIST && touch $SOURCES_LIST
   1275     for SUB in $SUBDIRS; do
   1276         toolchain_clone $SUB $SOURCES_LIST
   1277     done
   1278     )
   1279 }
   1280 
   1281 task_define download_ubuntu_packages_list "Download Ubuntu packages list"
   1282 cmd_download_ubuntu_packages_list ()
   1283 {
   1284     mkdir -p $DOWNLOAD_DIR
   1285     get_ubuntu_packages_list "$UBUNTU_MIRROR" "$UBUNTU_RELEASE"
   1286     fail_panic "Unable to download packages list, try --ubuntu-mirror=<url> to use another archive mirror"
   1287 }
   1288 
   1289 task_define download_packages "Download Ubuntu packages"
   1290 task_depends download_packages download_ubuntu_packages_list
   1291 cmd_download_packages ()
   1292 {
   1293     local PACKAGE PKGURL
   1294 
   1295     rm -f $DOWNLOAD_DIR/SOURCES && touch $DOWNLOAD_DIR/SOURCES
   1296     for PACKAGE in $UBUNTU_PACKAGES; do
   1297         echo "Downloading $PACKAGE"
   1298 	    for UA in $UBUNTU_ARCHS; do
   1299             PKGURL=`get_ubuntu_package_deb_url $PACKAGE $UBUNTU_MIRROR $UA`
   1300             echo "URL: $PKGURL"
   1301             download_file_to $PKGURL $DOWNLOAD_DIR
   1302             fail_panic "Could not download $PKGURL"
   1303         done
   1304     done
   1305     sha1sum $DOWNLOAD_DIR/*.deb | while read LINE; do
   1306         PACKAGE=$(basename $(echo $LINE | awk '{ print $2;}'))
   1307         SHA1=$(echo $LINE | awk '{ print $1; }')
   1308         printf "%-64s %s\n" $PACKAGE $SHA1 >> $DOWNLOAD_DIR/SOURCES
   1309     done
   1310 }
   1311 
   1312 task_define build_sysroot "Build sysroot"
   1313 task_depends build_sysroot download_packages
   1314 
   1315 cmd_build_sysroot ()
   1316 {
   1317     local PACKAGE PKGURL SRC_PKG
   1318     mkdir -p $SRC_PKG $ORG_SYSROOT_DIR
   1319     for PACKAGE in $UBUNTU_PACKAGES; do
   1320 	    for UA in $UBUNTU_ARCHS; do
   1321             PKGURL=`get_ubuntu_package_deb_url $PACKAGE $UBUNTU_MIRROR $UA`
   1322             SRC_PKG=$DOWNLOAD_DIR/`basename $PKGURL`
   1323             echo "Extracting $SRC_PKG"
   1324             dpkg -x $SRC_PKG $ORG_SYSROOT_DIR/$UA
   1325 	    done
   1326     done
   1327 }
   1328 
   1329 # Now, we need to patch libc.so which is actually a linker script
   1330 # referencing /lib and /usr/lib. Do the same for libpthread.so
   1331 patch_library ()
   1332 {
   1333     echo "Patching $1"
   1334     sed -i -e "s! /lib/! !g" -e "s! /usr/lib/! !g" $1
   1335 }
   1336 
   1337 # Used to setup phase 1 the run a command
   1338 phase_1 ()
   1339 {
   1340     PHASE=1
   1341     $@
   1342 }
   1343 
   1344 # Used to setup phase 2 then run a command
   1345 phase_2 ()
   1346 {
   1347     PHASE=1
   1348     BINPREFIX=$(install_dir)/bin/${GCC_TARGET}-
   1349     CC=${BINPREFIX}gcc
   1350     CXX=${BINPREFIX}g++
   1351     LD=${BINPREFIX}ld
   1352     AR=${BINPREFIX}ar
   1353     AS=${BINPREFIX}as
   1354     RANLIB=${BINPREFIX}ranlib
   1355     STRIP=${BINPREFIX}strip
   1356     CC_FOR_TARGET=${BINPREFIX}gcc
   1357     export CC CXX LD AR AS RANLIB STRIP CC_FOR_TARGET
   1358     PHASE=2
   1359     $@
   1360 }
   1361 
   1362 # Return the list of all symbolic links in a given directory, excluding
   1363 # any links in its sub-directories.
   1364 # $1: Sub-directory path.
   1365 find_symlinks_in () {
   1366     (cd $1 && find . -maxdepth 1 -type l) | sed -e 's|^\./||g'
   1367 }
   1368 
   1369 task2_define copy_sysroot "Fix and copy sysroot"
   1370 task2_depends1 copy_sysroot build_sysroot
   1371 cmd_copy_sysroot ()
   1372 {
   1373     local SL
   1374 
   1375     # Copy the content of $BUILD_DIR/lib to $(sysroot_dir)/usr/lib
   1376     copy_directory $ORG_SYSROOT_DIR/i386/lib $(sysroot_dir)/usr/lib32
   1377     copy_directory $ORG_SYSROOT_DIR/i386/usr/lib $(sysroot_dir)/usr/lib32
   1378     copy_directory $ORG_SYSROOT_DIR/i386/usr/include $(sysroot_dir)/usr/include
   1379 
   1380     copy_directory $ORG_SYSROOT_DIR/amd64/lib $(sysroot_dir)/usr/lib
   1381     copy_directory $ORG_SYSROOT_DIR/amd64/usr/lib $(sysroot_dir)/usr/lib
   1382     copy_directory $ORG_SYSROOT_DIR/amd64/usr/include $(sysroot_dir)/usr/include
   1383 
   1384     for LIB in lib lib32; do
   1385         # We need to fix the symlink like librt.so -> /lib/librt.so.1
   1386         # in $(sysroot_dir)/usr/$LIB, they should point to librt.so.1 instead now.
   1387         SYMLINKS=$(find_symlinks_in $(sysroot_dir)/usr/$LIB)
   1388         cd $(sysroot_dir)/usr/$LIB
   1389         for SL in $SYMLINKS; do
   1390             # convert /lib/libfoo.so.<n> into 'libfoo.so.<n>' for the target
   1391             local DST=$(readlink $SL 2>/dev/null)
   1392             local DST2=${DST##/lib/}
   1393             if [ "$DST2" != "$DST" ]; then
   1394                 echo "Fixing symlink $SL --> $DST"
   1395                 rm $SL && ln -s $DST2 $SL
   1396             fi
   1397         done
   1398         patch_library $(sysroot_dir)/usr/$LIB/libc.so
   1399         patch_library $(sysroot_dir)/usr/$LIB/libpthread.so
   1400     done
   1401 }
   1402 
   1403 task_define patch_toolchain_sources "Patch toolchain sources."
   1404 task_depends patch_toolchain_sources download_toolchain_sources
   1405 cmd_patch_toolchain_sources ()
   1406 {
   1407     log "PATCHES_DIR = $PATCHES_DIR"
   1408     if [ ! -d "$PATCHES_DIR" ]; then
   1409         log "$PATCHES_DIR doesn't exist"
   1410         return 0
   1411     fi
   1412 
   1413     local PATCHES=`(cd $PATCHES_DIR && find . -name "*.patch" | sort ) 2> /dev/null`
   1414     if [ -z "$PATCHES" ] ; then
   1415         log "No patches files in $PATCHES_DIR"
   1416         return 0
   1417     fi
   1418 
   1419     PATCHES=`echo $PATCHES | sed -e s%^\./%%g`
   1420     for PATCH in $PATCHES; do
   1421         PATCHDIR=`dirname $PATCH`
   1422         PATCHNAME=`basename $PATCH`
   1423         log "Applying $PATCHNAME into $TOOLCHAIN_SRC_DIR/$PATCHDIR"
   1424         (cd $TOOLCHAIN_SRC_DIR/$PATCHDIR && patch -p1 < $PATCHES_DIR/$PATCH)
   1425         fail_panic "Patch failure!! Please check your patches directory!"
   1426     done
   1427 
   1428     log "Done patching."
   1429 }
   1430 
   1431 task_define prepare_toolchain_sources "Prepare toolchain sources."
   1432 if [ -n "$GIT_BASE" -o -n "$GIT_REFERENCE" ]; then
   1433     task_depends prepare_toolchain_sources patch_toolchain_sources
   1434 fi
   1435 cmd_prepare_toolchain_sources ()
   1436 {
   1437     return
   1438 }
   1439 
   1440 task2_define configure_binutils "Configure binutils-$BINUTILS_VERSION"
   1441 task2_depends1 configure_binutils prepare_toolchain_sources
   1442 task2_depends2 configure_binutils copy_sysroot
   1443 cmd_configure_binutils ()
   1444 {
   1445     OUT_DIR=$(build_dir_for binutils)
   1446     mkdir -p $OUT_DIR && cd $OUT_DIR &&
   1447     run $TOOLCHAIN_SRC_DIR/binutils/binutils-$BINUTILS_VERSION/configure \
   1448         --prefix=$(install_dir) \
   1449         --with-sysroot=$(sysroot_dir) \
   1450         --target=$GCC_TARGET \
   1451         --enable-gold=default \
   1452         --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' \
   1453         --with-gold-ldflags='-static-libgcc -static-libstdc++' \
   1454         --with-bugurl=http://source.android.com/source/report-bugs.html
   1455 }
   1456 
   1457 task2_define build_binutils "Build binutils-$BINUTILS_VERSION"
   1458 task2_depends2 build_binutils configure_binutils
   1459 cmd_build_binutils ()
   1460 {
   1461     cd $(build_dir_for binutils) &&
   1462     make $MAKE_FLAGS
   1463 }
   1464 
   1465 task2_define install_binutils "Install binutils-$BINUTILS_VERSION"
   1466 task2_depends2 install_binutils build_binutils
   1467 cmd_install_binutils ()
   1468 {
   1469     cd $(build_dir_for binutils) &&
   1470     make install
   1471 }
   1472 
   1473 task2_define extract_gmp "Extract sources for gmp-$GMP_VERSION"
   1474 task2_depends1 extract_gmp prepare_toolchain_sources
   1475 cmd_extract_gmp ()
   1476 {
   1477     OUT_DIR=$(build_dir_for gmp)
   1478     GMP_TARBALL=$TOOLCHAIN_SRC_DIR/gmp/gmp-$GMP_VERSION.tar.bz2
   1479     if [ ! -f "$GMP_TARBALL" ]; then
   1480         GMP_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/gmp-$GMP_VERSION.tar.bz2
   1481         if [ ! -f "$GMP_TARBALL" ]; then
   1482             panic "Can't find gmp-$GMP_VERSION sources!!"
   1483         fi
   1484     fi
   1485     mkdir -p $OUT_DIR && cd $OUT_DIR &&
   1486     tar xjf "$GMP_TARBALL"
   1487 }
   1488 
   1489 task2_define configure_gmp "Configure gmp-$GMP_VERSION"
   1490 task2_depends2 configure_gmp extract_gmp install_binutils
   1491 cmd_configure_gmp ()
   1492 {
   1493     export ABI=$GMP_ABI &&
   1494     cd $(build_dir_for gmp) && mkdir -p build && cd build &&
   1495     ../gmp-$GMP_VERSION/configure \
   1496         --prefix=$(install_dir) \
   1497         --host=$GMP_TARGET \
   1498         --with-sysroot=$(install_dir) \
   1499         --disable-shared
   1500 }
   1501 
   1502 task2_define build_gmp "Build gmp-$GMP_VERSION"
   1503 task2_depends2 build_gmp configure_gmp
   1504 cmd_build_gmp ()
   1505 {
   1506     export ABI=$GMP_ABI &&
   1507     cd $(build_dir_for gmp)/build &&
   1508     make $MAKE_FLAGS
   1509 }
   1510 
   1511 task2_define install_gmp "Install gmp-$GMP_VERSION"
   1512 task2_depends2 install_gmp build_gmp
   1513 cmd_install_gmp ()
   1514 {
   1515     cd $(build_dir_for gmp)/build &&
   1516     make install
   1517 }
   1518 
   1519 # Third, build mpfr
   1520 task2_define extract_mpfr "Extract sources from mpfr-$MPFR_VERSION"
   1521 task2_depends1 extract_mpfr prepare_toolchain_sources
   1522 cmd_extract_mpfr ()
   1523 {
   1524     OUT_DIR=$(build_dir_for mpfr)
   1525     MPFR_TARBALL=$TOOLCHAIN_SRC_DIR/mpfr/mpfr-$MPFR_VERSION.tar.bz2
   1526     if [ ! -f "$MPFR_TARBALL" ]; then
   1527         MPFR_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/mpfr-$MPFR_VERSION.tar.bz2
   1528         if [ ! -f "$MPFR_TARBALL" ]; then
   1529             panic "Can't find mpfr-$MPFR_VERSION sources!!"
   1530         fi
   1531     fi
   1532     mkdir -p $OUT_DIR && cd $OUT_DIR &&
   1533     tar xjf "$MPFR_TARBALL"
   1534 }
   1535 
   1536 task2_define configure_mpfr "Configure mpfr-$MPFR_VERSION"
   1537 task2_depends2 configure_mpfr extract_mpfr install_gmp
   1538 cmd_configure_mpfr ()
   1539 {
   1540     cd $(build_dir_for mpfr) && mkdir -p build && cd build &&
   1541     run ../mpfr-$MPFR_VERSION/configure \
   1542         --prefix=$(install_dir) \
   1543         --host=$GMP_TARGET \
   1544         --with-gmp=$(install_dir) \
   1545         --with-sysroot=$(sysroot_dir) \
   1546         --disable-shared
   1547 }
   1548 
   1549 task2_define build_mpfr "Build mpfr-$MPFR_VERSION"
   1550 task2_depends2 build_mpfr configure_mpfr
   1551 cmd_build_mpfr ()
   1552 {
   1553     cd $(build_dir_for mpfr)/build &&
   1554     run make $MAKE_FLAGS
   1555 }
   1556 
   1557 task2_define install_mpfr "Install mpfr-$MPFR_VERSION"
   1558 task2_depends2 install_mpfr build_mpfr
   1559 cmd_install_mpfr ()
   1560 {
   1561     cd $(build_dir_for mpfr)/build &&
   1562     run make install
   1563 }
   1564 
   1565 task2_define extract_mpc "Extract sources for mpc-$MPC_VERSION"
   1566 task2_depends1 extract_mpc prepare_toolchain_sources
   1567 cmd_extract_mpc ()
   1568 {
   1569     OUT_DIR=$(build_dir_for mpc)
   1570     MPC_TARBALL=$TOOLCHAIN_SRC_DIR/mpc/mpc-$MPC_VERSION.tar.gz
   1571     if [ ! -f "$MPC_TARBALL" ]; then
   1572         MPC_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/mpc-$MPC_VERSION.tar.gz
   1573         if [ ! -f "$MPC_TARBALL" ]; then
   1574             panic "Can't find mpc-$MPC_VERSION sources!!"
   1575         fi
   1576     fi
   1577     mkdir -p $OUT_DIR && cd $OUT_DIR &&
   1578     tar xzf "$MPC_TARBALL"
   1579 }
   1580 
   1581 task2_define configure_mpc "Configure mpc-$MPC_VERSION"
   1582 task2_depends2 configure_mpc extract_mpc install_mpfr
   1583 cmd_configure_mpc ()
   1584 {
   1585     cd $(build_dir_for mpc) && mkdir -p build && cd build &&
   1586     run ../mpc-$MPC_VERSION/configure \
   1587         --prefix=$(install_dir) \
   1588         --host=$GMP_TARGET \
   1589         --with-gmp=$(install_dir) \
   1590         --with-mpfr=$(install_dir) \
   1591         --disable-shared
   1592 }
   1593 
   1594 task2_define build_mpc "Build mpc-$MPC_VERSION"
   1595 task2_depends2 build_mpc configure_mpc
   1596 cmd_build_mpc ()
   1597 {
   1598     cd $(build_dir_for mpc)/build &&
   1599     run make $MAKE_FLAGS
   1600 }
   1601 
   1602 task2_define install_mpc "Install mpc-$MPC_VERSION"
   1603 task2_depends2 install_mpc build_mpc
   1604 cmd_install_mpc ()
   1605 {
   1606     cd $(build_dir_for mpc)/build &&
   1607     run make install
   1608 }
   1609 
   1610 task2_define extract_isl "Extract sources for isl-$ISL_VERSION"
   1611 task2_depends2 extract_isl prepare_toolchain_sources
   1612 cmd_extract_isl ()
   1613 {
   1614     OUT_DIR=$(build_dir_for isl)
   1615     ISL_TARBALL=$TOOLCHAIN_SRC_DIR/isl/isl-$ISL_VERSION.tar.bz2
   1616     if [ ! -f "$ISL_TARBALL" ]; then
   1617         panic "Can't find isl-$ISL_VERSION sources!!"
   1618     fi
   1619     mkdir -p $OUT_DIR && cd $OUT_DIR &&
   1620     tar xf "$ISL_TARBALL"
   1621 }
   1622 
   1623 task2_define configure_isl "Configuring isl-$ISL_VERSION"
   1624 task2_depends2 configure_isl extract_isl install_gmp
   1625 cmd_configure_isl ()
   1626 {
   1627     cd $(build_dir_for isl) && mkdir -p build && cd build &&
   1628     run ../isl-$ISL_VERSION/configure \
   1629         --prefix=$(install_dir) \
   1630         --host=$GMP_TARGET \
   1631         --with-gmp-prefix=$(install_dir) \
   1632         --with-sysroot=$(sysroot_dir) \
   1633         --disable-shared
   1634 }
   1635 
   1636 task2_define build_isl "Building isl-$ISL_VERSION"
   1637 task2_depends2 build_isl configure_isl
   1638 cmd_build_isl ()
   1639 {
   1640     cd $(build_dir_for isl)/build &&
   1641     run make $MAKE_FLAGS
   1642 }
   1643 
   1644 task2_define install_isl "Installing isl-$ISL_VERSION"
   1645 task2_depends2 install_isl build_isl
   1646 cmd_install_isl ()
   1647 {
   1648     cd $(build_dir_for isl)/build &&
   1649     make install
   1650 }
   1651 
   1652 task2_define configure_cloog "Configure Cloog-$CLOOG_VERSION"
   1653 task2_depends2 configure_cloog prepare_toolchain_sources install_gmp install_isl
   1654 cmd_configure_cloog () {
   1655     mkdir -p $(build_dir_for cloog)/build && cd $(build_dir_for cloog)/build &&
   1656     run $TOOLCHAIN_SRC_DIR/cloog/cloog-$CLOOG_VERSION/configure \
   1657         --prefix=$(install_dir) \
   1658         --host=$GMP_TARGET \
   1659         --with-gmp-prefix=$(install_dir) \
   1660         --with-sysroot=$(sysroot_dir) \
   1661         --disable-shared
   1662 }
   1663 
   1664 task2_define build_cloog "Building Cloog-$CLOOG_VERSION"
   1665 task2_depends2 build_cloog configure_cloog
   1666 cmd_build_cloog ()
   1667 {
   1668     cd $(build_dir_for cloog)/build &&
   1669     run make $MAKE_FLAGS
   1670 }
   1671 
   1672 task2_define install_cloog "Installing Cloog-$CLOOG_VERSION"
   1673 task2_depends2 install_cloog build_cloog
   1674 cmd_install_cloog ()
   1675 {
   1676     cd $(build_dir_for cloog)/build &&
   1677     run make install
   1678 }
   1679 
   1680 # Fourth, the compiler itself
   1681 task2_define configure_gcc "Configure gcc-$GCC_VERSION"
   1682 task2_depends1 configure_gcc prepare_toolchain_sources
   1683 task2_depends2 configure_gcc install_binutils install_gmp install_mpfr install_mpc install_cloog
   1684 cmd_configure_gcc ()
   1685 {
   1686     local EXTRA_CONFIGURE_FLAGS=
   1687     if [ "$GCC_VERSION" != "4.6" ]; then
   1688         EXTRA_CONFIGURE_FLAGS="--with-cloog=$(install_dir)"
   1689     fi
   1690     OUT_DIR=$(build_dir_for gcc)
   1691     mkdir -p $OUT_DIR && cd $OUT_DIR &&
   1692     export CC=$HOST_CC &&
   1693     export CC_FOR_TARGET="$HOST_CC" &&
   1694     run $TOOLCHAIN_SRC_DIR/gcc/gcc-$GCC_VERSION/configure \
   1695         --prefix=$(install_dir) \
   1696         --with-sysroot=$(sysroot_dir) \
   1697         --disable-nls \
   1698         --with-gmp=$(install_dir) \
   1699         --with-mpfr=$(install_dir) \
   1700         --with-mpc=$(install_dir) \
   1701         --target=$GCC_TARGET \
   1702         --with-arch=x86-64 \
   1703         --with-multilib-list=m32,m64 \
   1704         --disable-plugin \
   1705         --disable-docs \
   1706         --disable-bootstrap \
   1707         --disable-libgomp \
   1708         --disable-libmudflap \
   1709         --disable-libquadmath \
   1710         --enable-target-optspace \
   1711         --enable-gold=default \
   1712         --enable-languages=c,c++ \
   1713         $EXTRA_CONFIGURE_FLAGS
   1714 }
   1715 
   1716 task2_define build_gcc "Build gcc-$GCC_VERSION"
   1717 task2_depends2 build_gcc configure_gcc
   1718 cmd_build_gcc ()
   1719 {
   1720     cd $(build_dir_for gcc) &&
   1721     make $MAKE_FLAGS
   1722 }
   1723 
   1724 task2_define install_gcc "Install gcc-$GCC_VERSION"
   1725 task2_depends2 install_gcc build_gcc
   1726 cmd_install_gcc ()
   1727 {
   1728     cd $(build_dir_for gcc) &&
   1729     make install
   1730 }
   1731 
   1732 task2_define cleanup_toolchain "Cleanup toolchain"
   1733 task2_depends2 cleanup_toolchain install_gcc
   1734 cmd_cleanup_toolchain ()
   1735 {
   1736     # Remove un-needed directories and files
   1737     rm -rf $(install_dir)/share
   1738     rm -rf $(install_dir)/man
   1739     rm -rf $(install_dir)/info
   1740     rm -rf $(install_dir)/libexec/*/*/install-tools
   1741     #rm -rf $(install_dir)/$GCC_TARGET/bin
   1742     find $(install_dir) -name "*.la" -exec rm -f {} \;
   1743 
   1744     (strip $(install_dir)/bin/*)
   1745     (strip $(install_dir)/libexec/gcc/$GCC_TARGET/*/*)
   1746     true
   1747 }
   1748 
   1749 task2_define package_toolchain "Package final toolchain"
   1750 task2_depends2 package_toolchain cleanup_toolchain
   1751 cmd_package_toolchain ()
   1752 {
   1753     # Copy this script to the install directory
   1754     cp -f $0 $(install_dir)
   1755     fail_panic "Could not copy build script to install directory"
   1756 
   1757     if [ -d "$PATCHES_DIR" ]; then
   1758         # Copy patches to the install directory
   1759         cp -rf "$PATCHES_DIR" $(install_dir)
   1760         fail_panic "Could not copy patch directory to install directory"
   1761     fi
   1762 
   1763     # Copy the SOURCES file as well
   1764     cp $DOWNLOAD_DIR/SOURCES $(install_dir)/PACKAGE_SOURCES &&
   1765     cp $TOOLCHAIN_SRC_DIR/SOURCES $(install_dir)/TOOLCHAIN_SOURCES
   1766     fail_panic "Could not copy SOURCES files to install directory"
   1767 
   1768     # Package everything
   1769     pack_archive $TOOLCHAIN_ARCHIVE "`dirname $(install_dir)`" "`basename $(install_dir)`"
   1770 }
   1771 
   1772 task2_define install_toolchain "Install final toolchain"
   1773 task2_depends2 install_toolchain cleanup_toolchain
   1774 cmd_install_toolchain ()
   1775 {
   1776     copy_directory "$(install_dir)" "$PREFIX_DIR/$TOOLCHAIN_NAME"
   1777     cp -f $0 "$PREFIX_DIR/$TOOLCHAIN_NAME/"
   1778 }
   1779 
   1780 # Make sure that the second toolchain depends on the first one
   1781 task_depends configure_binutils_2 install_gcc_1
   1782 
   1783 if [ "$ONLY_SYSROOT" = "yes" ]; then
   1784     MAIN_TASK=copy_sysroot
   1785     COMPLETION_TEXT="Done, see sysroot files in $(sysroot_dir)"
   1786 elif [ -n "$PREFIX_DIR" ]; then
   1787     if [ -z "$BOOTSTRAP" ]; then
   1788         MAIN_TASK=install_toolchain_1
   1789     else
   1790         MAIN_TASK=install_toolchain_2
   1791     fi
   1792     COMPLETION_TEXT="Done, see $PREFIX_DIR/$TOOLCHAIN_NAME"
   1793 else
   1794     if [ -z "$BOOTSTRAP" ]; then
   1795         MAIN_TASK=package_toolchain_1
   1796     else
   1797         MAIN_TASK=package_toolchain_2
   1798     fi
   1799     COMPLETION_TEXT="Done, see $TOOLCHAIN_ARCHIVE"
   1800 fi
   1801 
   1802 if [ "$LIST_TASKS" ]; then
   1803     task_dump
   1804 else
   1805     run_task $MAIN_TASK
   1806     echo "$COMPLETION_TEXT"
   1807 fi
   1808