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