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