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