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