Home | History | Annotate | Download | only in tools
      1 #!/bin/sh
      2 #
      3 # Copyright (C) 2012 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 # Rebuild the mingw64 cross-toolchain from scratch
     18 #
     19 # Sample (recommended for compatibility reasons) command line:
     20 #
     21 # GOOGLE_PREBUILT=<some folder>
     22 # git clone https://android.googlesource.com/platform/prebuilt $GOOGLE_PREBUILT
     23 # export PATH=$GOOGLE_PREBUILT/linux-x86/toolchain/i686-linux-glibc2.7-4.6/bin:$PATH
     24 # build-mingw64-toolchain.sh --target-arch=i686                       \
     25 #                            --package-dir=i686-w64-mingw32-toolchain \
     26 #                            --binprefix=i686-linux
     27 #
     28 
     29 PROGNAME=$(basename $0)
     30 PROGDIR=$(dirname $0)
     31 PROGDIR=$(cd $PROGDIR && pwd)
     32 
     33 HELP=
     34 VERBOSE=1
     35 
     36 # This will be reset later.
     37 LOG_FILE=/dev/null
     38 
     39 panic ()
     40 {
     41     1>&2 echo "Error: $@"
     42     exit 1
     43 }
     44 
     45 fail_panic ()
     46 {
     47     if [ $? != 0 ]; then
     48         panic "$@"
     49     fi
     50 }
     51 
     52 var_value ()
     53 {
     54     eval echo \"$1\"
     55 }
     56 
     57 var_append ()
     58 {
     59     local _varname=$1
     60     local _varval=$(var_value $_varname)
     61     shift
     62     if [ -z "$_varval" ]; then
     63         eval $_varname=\"$*\"
     64     else
     65         eval $_varname=\$$_varname\" $*\"
     66     fi
     67 }
     68 
     69 run ()
     70 {
     71     if [ "$VERBOSE" -gt 0 ]; then
     72         echo "COMMAND: >>>> $@" >> $LOG_FILE
     73     fi
     74     if [ "$VERBOSE" -gt 1 ]; then
     75         echo "COMMAND: >>>> $@"
     76     fi
     77     if [ "$VERBOSE" -gt 1 ]; then
     78         "$@"
     79     else
     80        "$@" > /dev/null 2>&1
     81     fi
     82 }
     83 
     84 log ()
     85 {
     86     if [ "$LOG_FILE" ]; then
     87         echo "$@" >> $LOG_FILE
     88     fi
     89     if [ "$VERBOSE" -gt 0 ]; then
     90         echo "$@"
     91     fi
     92 }
     93 
     94 # For now, only tested on Linux
     95 OS=$(uname -s)
     96 EXEEXT= # executable extension
     97 case $OS in
     98     Linux) OS=linux;;
     99     Darwin) OS=darwin;;
    100     CYGWIN*|*_NT-*) OS=windows;
    101         if [ "$OSTYPE" = cygwgin ]; then
    102             OS=cygwin
    103         fi
    104         EXEEXT=.exe
    105         ;;
    106 esac
    107 
    108 ARCH=$(uname -m)
    109 case $ARCH in
    110     i?86) ARCH=i686;;
    111     amd64) ARCH=x86_64;;
    112 esac
    113 
    114 case $OS in
    115     linux)
    116         NUM_CORES=$(grep -c -e '^processor' /proc/cpuinfo)
    117         ;;
    118     darwin|freebsd)
    119         NUM_CORES=`sysctl -n hw.ncpu`
    120         ;;
    121     windows|cygwin)
    122         NUM_CORES=$NUMBER_OF_PROCESSORS
    123         ;;
    124     *)  # let's play safe here
    125         NUM_CORES=1
    126         ;;
    127 esac
    128 
    129 # Warn our users, because the script probably fails on anything but Linux
    130 # at that point (e.g. there are strange libtool build breakages on darwin).
    131 if [ "$OS" != "linux" ]; then
    132     echo "WARNING: WARNING: WARNING: THIS SCRIPT PROBABLY ONLY WORKS ON LINUX!!"
    133 fi
    134 
    135 # GMP moving home?
    136 # GMP_VERSION=5.1.0
    137 # GMP_URL=ftp://ftp.gmplib.org/pub/gmp-$GMP_VERSION/
    138 # ..but the old one is still there:
    139 GMP_VERSION=5.0.5
    140 GMP_URL=http://ftp.gnu.org/gnu/gmp/
    141 
    142 MPFR_VERSION=3.1.1
    143 MPC_VERSION=1.0.1
    144 BINUTILS_VERSION=2.22
    145 GCC_VERSION=4.7.2
    146 
    147 # Need at least revision 5166
    148 # For reference, I've built a working NDK with 5445
    149 # (latest as of Sun Feb 3 2013 is 5578)
    150 MINGW_W64_VERSION=svn@5861
    151 
    152 JOBS=$(( $NUM_CORES * 2 ))
    153 
    154 
    155 HOST_BINPREFIX=
    156 TARGET_ARCH=x86_64
    157 TARGET_MULTILIBS=true  # not empty to enable multilib
    158 PACKAGE_DIR=
    159 FORCE_ALL=
    160 FORCE_BUILD=
    161 CLEANUP=
    162 
    163 TEMP_DIR=/tmp/build-mingw64-toolchain-$USER
    164 
    165 for opt; do
    166     optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
    167     case $opt in
    168         -h|-?|--help) HELP=true;;
    169         --verbose) VERBOSE=$(( $VERBOSE + 1 ));;
    170         --quiet) VERBOSE=$(( $VERBOSE - 1 ));;
    171         --binprefix=*) HOST_BINPREFIX=$optarg;;
    172         -j*|--jobs=*) JOBS=$optarg;;
    173         --target-arch=*) TARGET_ARCH=$optarg;;
    174         --no-multilib) TARGET_MULTILIBS="";;
    175         --force-build) FORCE_BUILD=true;;
    176         --force-all) FORCE_ALL=true;;
    177         --work-dir=*) TEMP_DIR=$optarg;;
    178         --package-dir=*) PACKAGE_DIR=$optarg;;
    179         --cleanup) CLEANUP=true;;
    180         --gcc-version=*) GCC_VERSION=$optarg;;
    181         --binutils-version=*) BINUTILS_VERSION=$optarg;;
    182         --gmp-version=*) GMP_VERSION=$optarg;;
    183         --mpfr-version=*) MPFR_VERSION=$optarg;;
    184         --mpc-version=*) MPC_VERSION=$optarg;;
    185         --mingw-version=*) MINGW_W64_VERSION=$optarg;;
    186         -*) panic "Unknown option '$opt', see --help for list of valid ones.";;
    187         *) panic "This script doesn't take any parameter, see --help for details.";;
    188     esac
    189 done
    190 
    191 
    192 if [ "$HELP" ]; then
    193     echo "Usage: $PROGNAME [options]"
    194     echo ""
    195     echo "This program is used to rebuild a mingw64 cross-toolchain from scratch."
    196     echo ""
    197     echo "Valid options:"
    198     echo "  -h|-?|--help                 Print this message."
    199     echo "  --verbose                    Increase verbosity."
    200     echo "  --quiet                      Decrease verbosity."
    201     echo "  --gcc-version=<version>      Select gcc version [$GCC_VERSION]."
    202     echo "  --binutil-version=<version>  Select binutils version [$BINUTILS_VERSION]."
    203     echo "  --gmp-version=<version>      Select libgmp version [$GMP_VERSION]."
    204     echo "  --mpfr-version=<version>     Select libmpfr version [$MPFR_VERSION]."
    205     echo "  --mpc-version=<version>      Select libmpc version [$MPC_VERSION]."
    206     echo "  --mingw-version=<version>    Select mingw-w64 version [$MINGW_W64_VERSION]."
    207     echo "  --jobs=<num>                 Run <num> build tasks in parallel [$JOBS]."
    208     echo "  -j<num>                      Same as --jobs=<num>."
    209     echo "  --binprefix=<prefix>         Specify bin prefix for host toolchain."
    210     echo "  --no-multilib                Disable multilib toolchain build."
    211     echo "  --target-arch=<arch>         Select default target architecture [$TARGET_ARCH]."
    212     echo "  --force-all                  Redo everything from scratch."
    213     echo "  --force-build                Force a rebuild (keep sources)."
    214     echo "  --cleanup                    Remove all temp files after build."
    215     echo "  --work-dir=<path>            Specify work/build directory [$TEMP_DIR]."
    216     echo "  --package-dir=<path>         Package toolchain to directory."
    217     echo ""
    218     exit 0
    219 fi
    220 
    221 if [ "$CLEANUP" ]; then
    222     if [ -z "$PACKAGE_DIR" ]; then
    223         panic "You should only use --cleanup with --package-dir=<path> !".
    224     fi
    225 fi
    226 
    227 BUILD_TAG64=x86_64-linux-gnu
    228 BUILD_TAG32=i686-linux-gnu
    229 
    230 # We don't want debug executables
    231 BUILD_CFLAGS="-O2 -fomit-frame-pointer -s"
    232 BUILD_LDFLAGS=""
    233 
    234 # On Darwin, we want to use the 10.4 / 10.5 / 10.6 SDKs to generate binaries
    235 # that work on "old" platform releases.
    236 if [ "$OS" = darwin ]; then
    237     # Use the check for the availability of a compatibility SDK in Darwin
    238     # this can be used to generate binaries compatible with either Tiger or
    239     # Leopard.
    240     #
    241     # $1: SDK root path
    242     # $2: MacOS X minimum version (e.g. 10.4)
    243     check_darwin_sdk ()
    244     {
    245         if [ -d "$1" ] ; then
    246             var_append BUILD_CFLAGS "-isysroot $1 -mmacosx-version-min=$2 -DMAXOSX_DEPLOYEMENT_TARGET=$2"
    247             var_append BUILD_LDFLAGS "-Wl,-syslibroot,$sdk -mmacosx-version-min=$2"
    248             return 0  # success
    249         fi
    250         return 1
    251     }
    252 
    253     if check_darwin_sdk /Developer/SDKs/MacOSX10.4.sdku 10.4; then
    254         log "Generating Tiger-compatible binaries!"
    255     elif check_darwin_sdk /Developer/SDKs/MacOSX10.5.sdk 10.5; then
    256         log "Generating Leopard-compatible binaries!"
    257     elif check_darwin_sdk /Developer/SDKs/MacOSX10.6.sdk 10.6; then
    258         log "Generating Snow Leopard-compatible binaries!"
    259     else
    260         osx_version=`sw_vers -productVersion`
    261         log "Generating $osx_version-compatible binaries!"
    262     fi
    263 fi
    264 
    265 mkdir -p $TEMP_DIR
    266 if [ "$FORCE_ALL" ]; then
    267     log "Cleaning up work directory..."
    268     rm -rf $TEMP_DIR/*
    269 fi
    270 
    271 LOG_FILE=$TEMP_DIR/build.log
    272 rm -f $LOG_FILE && touch $LOG_FILE
    273 if [ "$VERBOSE" -eq 1 ]; then
    274     echo  "To follow build, use in another terminal: tail -F $LOG_FILE"
    275 fi
    276 
    277 case $TARGET_ARCH in
    278     x86_64) TARGET_BITS=64;;
    279     i686) TARGET_BITS=32;;
    280     *) panic "Invalid --target parameter. Valid values are: x86_64 i686";;
    281 esac
    282 TARGET_TAG=$TARGET_ARCH-w64-mingw32
    283 log "Target arch: $TARGET_TAG"
    284 log "Target bits: $TARGET_BITS"
    285 
    286 # Determine bitness of host architecture
    287 PROBE_CC=${CC:-gcc}
    288 if [ -n "$HOST_BINPREFIX" ]; then
    289     # If $HOST_BINPREFIX is a directory but not ends with '/', append '/'.
    290     # Otherwise, append '-'.
    291     if [ -d "$HOST_BINPREFIX" ] ; then
    292         if [ -n "${HOST_BINPREFIX##*/}" ] ; then
    293 	    HOST_BINPREFIX="${HOST_BINPREFIX}/"
    294 	fi
    295     else
    296         HOST_BINPREFIX="${HOST_BINPREFIX}-"
    297     fi
    298     PROBE_CC=${HOST_BINPREFIX}gcc
    299 fi
    300 echo "Using GCC: $PROBE_CC"
    301 echo "int main() { return 0; }" > $TEMP_DIR/test-host-cc.c
    302 $PROBE_CC -c $TEMP_DIR/test-host-cc.c -o $TEMP_DIR/test-host-cc.o > /dev/null
    303 fail_panic "Host compiler doesn't work: $PROBE_CC"
    304 
    305 file $TEMP_DIR/test-host-cc.o | grep -q -e "x86[_-]64"
    306 if [ $? != 0 ]; then
    307     log "Host compiler generates 32-bit code: $PROBE_CC"
    308     HOST_ARCH=i686
    309     HOST_BITS=32
    310 else
    311     log "Host compiler generates 64-bit code: $PROBE_CC"
    312     HOST_ARCH=x86_64
    313     HOST_BITS=64
    314 fi
    315 
    316 case $OS in
    317     linux) HOST_TAG=$HOST_ARCH-linux-gnu;;
    318     darwin) HOST_TAG=$HOST_ARCH-apple-darwinx11;;
    319     cygwin) HOST_TAG=$HOST_ARCH-pc-cygwin;;
    320     *) panic "Unsupported host operating system!"
    321 esac
    322 log "Host arch: $HOST_TAG"
    323 
    324 download_package ()
    325 {
    326     # Assume the packages are already downloaded under $ARCHIVE_DIR
    327     local PKG_URL=$1
    328     local PKG_NAME=$(basename $PKG_URL)
    329 
    330     case $PKG_NAME in
    331         *.tar.bz2)
    332             PKG_BASENAME=${PKG_NAME%%.tar.bz2}
    333             ;;
    334         *.tar.gz)
    335             PKG_BASENAME=${PKG_NAME%%.tar.gz}
    336             ;;
    337         *)
    338             panic "Unknown archive type: $PKG_NAME"
    339     esac
    340 
    341     if [ ! -f "$ARCHIVE_DIR/$PKG_NAME" ]; then
    342         log "Downloading $PKG_URL..."
    343         (cd $ARCHIVE_DIR && run curl -L -o "$PKG_NAME" "$PKG_URL")
    344         fail_panic "Can't download '$PKG_URL'"
    345     fi
    346 
    347     MD5SUM=$(md5sum $ARCHIVE_DIR/$PKG_NAME | cut -d" " -f1)
    348     echo "$MD5SUM  $PKG_URL" >> $INSTALL_DIR/README
    349 
    350     if [ ! -d "$SRC_DIR/$PKG_BASENAME" ]; then
    351         log "Uncompressing $PKG_URL into $SRC_DIR"
    352         case $PKG_NAME in
    353             *.tar.bz2)
    354                 run tar xjf $ARCHIVE_DIR/$PKG_NAME -C $SRC_DIR
    355                 ;;
    356             *.tar.gz)
    357                 run tar xzf $ARCHIVE_DIR/$PKG_NAME -C $SRC_DIR
    358                 ;;
    359             *)
    360                 panic "Unknown archive type: $PKG_NAME"
    361                 ;;
    362         esac
    363         fail_panic "Can't uncompress $ARCHIVE_DIR/$PKG_NAME"
    364     fi
    365 }
    366 
    367 # Download and unpack source packages from official sites
    368 ARCHIVE_DIR=$TEMP_DIR/archive
    369 SRC_DIR=$TEMP_DIR/src
    370 STAMP_DIR=$TEMP_DIR/timestamps
    371 
    372 mkdir -p $ARCHIVE_DIR
    373 mkdir -p $SRC_DIR
    374 mkdir -p $STAMP_DIR
    375 
    376 INSTALL_DIR=$TEMP_DIR/install-$HOST_TAG/$TARGET_TAG
    377 BUILD_DIR=$TEMP_DIR/build-$HOST_TAG
    378 
    379 if [ "$FORCE_BUILD" ]; then
    380     rm -f $STAMP_DIR/*
    381     rm -rf $INSTALL_DIR
    382     rm -rf $BUILD_DIR
    383 fi
    384 
    385 # Make temp install directory
    386 mkdir -p $INSTALL_DIR
    387 mkdir -p $BUILD_DIR
    388 
    389 # Copy this script
    390 cp $0 $INSTALL_DIR/ &&
    391 echo "This file has been automatically generated on $(date) with the following command:" > $INSTALL_DIR/README &&
    392 echo "$PROGNAME $@" >> $INSTALL_DIR/README &&
    393 echo "" >> $INSTALL_DIR/README &&
    394 echo "The MD5 hashes for the original sources packages are:" >> $INSTALL_DIR/README
    395 fail_panic "Could not copy script to installation directory."
    396 
    397 download_package ${GMP_URL}gmp-${GMP_VERSION}.tar.bz2
    398 download_package http://ftp.gnu.org/gnu/mpfr/mpfr-$MPFR_VERSION.tar.bz2
    399 download_package http://www.multiprecision.org/mpc/download/mpc-$MPC_VERSION.tar.gz
    400 download_package http://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VERSION.tar.bz2
    401 download_package http://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.bz2
    402 
    403 PREFIX_FOR_TARGET=$INSTALL_DIR/$TARGET_TAG
    404 WITH_WIDL=$INSTALL_DIR/bin
    405 MINGW_W64_REVISION=
    406 MINGW_W64_VERSION_NO_REV=$(echo $MINGW_W64_VERSION | awk 'BEGIN { FS="@" }; { print $1 }')
    407 if [ "$MINGW_W64_VERSION_NO_REV" = "svn" ];  then
    408     MINGW_W64_REVISION=$(echo $MINGW_W64_VERSION | awk 'BEGIN { FS="@" }; { print $2 }')
    409     if [ ! -z "$MINGW_W64_REVISION" ] ; then
    410         if [ $MINGW_W64_REVISION -lt 5186 ] ; then
    411             PREFIX_FOR_TARGET=$INSTALL_DIR
    412         fi
    413         if [ $MINGW_W64_REVISION -lt 5252 ] ; then
    414             WITH_WIDL=mingw-w64-widl
    415         elif [ $MINGW_W64_REVISION -lt 5258 ] ; then
    416             WITH_WIDL=$TARGET_TAG-widl
    417         fi
    418         MINGW_W64_REVISION2=-r$MINGW_W64_REVISION
    419         MINGW_W64_REVISION=@${MINGW_W64_REVISION}
    420     fi
    421     MINGW_W64_SRC=$SRC_DIR/mingw-w64-svn$MINGW_W64_REVISION2
    422     MINGW_W64_VERSION=svn
    423 fi
    424 
    425 if [ -z "$MINGW_W64_REVISION" ] ; then
    426     # Released versions of MinGW-w64 don't provide easily accessible information
    427     # about the svn revision which this script needs to know.
    428     fail_panic "Building MinGW-w64 toolchain requires specifying an svn version"
    429 fi
    430 
    431 if [ ! -d $MINGW_W64_SRC ]; then
    432     echo "Checking out https://mingw-w64.svn.sourceforge.net/svnroot/mingw-w64/trunk$MINGW_W64_REVISION $MINGW_W64_SRC"
    433     run svn co https://mingw-w64.svn.sourceforge.net/svnroot/mingw-w64/trunk$MINGW_W64_REVISION $MINGW_W64_SRC
    434     PATCHES_DIR="$PROGDIR/toolchain-patches-host/mingw-w64"
    435     if [ -d "$PATCHES_DIR" ] ; then
    436         PATCHES=$(find "$PATCHES_DIR" -name "*.patch" | sort)
    437         for PATCH in $PATCHES; do
    438             echo "Patching mingw-w64-$MINGW_W64_REVISION with $PATCH"
    439             (cd $MINGW_W64_SRC && run patch -p0 < $PATCH)
    440         done
    441     fi
    442 fi
    443 
    444 # Let's generate the licenses/ directory
    445 LICENSES_DIR=$INSTALL_DIR/licenses/
    446 mkdir -p $LICENSES_DIR
    447 if [ ! -f $STAMP_DIR/licenses ]; then
    448     LICENSE_FILES=$(cd $SRC_DIR && find . -name "COPYING*")
    449     # Copy all license files to $LICENSES_DIR
    450     (tar cf - -C $SRC_DIR $LICENSE_FILES) | (tar xf - -C $LICENSES_DIR)
    451     touch $STAMP_DIR/licenses
    452 fi
    453 
    454 setup_build_env ()
    455 {
    456     local BINPREFIX=$1
    457 
    458     if [ "$BINPREFIX" ]; then
    459         CC=${BINPREFIX}gcc
    460         CXX=${BINPREFIX}g++
    461         LD=${BINPREFIX}ld
    462         AS=${BINPREFIX}as
    463         AR=${BINPREFIX}ar
    464         RANLIB=${BINPREFIX}ranlib
    465         STRIP=${BINPREFIX}strip
    466         export CC CXX LD AS AR RANLIB STRIP
    467     elif [ "$OS" = darwin ]; then
    468         # Needed on OS X otherwise libtool will try to use gcc and $BUILD_CFLAGS
    469         LD=ld
    470     fi
    471 
    472     export CFLAGS="$BUILD_CFLAGS"
    473     export CXXFLAGS="$BUILD_CFLAGS"
    474     export LDFLAGS="$BUILD_LDFLAGS"
    475 }
    476 
    477 setup_install_env ()
    478 {
    479     export PATH=$INSTALL_DIR/bin:$PATH
    480 }
    481 
    482 build_host_package ()
    483 {
    484     local PKGNAME=$1
    485     shift
    486 
    487     if [ ! -f $STAMP_DIR/$PKGNAME ]; then
    488         (
    489             mkdir -p $BUILD_DIR/$PKGNAME &&
    490             cd $BUILD_DIR/$PKGNAME &&
    491             setup_build_env $HOST_BINPREFIX &&
    492             log "$PKGNAME: Configuring" &&
    493             run $SRC_DIR/$PKGNAME/configure "$@"
    494             fail_panic "Can't configure $PKGNAME !!"
    495 
    496             log "$PKGNAME: Building" &&
    497             run make -j$JOBS
    498             fail_panic "Can't build $PKGNAME !!"
    499 
    500             log "$PKGNAME: Installing" &&
    501             run make install
    502             fail_panic "Can't install $PKGNAME"
    503         ) || exit 1
    504         touch $STAMP_DIR/$PKGNAME
    505     fi
    506 }
    507 
    508 export ABI=$HOST_BITS
    509 BASE_HOST_OPTIONS="--prefix=$INSTALL_DIR --disable-shared"
    510 build_host_package gmp-$GMP_VERSION $BASE_HOST_OPTIONS
    511 var_append BASE_HOST_OPTIONS "--with-gmp=$INSTALL_DIR"
    512 
    513 build_host_package mpfr-$MPFR_VERSION $BASE_HOST_OPTIONS
    514 var_append BASE_HOST_OPTIONS "--with-mpfr=$INSTALL_DIR"
    515 
    516 build_host_package mpc-$MPC_VERSION $BASE_HOST_OPTIONS
    517 var_append BASE_HOST_OPTIONS "--with-mpc=$INSTALL_DIR"
    518 
    519 BINUTILS_CONFIGURE_OPTIONS=$BASE_HOST_OPTIONS
    520 var_append BINUTILS_CONFIGURE_OPTIONS "--target=$TARGET_TAG --disable-nls"
    521 if [ "$TARGET_MULTILIBS" ]; then
    522     var_append BINUTILS_CONFIGURE_OPTIONS "--enable-targets=x86_64-w64-mingw32,i686-w64-mingw32"
    523 fi
    524 
    525 var_append BINUTILS_CONFIGURE_OPTIONS "--with-sysroot=$INSTALL_DIR"
    526 
    527 build_host_package binutils-$BINUTILS_VERSION $BINUTILS_CONFIGURE_OPTIONS
    528 
    529 build_mingw_tools ()
    530 {
    531     local PKGNAME=$1
    532     echo "$STAMP_DIR/$PKGNAME"
    533     if [ ! -f "$STAMP_DIR/$PKGNAME" ]; then
    534         (
    535             mkdir -p $BUILD_DIR/$PKGNAME &&
    536             cd $BUILD_DIR/$PKGNAME &&
    537             log "$PKGNAME: Configuring" &&
    538             run $MINGW_W64_SRC/mingw-w64-tools/widl/configure --prefix=$INSTALL_DIR --target=$TARGET_TAG
    539             fail_panic "Can't configure mingw-64-tools"
    540             log "$PKGNAME: Installing" &&
    541             run make install -j$JOBS
    542         ) || exit 1
    543         touch $STAMP_DIR/$PKGNAME
    544     fi
    545 }
    546 
    547 # Install the right mingw64 headers into the sysroot
    548 build_mingw_headers ()
    549 {
    550     local PKGNAME=$1
    551     if [ ! -f "$STAMP_DIR/$PKGNAME" ]; then
    552         (
    553             # If --with-widl only identifies the program name (svn version dependent)...
    554             if [ $(basename "$WITH_WIDL") = "$WITH_WIDL" ] ; then
    555                 # ...then need to add the right path too.
    556                 export PATH=$PATH:$INSTALL_DIR/bin
    557             fi
    558             fail_panic "Can't find widl"
    559             mkdir -p $BUILD_DIR/$PKGNAME &&
    560             cd $BUILD_DIR/$PKGNAME &&
    561             log "$PKGNAME: Configuring" &&
    562             run $MINGW_W64_SRC/mingw-w64-headers/configure --prefix=$PREFIX_FOR_TARGET --host=$TARGET_TAG \
    563                 --build=$HOST_TAG --with-widl=$WITH_WIDL --enable-sdk=all
    564             fail_panic "Can't configure mingw-64-headers"
    565 
    566             run make
    567             log "$PKGNAME: Installing" &&
    568             run make install -j$JOBS &&
    569             run cd $INSTALL_DIR && 
    570             run ln -s $TARGET_TAG mingw &&
    571             run cd $INSTALL_DIR/mingw && 
    572             run ln -s lib lib$TARGET_BITS
    573             fail_panic "Can't configure mingw-64-headers"
    574         ) || exit 1
    575         touch $STAMP_DIR/$PKGNAME
    576     fi
    577 }
    578 
    579 # Slightly different from build_host_package because we need to call
    580 # 'make all-gcc' and 'make install-gcc' as a special case.
    581 #
    582 build_core_gcc ()
    583 {
    584     local PKGNAME=$1
    585     shift
    586 
    587     if [ ! -f "$STAMP_DIR/core-$PKGNAME" ]; then
    588         (
    589             mkdir -p $BUILD_DIR/$PKGNAME &&
    590             cd $BUILD_DIR/$PKGNAME &&
    591             setup_build_env $HOST_BINPREFIX &&
    592             log "core-$PKGNAME: Configuring" &&
    593             run $SRC_DIR/$PKGNAME/configure "$@"
    594             fail_panic "Can't configure $PKGNAME !!"
    595 
    596             log "core-$PKGNAME: Building" &&
    597             run make -j$JOBS all-gcc
    598             fail_panic "Can't build $PKGNAME !!"
    599 
    600             log "core-$PKGNAME: Installing" &&
    601             run make -j$JOBS install-gcc
    602             fail_panic "Can't install $PKGNAME"
    603         ) || exit 1
    604         touch $STAMP_DIR/core-$PKGNAME
    605     fi
    606 }
    607 
    608 
    609 # Build and install the C runtime files needed by the toolchain
    610 build_mingw_crt ()
    611 {
    612     local PKGNAME=$1
    613     shift
    614 
    615     if [ ! -f $STAMP_DIR/$PKGNAME ]; then
    616         (
    617             mkdir -p $BUILD_DIR/$PKGNAME &&
    618             cd $BUILD_DIR/$PKGNAME &&
    619             export PATH=$INSTALL_DIR/bin:$PATH
    620             log "$PKGNAME: Configuring" &&
    621             run $MINGW_W64_SRC/mingw-w64-crt/configure "$@"
    622             fail_panic "Can't configure $PKGNAME !!"
    623 
    624             log "$PKGNAME: Building" &&
    625             run make -j$JOBS
    626             fail_panic "Can't build $PKGNAME !!"
    627 
    628             log "$PKGNAME: Installing" &&
    629             run make -j$JOBS install
    630             fail_panic "Can't install $PKGNAME"
    631         ) || exit 1
    632         touch $STAMP_DIR/$PKGNAME
    633     fi
    634 }
    635 
    636 
    637 build_libgcc ()
    638 {
    639     local PKGNAME=$1
    640     shift
    641 
    642     if [ ! -f "$STAMP_DIR/libgcc-$PKGNAME" ]; then
    643         (
    644             # No configure step here! We're resuming work that was started
    645             # in build_core_gcc.
    646             cd $BUILD_DIR/$PKGNAME &&
    647             setup_build_env $HOST_BINPREFIX &&
    648             log "libgcc-$PKGNAME: Building" &&
    649             run make -j$JOBS
    650             fail_panic "Can't build libgcc-$PKGNAME !!"
    651 
    652             log "libgcc-$PKGNAME: Installing" &&
    653             run make -j$JOBS install
    654             fail_panic "Can't install libgcc-$PKGNAME"
    655         ) || exit 1
    656 
    657         touch "$STAMP_DIR/libgcc-$PKGNAME"
    658     fi
    659 }
    660 
    661 GCC_CONFIGURE_OPTIONS=$BASE_HOST_OPTIONS
    662 var_append GCC_CONFIGURE_OPTIONS "--target=$TARGET_TAG"
    663 if [ "$TARGET_MULTILIBS" ]; then
    664     var_append GCC_CONFIGURE_OPTIONS "--enable-targets=all"
    665 fi
    666 var_append GCC_CONFIGURE_OPTIONS "--enable-languages=c,c++"
    667 var_append GCC_CONFIGURE_OPTIONS "--with-sysroot=$INSTALL_DIR"
    668 
    669 # A bug in MinGW-w64 forces us to build and use widl.
    670 build_mingw_tools mingw-w64-tools
    671 build_mingw_headers mingw-w64-headers
    672 
    673 build_core_gcc gcc-$GCC_VERSION $GCC_CONFIGURE_OPTIONS
    674 
    675 CRT_CONFIGURE_OPTIONS="--host=$TARGET_TAG --with-sysroot=$INSTALL_DIR --prefix=$PREFIX_FOR_TARGET"
    676 if [ "$TARGET_MULTILIBS" ]; then
    677     var_append CRT_CONFIGURE_OPTIONS "--enable-lib32"
    678 fi
    679 
    680 build_mingw_crt mingw-w64-crt $CRT_CONFIGURE_OPTIONS
    681 
    682 build_libgcc gcc-$GCC_VERSION
    683 
    684 if [ "$PACKAGE_DIR" ]; then
    685     mkdir -p $PACKAGE_DIR
    686     fail_panic "Could not create packaging directory: $PACKAGE_DIR"
    687     PACKAGE_NAME=$PACKAGE_DIR/$TARGET_TAG-$OS-$HOST_ARCH.tar.bz2
    688     log "Packaging $TARGET_TAG toolchain to $PACKAGE_NAME"
    689     run tar cjf $PACKAGE_NAME -C $(dirname $INSTALL_DIR) $TARGET_TAG/
    690     fail_panic "Could not package $TARGET_TAG toolchain!"
    691     log "Done. See $PACKAGE_DIR:"
    692     ls -l $PACKAGE_NAME
    693 else
    694     log "Done. See: $INSTALL_DIR"
    695 fi
    696 
    697 if [ "$CLEANUP" ]; then
    698     log "Cleaning up..."
    699     rm -rf $TEMP_DIR/*
    700 fi
    701 
    702 exit 0
    703