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