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 host GCC toolchain binaries from sources.
18#
19# NOTE: this script does not rebuild gdb, see build-host-gdb.sh for this.
20#
21
22# include common function and variable definitions
23. `dirname $0`/prebuilt-common.sh
24
25PROGRAM_PARAMETERS="[<toolchain-name>+]"
26PROGRAM_DESCRIPTION="\
27This program is used to rebuild one or more NDK cross-toolchains from scratch.
28To use it, you will first need to call download-toolchain-sources.sh to download
29the toolchain sources, then pass the corresponding directory with the
30--toolchain-src-dir=<path> option.
31
32If you don't pass any parameter, the script will rebuild all NDK toolchains
33for the current host system [$HOST_TAG]. You can otherwise give a list of
34toolchains among the following names:
35
36  arm-linux-androideabi-4.8
37  arm-linux-androideabi-4.9
38  x64-4.8
39  x86-4.9
40  mipsel-linux-android-4.8
41  mipsel-linux-android-4.9
42  aarch64-linux-android-4.9
43  mips64el-linux-android-4.9
44  x86_64-4.9
45
46By default, the script rebuilds the toolchain(s) for you host system [$HOST_TAG],
47but you can use --systems=<tag1>,<tag2>,.. to ask binaries that can run on
48several distinct systems. Each <tag> value in the list can be one of the
49following:
50
51   linux-x86
52   linux-x86_64
53   windows
54   windows-x86  (equivalent to 'windows')
55   windows-x86_64
56   darwin-x86
57   darwin-x86_64
58
59For example, here's how to rebuild the ARM toolchains on Linux
60for four different systems:
61
62  $PROGNAME --toolchain-src-dir=/path/to/toolchain/src \
63    --systems=linux-x86,linux-x86_64,windows,windows-x86_64 \
64    arm-linux-androideabi-4.8 \
65    arm-linux-androideabi-4.9
66
67You can build Windows binaries on Linux if you have a Windows-targetting
68cross-toolchain installed and in your path. Note that the script named
69'build-mingw64-toolchain.sh' can be used to rebuild such a toolchain
70(x86_64-w64-mingw32) from sources if you don't have one available.
71
72Building the toolchains directly under Cygwin/MSys has not be tested and
73is not recommended (it will be *extremely* slow, if it ever works).
74
75On Darwin, the script will try to probe any compatibility SDK installed
76on your development machine and will use the first it finds among a list
77of well-known names. You can however force a specific usage with the
78--darwin-sdk-version=<version> name, where <version> can be one of 10.4, 10.5,
7910.6, 10.7, etc.
80
81The generated binaries should run on 10.5 or higher. You can force a
82different compatibility minimum with --darwin-min-version.
83
84If you want to build Darwin binaries on a non-Darwin machine, you will
85have to define DARWIN_TOOLCHAIN / DARWIN_SYSROOT in your environment first
86(note: this feature is highly experimental).
87
88The script is sufficiently clever to minimize all build steps, especially
89if you try to build several toolchains for several distinct host systems. Note
90however that generating a canadian-cross toolchain (e.g. building on Linux a
91Windows toolchain that targets Android ARM binaries) will force the generation
92of a host toolchain as well, in case it is not listed in your --systems list.
93This is required to generate proper target GCC libraries.
94
95The toolchain binaries are installed under \$NDK_DIR/toolchains by default,
96but you can use --ndk-dir=<path> to specify a different NDK installation path.
97The script will try to build the Gold linker for host/target combination that
98are well supported (Gold doesn't build / is buggy for some of them). However,
99the BFD linker is still the default used by the generated toolchain. You can
100change this behaviour with two options:
101
102   --default-ld=<name>  Changes the default toolchain linker.
103                        <name> can be one of 'default', 'bfd' and 'gold'.
104
105                        For now, 'default' is an alias for 'bfd', but we plan
106                        to map it to 'gold' for some combos in the future, once
107                        we're confident it works reliably
108
109   --force-gold-build   Force the build of the Gold linker, even if it is known
110                        to fail or generate a buggy linker. Only use this for
111                        experimentation (e.g. with your own patched toolchain
112                        sources).
113"
114
115BINUTILS_VERSION=$DEFAULT_BINUTILS_VERSION
116register_var_option "--binutils-version=<version>" BINUTILS_VERSION "Select binutils version"
117
118GMP_VERSION=$DEFAULT_GMP_VERSION
119register_var_option "--gmp-version=<version>" GMP_VERSION "Select gmp version"
120
121MPFR_VERSION=$DEFAULT_MPFR_VERSION
122register_var_option "--mpfr-version=<version>" MPFR_VERSION "Select mpfr version"
123
124MPC_VERSION=$DEFAULT_MPC_VERSION
125register_var_option "--mpc-version=<version>" MPC_VERSION "Select mpc version"
126
127TOOLCHAIN_SRC_DIR=
128register_var_option "--toolchain-src-dir=<path>" TOOLCHAIN_SRC_DIR "Select toolchain source directory"
129
130NDK_DIR=$ANDROID_NDK_ROOT
131register_var_option "--ndk-dir=<path>" NDK_DIR "Select NDK install directory"
132
133BUILD_DIR=
134register_var_option "--build-dir=<path>" BUILD_DIR "Build GCC into directory"
135
136PACKAGE_DIR=
137register_var_option "--package-dir=<path>" PACKAGE_DIR "Package prebuilt tarballs into directory"
138
139HOST_SYSTEMS="$HOST_TAG"
140register_var_option "--systems=<list>" HOST_SYSTEMS "Build binaries for these host systems"
141
142FORCE=
143register_var_option "--force" FORCE "Force full rebuild"
144
145NO_TARGET_LIBS=
146register_var_option "--no-target-libs" NO_TARGET_LIBS "Don't build gcc target libs."
147
148NO_STRIP=
149register_var_option "--no-strip" NO_STRIP "Don't strip generated binaries."
150
151NO_COLOR=
152register_var_option "--no-color" NO_COLOR "Don't output colored text."
153
154if [ "$HOST_OS" = darwin ]; then
155    DARWIN_SDK_VERSION=
156    register_var_option "--darwin-sdk-version=<version>" DARWIN_SDK "Select Darwin SDK version."
157
158    DARWIN_MIN_VERSION=
159    register_var_option "--darwin-min-version=<version>" DARWIN_MIN_VERSION "Select minimum OS X version of generated host toolchains."
160fi
161
162DEFAULT_LD=
163register_var_option "--default-ld=<name>" DEFAULT_LD "Select default linker ('bfd' or 'gold')."
164
165FORCE_GOLD_BUILD=
166register_var_option "--force-gold-build" FORCE_GOLD_BUILD "Always try to build Gold (experimental)."
167
168register_jobs_option
169
170
171extract_parameters "$@"
172
173TOOLCHAINS=$PARAMETERS
174if [ -z "$TOOLCHAINS" ]; then
175    TOOLCHAINS="arm-linux-androideabi-4.8,x86-4.8,mipsel-linux-android-4.8"
176    dump "Auto-config: $TOOLCHAINS"
177fi
178
179if [ -z "$TOOLCHAIN_SRC_DIR" ]; then
180    panic "Please use --toolchain-src-dir=<path> to select toolchain source directory."
181fi
182
183if [ -z "$BUILD_DIR" ]; then
184    BUILD_DIR=/tmp/ndk-$USER/build/host-gcc
185fi
186
187case $DEFAULT_LD in
188    gold|bfd)
189      ;;
190    "")
191      # We always use the default gold linker.
192      # bfd is used for some of the older toolchains or archs not supported by gold.
193      DEFAULT_LD=gold
194      ;;
195    *)
196      panic "Invalid --default-ld name '$DEFAULT_LD', valid values are: bfd gold"
197      ;;
198esac
199
200HOST_SYSTEMS=$(commas_to_spaces $HOST_SYSTEMS)
201TOOLCHAINS=$(commas_to_spaces $TOOLCHAINS)
202
203# The values of HOST_OS/ARCH/TAG will be redefined during the build to
204# match those of the system the generated compiler binaries will run on.
205#
206# Save the original ones into BUILD_XXX variants, corresponding to the
207# machine where the build happens.
208#
209BUILD_OS=$HOST_OS
210BUILD_ARCH=$HOST_ARCH
211BUILD_TAG=$HOST_TAG
212
213# Important note: When identifying a build or host system, there is
214# a difference between 'NDK system tags' and "GNU configuration triplet'.
215#
216# A "system tag" is specific to the NDK and identifies a given host
217# system for the toolchain binaries, valid values:
218#
219#  linux-x86
220#  linux-x86_64
221#  windows        (historical alias to windows-x86)
222#  windows-x86
223#  windows-x86_64
224#  darwin-x86
225#  darwin-x86_64
226#
227# A GNU configuration triplet identifies a system too, but it used by
228# configure scripts, not the NDK. They vary a lot too and some of the
229# scripts are *very* picky about the exact values being used.
230#
231# Typical values that are known to work properly:
232#
233#    i686-linux-gnu       (Linux x86 system, with GNU libc)
234#    x86_64-linux-gnu     (Same, with x86_64 CPU)
235#    i586-mingw32msvc     (Windows 32-bits, MSVCRT.DLL)
236#    i586-pc-mingw32msvc  (same)
237#    i686-w64-mingw32     (same, slightly different sources)
238#    x86_64-w64-mingw32   (Windows 64-bits, MSVCRT.DLL)
239#    i686-apple-darwin    (OS X / Darwin, x86 CPU)
240#    x86_64-apple-darwin  (OS X / Darwin, x86_64 CPU)
241#
242# A cross-toolchain will typically use the GNU configuration triplet as
243# a prefix for all its binaries, but not always. For example, the 'mingw32'
244# package on Ubuntu provides a Windows cross-toolchain that uses the
245# i586-mingw32msvc prefix, but if you try to use it as a configuration
246# triplet when configuring binutils-2.21, the build will fail. You need to
247# pass i586-pc-mingw32msvc instead (binutils-2.19 accepts both).
248#
249# Another issue is that some toolchains need to use additional compiler
250# flags to deal with backwards-compatibility SDKs (Darwin) or 32/64 bit
251# code generation. Note all build scripts accept the same mix of
252# '--with-cflags=...' or 'export CFLAGS' configuration, which makes
253# things pretty difficult to manage.
254#
255# To work-around these issues, the script will generate "wrapper toolchains"
256# with the prefix that the configure scripts expects. I.e. small scripts that
257# redirect to the correct toolchain, eventually adding hidden extra compiler
258# flags. This seems to completely get rid of the problems described above.
259#
260
261
262# $1: system tag (e.g. linux-x86)
263tag_to_os ()
264{
265    local RET
266    case $1 in
267        linux-*) RET="linux";;
268        darwin-*) RET="darwin";;
269        windows|windows-*) RET="windows";;
270    esac
271    echo $RET
272}
273
274# $1: system tag (e.g. linux-x86)
275tag_to_arch ()
276{
277    local RET
278    case $1 in
279        windows|*-x86) RET=x86;;
280        *-x86_64) RET=x86_64;;
281    esac
282    echo $RET
283}
284
285# $1: system tag (e.g. linux-x86)
286tag_to_bits ()
287{
288    local RET
289    case $1 in
290        windows|*-x86) RET=32;;
291        *-x86_64) RET=64;;
292    esac
293    echo $RET
294}
295
296if [ "$NO_COLOR" ]; then
297    COLOR_GREEN=
298    COLOR_PURPLE=
299    COLOR_CYAN=
300    COLOR_END=
301else
302    COLOR_GREEN="\e[32m"
303    COLOR_PURPLE="\e[35m"
304    COLOR_CYAN="\e[36m"
305    COLOR_END="\e[0m"
306fi
307
308# Pretty printing with colors!
309host_text ()
310{
311    printf "[${COLOR_GREEN}${HOST}${COLOR_END}]"
312}
313
314toolchain_text ()
315{
316    printf "[${COLOR_PURPLE}${TOOLCHAIN}${COLOR_END}]"
317}
318
319target_text ()
320{
321    printf "[${COLOR_CYAN}${TARGET}${COLOR_END}]"
322}
323
324arch_text ()
325{
326    # Print arch name in cyan
327    printf "[${COLOR_CYAN}${ARCH}${COLOR_END}]"
328}
329
330# We're going to cheat a little here. If we're only building a linux-x86
331# on a linux-x86_64 machine, we want to change the value of BUILD_TAG
332# to linux-x86 instead to speed-up the build.
333#
334# More generally speaking, we need to verify that if:
335#   - we build a $BUILD_OS-x86 toolchain on a $BUILD_OS-x86_64 machine
336#   - we don't want to build $BUILD_OS-x86_64 either.
337#
338# Then we can change our BUILD values to $BUILD_OS-x86
339# This assumes that the build machine's toolchain can generate both
340# 32-bit and 64-bit binaries with either -m32 or -m64
341#
342BUILD_BUILD_32=
343BUILD_BUILD_64=
344for SYSTEM in $HOST_SYSTEMS; do
345    if [ "$(tag_to_os $SYSTEM)" = "$BUILD_OS" ]; then
346        BUILD_BUILD_OS=true
347        case $(tag_to_bits $SYSTEM) in
348            32) BUILD_BUILD_32=true;;
349            64) BUILD_BUILD_64=true;;
350        esac
351    fi
352done
353
354case $(tag_to_bits $BUILD_TAG) in
355    64)
356        # Building on a 64-bit machine
357        if [ "$BUILD_BUILD_32" -a -z "$BUILD_BUILD_64" ]; then
358            # Ok, we want to build a 32-bit toolchain on a 64-bit machine
359            # So cheat a little now :-)
360            BUILD_ARCH=x86
361            BUILD_TAG=$BUILD_OS-$BUILD_ARCH
362            dump "Forcing build config: $BUILD_TAG"
363        fi
364        ;;
365esac
366
367BUILD_BITS=$(tag_to_bits $BUILD_TAG)
368
369# On Darwin, parallel installs of certain libraries do not work on
370# some multi-core machines. So define NUM_BUILD_JOBS as 1 on this
371# platform.
372case $BUILD_OS in
373    darwin) NUM_INSTALL_JOBS=1;;
374    *) NUM_INSTALL_JOBS=$NUM_JOBS;;
375esac
376
377tag_to_config_triplet ()
378{
379    local RET
380    case $1 in
381        linux-x86) RET=i686-linux-gnu;;
382        linux-x86_64) RET=x86_64-linux-gnu;;
383        darwin-x86) RET=i686-apple-darwin;;
384        darwin-x86_64) RET=x86_64-apple-darwin;;
385        windows|windows-x86) RET=i586-pc-mingw32msvc;;
386        windows-x86_64) RET=x86_64-w64-mingw32;;
387    esac
388    echo "$RET"
389}
390
391run_on_setup ()
392{
393    if [ "$PHASE" = setup ]; then
394        run "$@"
395    fi
396}
397
398setup_build ()
399{
400    run_on_setup mkdir -p "$BUILD_DIR"
401    if [ -n "$FORCE" ]; then
402        rm -rf "$BUILD_DIR"/*
403    fi
404
405    TOP_BUILD_DIR=$BUILD_DIR
406
407    setup_default_log_file $BUILD_DIR/build.log
408
409    WRAPPERS_DIR="$BUILD_DIR/toolchain-wrappers"
410    run_on_setup mkdir -p "$WRAPPERS_DIR" && run_on_setup rm -rf "$WRAPPERS_DIR/*"
411
412    STAMPS_DIR="$BUILD_DIR/timestamps"
413    run_on_setup mkdir -p "$STAMPS_DIR"
414    if [ -n "$FORCE" ]; then
415        run_on_setup rm -f "$STAMPS_DIR"/*
416    fi
417
418    if [ "$PACKAGE_DIR" ]; then
419        mkdir -p "$PACKAGE_DIR"
420        fail_panic "Can't create packaging directory: $PACKAGE_DIR"
421    fi
422
423    BUILD=$(tag_to_config_triplet $BUILD_TAG)
424}
425
426stamps_do ()
427{
428    local NAME=$1
429    shift
430    if [ ! -f "$STAMPS_DIR/$NAME" ]; then
431        "$@"
432        fail_panic
433        mkdir -p "$STAMPS_DIR" && touch "$STAMPS_DIR/$NAME"
434    fi
435}
436
437# Check that a given compiler generates code correctly
438#
439# This is to detect bad/broken toolchains, e.g. amd64-mingw32msvc
440# is totally broken on Ubuntu 10.10 and 11.04
441#
442# $1: compiler
443# $2: optional extra flags
444#
445check_compiler ()
446{
447    local CC="$1"
448    local TMPC=/tmp/build-host-gcc-$USER-$$.c
449    local TMPE=${TMPC%%.c}
450    local TMPL=$TMPC.log
451    local RET
452    shift
453    cat > $TMPC <<EOF
454int main(void) { return 0; }
455EOF
456    log_n "Checking compiler code generation ($CC)... "
457    $CC -o $TMPE $TMPC "$@" >$TMPL 2>&1
458    RET=$?
459    rm -f $TMPC $TMPE $TMPL
460    if [ "$RET" = 0 ]; then
461        log "yes"
462    else
463        log "no"
464    fi
465    return $RET
466}
467
468
469# $1: toolchain install dir
470# $2: toolchain prefix, no trailing dash (e.g. arm-linux-androideabi)
471# $3: optional -m32 or -m64.
472try_host_fullprefix ()
473{
474    local PREFIX="$1/bin/$2"
475    shift; shift;
476    if [ -z "$HOST_FULLPREFIX" ]; then
477        local GCC="$PREFIX-gcc"
478        if [ -f "$GCC" ]; then
479            if check_compiler "$GCC" "$@"; then
480                HOST_FULLPREFIX="${GCC%%gcc}"
481                dump "$(host_text) Using host gcc: $GCC $@"
482            else
483                dump "$(host_text) Ignoring broken host gcc: $GCC $@"
484            fi
485        fi
486    fi
487}
488
489# $1: host prefix, no trailing slash (e.g. i686-linux-android)
490# $2: optional compiler args (should be empty, -m32 or -m64)
491try_host_prefix ()
492{
493    local PREFIX="$1"
494    shift
495    if [ -z "$HOST_FULLPREFIX" ]; then
496        local GCC="$(which $PREFIX-gcc 2>/dev/null)"
497        if [ "$GCC" -a -e "$GCC" ]; then
498            if check_compiler "$GCC" "$@"; then
499                HOST_FULLPREFIX=${GCC%%gcc}
500                dump "$(host_text) Using host gcc: ${HOST_FULLPREFIX}gcc $@"
501            else
502                dump "$(host_text) Ignoring broken host gcc: $GCC $@"
503            fi
504        fi
505    fi
506}
507
508# Used to determine the minimum possible Darwin version that a Darwin SDK
509# can target. This actually depends from the host architecture.
510# $1: Host architecture name
511# out: SDK version number (e.g. 10.4 or 10.5)
512darwin_arch_to_min_version ()
513{
514  if [ "$DARWIN_MIN_VERSION" ]; then
515    echo "$DARWIN_MIN_VERSION"
516  elif [ "$1" = "x86" ]; then
517    echo "10.4"
518  else
519    echo "10.5"
520  fi
521}
522
523# Use the check for the availability of a compatibility SDK in Darwin
524# this can be used to generate binaries compatible with either Tiger or
525# Leopard.
526#
527# $1: SDK root path
528# $2: Darwin architecture
529check_darwin_sdk ()
530{
531    if [ -d "$1" -a -z "$HOST_CFLAGS" ] ; then
532        local MINVER=$(darwin_arch_to_min_version $2)
533        HOST_CFLAGS="-isysroot $1 -mmacosx-version-min=$MINVER -DMAXOSX_DEPLOYEMENT_TARGET=$MINVER"
534        HOST_CXXFLAGS=$HOST_CFLAGS
535        HOST_LDFLAGS="-syslibroot $1 -mmacosx-version-min=$MINVER"
536        dump "Generating $MINVER-compatible binaries."
537        return 0  # success
538    fi
539    return 1
540}
541
542# Check that a given compiler generates 32 or 64 bit code.
543# $1: compiler full path (.e.g  /path/to/fullprefix-gcc)
544# $2: 32 or 64
545# $3: extract compiler flags
546# Return: success iff the compiler generates $2-bits code
547check_compiler_bitness ()
548{
549    local CC="$1"
550    local BITS="$2"
551    local TMPC=/tmp/build-host-gcc-bits-$USER-$$.c
552    local TMPL=$TMPC.log
553    local RET
554    shift; shift;
555    cat > $TMPC <<EOF
556/* this program will fail to compile if the compiler doesn't generate BITS-bits code */
557int tab[1-2*(sizeof(void*)*8 != BITS)];
558EOF
559    dump_n "$(host_text) Checking that the compiler generates $BITS-bits code ($@)... "
560    $CC -c -DBITS=$BITS -o /dev/null $TMPC $HOST_CFLAGS "$@" > $TMPL 2>&1
561    RET=$?
562    rm -f $TMPC $TMPL
563    if [ "$RET" = 0 ]; then
564        dump "yes"
565    else
566        dump "no"
567    fi
568    return $RET
569}
570
571# This function probes the system to find the best toolchain or cross-toolchain
572# to build binaries that run on a given host system. After that, it generates
573# a wrapper toolchain under $WRAPPERS_DIR with a prefix of ${HOST}-
574# where $HOST is a GNU configuration name.
575#
576# Important: this script might redefine $HOST to a different value!
577# Important: must be called after setup_build.
578#
579# $1: NDK system tag (e.g. linux-x86)
580#
581select_toolchain_for_host ()
582{
583    local HOST_CFLAGS HOST_CXXFLAGS HOST_LDFLAGS HOST_FULLPREFIX DARWIN_ARCH
584
585    # We do all the complex auto-detection magic in the setup phase,
586    # then save the result in host-specific global variables.
587    #
588    # In the build phase, we will simply restore the values into the
589    # global HOST_FULLPREFIX / HOST_BUILD_DIR
590    # variables.
591    #
592
593    # Try to find the best toolchain to do that job, assuming we are in
594    # a full Android platform source checkout, we can look at the prebuilts/
595    # directory.
596    case $1 in
597        linux-x86)
598            # If possible, automatically use our custom toolchain to generate
599            # 32-bit executables that work on Ubuntu 8.04 and higher.
600            try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" i686-linux
601            try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.4.3" i686-linux
602            try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilt/linux-x86/toolchain/i686-linux-glibc2.7-4.4.3" i686-linux
603            try_host_prefix i686-linux-gnu
604            try_host_prefix i686-linux
605            try_host_prefix x86_64-linux-gnu -m32
606            try_host_prefix x86_64-linux -m32
607            ;;
608
609        linux-x86_64)
610            # If possible, automaticaly use our custom toolchain to generate
611            # 64-bit executables that work on Ubuntu 8.04 and higher.
612            try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" x86_64-linux
613            try_host_prefix x86_64-linux-gnu
614            try_host_prefix x84_64-linux
615            try_host_prefix i686-linux-gnu -m64
616            try_host_prefix i686-linux -m64
617            ;;
618
619        darwin-*)
620            DARWIN_ARCH=$(tag_to_arch $1)
621            case $BUILD_OS in
622                darwin)
623                    if [ "$DARWIN_SDK_VERSION" ]; then
624                        # Compute SDK subdirectory name
625                        case $DARWIN_SDK_VERSION in
626                            10.4) DARWIN_SDK_SUBDIR=$DARWIN_SDK.sdku;;
627                            *) DARWIN_SDK_SUBDIR=$DARWIN_SDK.sdk;;
628                        esac
629                        # Since xCode moved to the App Store the SDKs have been 'sandboxed' into the Xcode.app folder.
630                        check_darwin_sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$DARWIN_SDK_SUBDIR $DARWIN_ARCH
631                        check_darwin_sdk /Developer/SDKs/MacOSX$DARWIN_SDK_SUBDIR $DARWIN_ARCH
632                    else
633                        # Since xCode moved to the App Store the SDKs have been 'sandboxed' into the Xcode.app folder.
634                        check_darwin_sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk $DARWIN_ARCH
635                        check_darwin_sdk /Developer/SDKs/MacOSX10.7.sdk  $DARWIN_ARCH
636                        check_darwin_sdk /Developer/SDKs/MacOSX10.6.sdk  $DARWIN_ARCH
637                        # NOTE: The 10.5.sdk on Lion is buggy and cannot build basic C++ programs
638                        #check_darwin_sdk /Developer/SDKs/MacOSX10.5.sdk  $DARWIN_ARCH
639                        # NOTE: The 10.4.sdku is not available anymore and could not be tested.
640                        #check_darwin_sdk /Developer/SDKs/MacOSX10.4.sdku $DARWIN_ARCH
641                    fi
642                    if [ -z "$HOST_CFLAGS" ]; then
643                        local version="$(sw_vers -productVersion)"
644                        log "Generating $version-compatible binaries!"
645                    fi
646                    ;;
647                *)
648                    if [ -z "$DARWIN_TOOLCHAIN" -o -z "$DARWIN_SYSROOT" ]; then
649                        dump "If you want to build Darwin binaries on a non-Darwin machine,"
650                        dump "Please define DARWIN_TOOLCHAIN to name it, and DARWIN_SYSROOT to point"
651                        dump "to the SDK. For example:"
652                        dump ""
653                        dump "   DARWIN_TOOLCHAIN=\"i686-apple-darwin11\""
654                        dump "   DARWIN_SYSROOT=\"~/darwin-cross/MacOSX10.7.sdk\""
655                        dump "   export DARWIN_TOOLCHAIN DARWIN_SYSROOT"
656                        dump ""
657                        exit 1
658                    fi
659                    local DARWINMINVER=$(darwin_arch_to_min_version $2)
660                    check_darwin_sdk $DARWIN_SYSROOT $DARWINARCH
661                    try_host_prefix "$DARWIN_TOOLCHAIN" -m$(tag_to_bits $1) --sysroot "$DARWIN_SYSROOT"
662                    if [ -z "$HOST_FULLPREFIX" ]; then
663                        dump "It looks like $DARWIN_TOOLCHAIN-gcc is not in your path, or does not work correctly!"
664                        exit 1
665                    fi
666                    dump "Using darwin cross-toolchain: ${HOST_FULLPREFIX}gcc"
667                    ;;
668            esac
669            ;;
670
671        windows|windows-x86)
672            case $BUILD_OS in
673                linux)
674                    # We favor these because they are more recent, and because
675                    # we have a script to rebuild them from scratch. See
676                    # build-mingw64-toolchain.sh.
677                    try_host_prefix x86_64-w64-mingw32 -m32
678                    try_host_prefix i686-w64-mingw32
679                    # Typically provided by the 'mingw32' package on Debian
680                    # and Ubuntu systems.
681                    try_host_prefix i586-mingw32msvc
682                    # Special note for Fedora: this distribution used
683                    # to have a mingw32-gcc package that provided a 32-bit
684                    # only cross-toolchain named i686-pc-mingw32.
685                    # Later versions of the distro now provide a new package
686                    # named mingw-gcc which provides i686-w64-mingw32 and
687                    # x86_64-w64-mingw32 instead.
688                    try_host_prefix i686-pc-mingw32
689                    if [ -z "$HOST_FULLPREFIX" ]; then
690                        dump "There is no Windows cross-compiler. Ensure that you"
691                        dump "have one of these installed and in your path:"
692                        dump "   x86_64-w64-mingw32-gcc  (see build-mingw64-toolchain.sh)"
693                        dump "   i686-w64-mingw32-gcc    (see build-mingw64-toolchain.sh)"
694                        dump "   i586-mingw32msvc-gcc    ('mingw32' Debian/Ubuntu package)"
695                        dump "   i686-pc-mingw32         (on Fedora)"
696                        dump ""
697                        exit 1
698                    fi
699                    # Adjust $HOST to match the toolchain to ensure proper builds.
700                    # I.e. chose configuration triplets that are known to work
701                    # with the gmp/mpfr/mpc/binutils/gcc configure scripts.
702                    case $HOST_FULLPREFIX in
703                        *-mingw32msvc-*|i686-pc-mingw32)
704                            HOST=i586-pc-mingw32msvc
705                            ;;
706                        *)
707                            HOST=i686-w64-mingw32msvc
708                            ;;
709                    esac
710                    ;;
711                *) panic "Sorry, this script only supports building windows binaries on Linux."
712                ;;
713            esac
714            ;;
715
716        windows-x86_64)
717            # Sanity check for GMP which doesn't build with x86_64-w64-mingw32-gcc
718            # before 5.0. We already have 5.0.5 in AOSP toolchain source tree, so
719            # suggest it here.
720            if ! version_is_at_least $GMP_VERSION 5.0; then
721                dump "You cannot build a 64-bit Windows toolchain with this version of libgmp."
722                dump "Please use --gmp-version=5.0.5 to fix this."
723                exit 1
724            fi
725            case $BUILD_OS in
726                linux)
727                    # See comments above for windows-x86
728                    try_host_prefix x86_64-w64-mingw32
729                    try_host_prefix i686-w64-mingw32 -m64
730                    # Beware that this package is completely broken on many
731                    # versions of no vinegar Ubuntu (i.e. it fails at building trivial
732                    # programs).
733                    try_host_prefix amd64-mingw32msvc
734                    # There is no x86_64-pc-mingw32 toolchain on Fedora.
735                    if [ -z "$HOST_FULLPREFIX" ]; then
736                        dump "There is no Windows cross-compiler in your path. Ensure you"
737                        dump "have one of these installed and in your path:"
738                        dump "   x86_64-w64-mingw32-gcc  (see build-mingw64-toolchain.sh)"
739                        dump "   i686-w64-mingw32-gcc    (see build-mingw64-toolchain.sh)"
740                        dump "   amd64-mingw32msvc-gcc   (Debian/Ubuntu - broken until Ubuntu 11.10)"
741                        dump ""
742                        exit 1
743                    fi
744                    # See comment above for windows-x86
745                    case $HOST_FULLPREFIX in
746                        *-mingw32msvc*)
747                            # Actually, this has never been tested.
748                            HOST=amd64-pc-mingw32msvc
749                            ;;
750                        *)
751                            HOST=x86_64-w64-mingw32
752                            ;;
753                    esac
754                    ;;
755
756                *) panic "Sorry, this script only supports building windows binaries on Linux."
757                ;;
758            esac
759            ;;
760    esac
761
762    mkdir -p "$(host_build_dir)"
763    if [ "$FORCE" ]; then
764        rm -rf "$(host_build_dir)"/*
765    fi
766
767    # Determine the default bitness of our compiler. It it doesn't match
768    # HOST_BITS, tries to see if it supports -m32 or -m64 to change it.
769    if ! check_compiler_bitness ${HOST_FULLPREFIX}gcc $HOST_BITS; then
770        TRY_CFLAGS=
771        case $HOST_BITS in
772            32) TRY_CFLAGS=-m32;;
773            64) TRY_CFLAGS=-m64;;
774        esac
775        if ! check_compiler_bitness ${HOST_FULLPREFIX}gcc $HOST_BITS $TRY_CFLAGS; then
776            panic "Can't find a way to generate $HOST_BITS binaries with this compiler: ${HOST_FULLPREFIX}gcc"
777        fi
778        HOST_CFLAGS=$HOST_CFLAGS" "$TRY_CFLAGS
779        HOST_CXXFLAGS=$HOST_CXXFLAGS" "$TRY_CFLAGS
780    fi
781
782    # Support for ccache, to speed up rebuilds.
783    DST_PREFIX=$HOST_FULLPREFIX
784    if [ "$NDK_CCACHE" ]; then
785        DST_PREFIX="$NDK_CCACHE $HOST_FULLPREFIX"
786    fi
787
788    # We're going to generate a wrapper toolchain with the $HOST prefix
789    # i.e. if $HOST is 'i686-linux-gnu', then we're going to generate a
790    # wrapper toolchain named 'i686-linux-gnu-gcc' that will redirect
791    # to whatever HOST_FULLPREFIX points to, with appropriate modifier
792    # compiler/linker flags.
793    #
794    # This helps tremendously getting stuff to compile with the GCC
795    # configure scripts.
796    #
797    run $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh "$WRAPPERS_DIR" \
798        --src-prefix="$HOST-" \
799        --dst-prefix="$DST_PREFIX" \
800        --cflags="$HOST_CFLAGS" \
801        --cxxflags="$HOST_CXXFLAGS" \
802        --ldflags="$HOST_LDFLAGS"
803}
804
805# Call this before anything else to setup a few important variables that are
806# used consistently to build any host-specific binaries.
807#
808# $1: Host system name (e.g. linux-x86), this is the name of the host system
809#     where the generated GCC binaries will run, not the current machine's
810#     type (this one is in $ORIGINAL_HOST_TAG instead).
811#
812setup_build_for_host ()
813{
814    local HOST_VARNAME=$(dashes_to_underscores $1)
815    local HOST_VAR=_HOST_${HOST_VARNAME}
816
817    # Determine the host configuration triplet in $HOST
818    HOST=$(tag_to_config_triplet $1)
819    HOST_OS=$(tag_to_os $1)
820    HOST_ARCH=$(tag_to_arch $1)
821    HOST_BITS=$(tag_to_bits $1)
822    HOST_TAG=$1
823
824    # Note: since select_toolchain_for_host can change the value of $HOST
825    # we need to save it in a variable to later get the correct one when
826    # this function is called again.
827    if [ -z "$(var_value ${HOST_VAR}_SETUP)" ]; then
828        select_toolchain_for_host $1
829        var_assign ${HOST_VAR}_CONFIG $HOST
830        var_assign ${HOST_VAR}_SETUP true
831    else
832        HOST=$(var_value ${HOST_VAR}_CONFIG)
833    fi
834}
835
836# Returns the location of all $HOST specific files (build and install)
837host_build_dir ()
838{
839    echo "$TOP_BUILD_DIR/$HOST"
840}
841
842# Return the location of the build directory for a specific component
843# $1: component name (e.g. gmp-4.2.4)
844host_build_dir_for ()
845{
846    echo "$(host_build_dir)/build-$1"
847}
848
849# Returns the install location of the $HOST pre-reqs libraries
850host_prereqs_install_dir ()
851{
852    echo "$(host_build_dir)/temp-prereqs"
853}
854
855# Returns the install location of the $HOST binutils cross-toolchain
856host_binutils_install_dir ()
857{
858    echo "$(host_build_dir)/temp-binutils-$BINUTILS_VERSION-$TARGET"
859}
860
861# Returns the install location of the $HOST binutils cross-toolchain
862build_binutils_install_dir ()
863{
864    echo "$TOP_BUILD_DIR/$BUILD/temp-binutils-$BINUTILS_VERSION-$TARGET"
865}
866
867# Returns the install location of the $HOST gcc cross-toolchain
868host_gcc_install_dir ()
869{
870    echo "$(host_build_dir)/temp-$TOOLCHAIN"
871}
872
873# Returns the install location of the $BUILD gcc cross-toolchain
874build_gcc_install_dir ()
875{
876    echo "$TOP_BUILD_DIR/$BUILD/temp-$TOOLCHAIN"
877}
878
879
880# Location of the host sysroot used during the build
881host_sysroot ()
882{
883    # This must be a sub-directory of $(host_gcc_install_dir)
884    # to generate relocatable binaries that are used by
885    # standalone versions of the toolchain.
886    #
887    # If you change this, you will need to modify make-standalone-toolchain.sh
888    # as well.
889    #
890    echo "$(host_gcc_install_dir)/sysroot"
891}
892
893# Returns the final install location of the $HOST toolchain
894# This ones contains the binutils binaries, the gcc ones,
895# the target libraries, but does *not* include the sysroot
896# and other stuff (e.g. documentation like info or man files).
897#
898host_gcc_final_dir ()
899{
900    echo "$(host_build_dir)/final-$TOOLCHAIN"
901}
902
903setup_build_for_toolchain ()
904{
905    GCC_VERSION=$(extract_version $1)
906    BINUTILS_VERSION=$(get_default_binutils_version_for_gcc $1)
907
908    TARGET_ARCH=$(echo $1 | cut -d - -f 1)
909
910    # NOTE: The 'mipsel' toolchain architecture name maps to the 'mips'
911    # NDK architecture name.
912    case $TARGET_ARCH in
913        arm) TARGET=arm-linux-androideabi;;
914        x86) TARGET=i686-linux-android;;
915        x86_64) TARGET=x86_64-linux-android;;
916        mips|mipsel) TARGET=mipsel-linux-android; TARGET_ARCH=mips;;
917        *) panic "Unknown target toolchain architecture: $TARGET_ARCH"
918    esac
919
920    # MPC is only needed starting with GCC 4.5
921    HOST_NEED_MPC=
922    if version_is_at_least $GCC_VERSION 4.5; then
923        HOST_NEED_MPC=true
924    fi
925
926    # TODO: We will need to place these under
927    #      $NDK_DIR/prebuilts/$HOST/android-$TARGET_ARCH-gcc-$GCC_VERSION/
928    #      in a future patch.
929    TOOLCHAIN_SUB_DIR=toolchains/$TOOLCHAIN/prebuilt/$HOST_TAG
930    TOOLCHAIN_INSTALL_DIR=$NDK_DIR/$TOOLCHAIN_SUB_DIR
931
932    # These will go into CFLAGS_FOR_TARGET and others during the build
933    # of GCC target libraries.
934    if [ -z "$NO_STRIP" ]; then
935        TARGET_CFLAGS="-O2 -s"
936    else
937        TARGET_CFLAGS="-Os -g"
938    fi
939
940    TARGET_CXXFLAGS=$TARGET_CFLAGS
941    TARGET_LDFLAGS=""
942
943    case $TARGET_ARCH in
944        mips)
945        # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time
946        # You can't really build these separately at the moment.
947        # Add -fpic, because MIPS NDK will need to link .a into .so.
948        TARGET_CFLAGS=$TARGET_CFLAGS" -fexceptions -fpic"
949        TARGET_CXXFLAGS=$TARGET_CXXFLAGS" -frtti -fpic"
950        ;;
951    esac
952}
953
954# This function is used to setup the build environment whenever we
955# generate host-specific binaries.
956#
957setup_host_env ()
958{
959    CC=$HOST-gcc
960    CXX=$HOST-g++
961    LD=$HOST-ld
962    AR=$HOST-ar
963    AS=$HOST-as
964    RANLIB=$HOST-ranlib
965    NM=$HOST-nm
966    STRIP=$HOST-strip
967    STRINGS=$HOST-strings
968    export CC CXX AS LD AR RANLIB STRIP STRINGS NM
969
970    CFLAGS=
971    CXXFLAGS=
972    LDFLAGS=
973    if [ -z "$NO_STRIP" ]; then
974        CFLAGS="-O2 -Os -fomit-frame-pointer -s"
975        CXXFLAGS=$CFLAGS
976    fi
977
978    # This should only used when building the target GCC libraries
979    CFLAGS_FOR_TARGET=$TARGET_CFLAGS
980    CXXFLAGS_FOR_TARGET=$TARGET_CXXFLAGS
981    LDFLAGS_FOR_TARGET=$TARGET_LDFLAGS
982
983    export CFLAGS CXXFLAGS LDFLAGS CFLAGS_FOR_TARGET CXXFLAGS_FOR_TARGET LDFLAGS_FOR_TARGET
984
985    PATH=$WRAPPERS_DIR:$PATH
986}
987
988# $1: NDK architecture name (e.g. 'arm')
989arch_sysroot_install_dir ()
990{
991    echo "$BUILD_DIR/arch-$1/sysroot"
992}
993
994# $1: NDK architecture name (e.g. 'arm')
995arch_sysroot_dir ()
996{
997    echo "$(arch_sysroot_install_dir $1)/$(get_default_platform_sysroot_for_arch $1)"
998}
999
1000# $1: architecture name
1001gen_minimal_sysroot ()
1002{
1003    local ARCH=$1
1004    local INSTALL_DIR=$(arch_sysroot_install_dir $ARCH)
1005
1006    dump "$(arch_text) Generating minimal sysroot."
1007    run2 $NDK_BUILDTOOLS_PATH/gen-platforms.sh --minimal --arch=$ARCH --dst-dir="$INSTALL_DIR"
1008}
1009
1010
1011# $1: gmp version
1012extract_gmp_sources ()
1013{
1014    local SRC_DIR="$TOP_BUILD_DIR/temp-src"
1015
1016    dump "Extracting gmp-$1"
1017    run2 mkdir -p "$SRC_DIR" &&
1018    run2 tar xjf "$TOOLCHAIN_SRC_DIR/gmp/gmp-$1.tar.bz2" -C "$SRC_DIR"
1019}
1020
1021# $1: gmp version
1022build_gmp ()
1023{
1024    local SRC_DIR="$TOP_BUILD_DIR/temp-src/gmp-$1"
1025    local INSTALL_DIR="$(host_prereqs_install_dir)"
1026    local BUILD_DIR
1027
1028    stamps_do extract-gmp-$1 extract_gmp_sources $1
1029
1030    dump "$(host_text) Building gmp-$1"
1031    (
1032        setup_host_env &&
1033        BUILD_DIR="$(host_build_dir_for gmp-$GMP_VERSION)" &&
1034        run2 mkdir -p "$BUILD_DIR" && run2 rm -rf "$BUILD_DIR"/* &&
1035        cd "$BUILD_DIR" &&
1036        run2 "$SRC_DIR"/configure \
1037            --prefix=$INSTALL_DIR \
1038            --build=$BUILD \
1039            --host=$HOST \
1040            --disable-shared &&
1041        run2 make -j$NUM_JOBS &&
1042        run2 make install -j$NUM_INSTALL_JOBS
1043    )
1044    return $?
1045}
1046
1047extract_mpfr_sources ()
1048{
1049    local SRC_DIR="$TOP_BUILD_DIR/temp-src"
1050
1051    dump "Extracting mpfr-$1"
1052    run2 mkdir -p "$SRC_DIR" &&
1053    run2 tar xjf "$TOOLCHAIN_SRC_DIR/mpfr/mpfr-$1.tar.bz2" -C "$SRC_DIR"
1054}
1055
1056# $1: mpfr-version
1057build_mpfr ()
1058{
1059    local SRC_DIR="$TOP_BUILD_DIR/temp-src/mpfr-$1"
1060    local INSTALL_DIR="$(host_prereqs_install_dir)"
1061    local BUILD_DIR
1062
1063    stamps_do extract-mpfr-$MPFR_VERSION extract_mpfr_sources $1
1064
1065    stamps_do build-gmp-$GMP_VERSION-$HOST build_gmp $GMP_VERSION
1066
1067    dump "$(host_text) Building mpfr-$1"
1068    (
1069        setup_host_env &&
1070        BUILD_DIR="$(host_build_dir_for mpfr-$MPFR_VERSION)" &&
1071        run2 mkdir -p "$BUILD_DIR" && run2 rm -rf "$BUILD_DIR"/* &&
1072        cd $BUILD_DIR &&
1073        run2 "$SRC_DIR"/configure \
1074            --prefix=$INSTALL_DIR \
1075            --build=$BUILD \
1076            --host=$HOST \
1077            --disable-shared \
1078            --with-gmp=$INSTALL_DIR &&
1079        run2 make -j$NUM_JOBS &&
1080        run2 make -j$NUM_INSTALL_JOBS install
1081    )
1082    return $?
1083}
1084
1085# $1: mpc-version
1086extract_mpc_sources ()
1087{
1088    local SRC_DIR="$TOP_BUILD_DIR/temp-src"
1089
1090    dump "Extracting mpc-$1"
1091    run2 mkdir -p "$SRC_DIR" &&
1092    run2 tar xzf "$TOOLCHAIN_SRC_DIR/mpc/mpc-$1.tar.gz" -C "$SRC_DIR"
1093}
1094
1095
1096# $1: mpc-version
1097build_mpc ()
1098{
1099    local SRC_DIR="$TOP_BUILD_DIR/temp-src/mpc-$1"
1100    local INSTALL_DIR="$(host_prereqs_install_dir)"
1101    local BUILD_DIR
1102
1103    stamps_do extract-mpc-$1 extract_mpc_sources $1
1104
1105    stamps_do build-mpfr-$MPFR_VERSION-$HOST build_mpfr $MPFR_VERSION
1106
1107    dump "$(host_text) Building mpc-$1"
1108    (
1109        setup_host_env &&
1110        BUILD_DIR="$(host_build_dir_for mpc-$MPC_VERSION)" &&
1111        run2 mkdir -p "$BUILD_DIR" && run2 rm -rf "$BUILD_DIR"/* &&
1112        cd $BUILD_DIR &&
1113        run2 "$SRC_DIR"/configure \
1114            --prefix=$INSTALL_DIR \
1115            --build=$BUILD \
1116            --host=$HOST \
1117            --disable-shared \
1118            --with-gmp=$INSTALL_DIR \
1119            --with-mpfr=$INSTALL_DIR &&
1120        run2 make -j$NUM_JOBS &&
1121        run2 make -j$NUM_INSTALL_JOBS install
1122    )
1123    return $?
1124}
1125
1126# Build all pre-required host libraries (gmp, mpfr, etc...) that are needed
1127# by binutils and gcc, as static libraries that will be placed under
1128# $HOST_BUILD_DIR/temp-install
1129#
1130# $1: toolchain source directory
1131#
1132build_host_prereqs ()
1133{
1134    local INSTALL_DIR="$(host_prereqs_install_dir)"
1135    local ARGS
1136
1137    ARGS=" --with-gmp=$INSTALL_DIR --with-mpfr=$INSTALL_DIR"
1138
1139    # Only build MPC when we need it.
1140    if [ "$HOST_NEED_MPC" ]; then
1141        ARGS=$ARGS" --with-mpc=$INSTALL_DIR"
1142        stamps_do build-mpc-$MPC_VERSION-$HOST build_mpc $MPC_VERSION
1143    else
1144        stamps_do build-mpfr-$MPFR_VERSION-$HOST build_mpfr $MPFR_VERSION
1145    fi
1146
1147    # This gets used by build_host_binutils and others.
1148    HOST_PREREQS_ARGS=$ARGS
1149}
1150
1151build_host_binutils ()
1152{
1153    local SRC_DIR="$TOOLCHAIN_SRC_DIR/binutils/binutils-$BINUTILS_VERSION"
1154    local INSTALL_DIR="$(host_binutils_install_dir)"
1155    local PREREQS_INSTALL_DIR="$(host_prereqs_install_dir)"
1156    local ARGS
1157
1158    build_host_prereqs
1159
1160    ARGS=" --with-gmp=$PREREQS_INSTALL_DIR --with-mpfr=$PREREQS_INSTALL_DIR"
1161    if [ "$HOST_NEED_MPC" ]; then
1162        ARGS=$ARGS" --with-mpc=$PREREQS_INSTALL_DIR"
1163    fi
1164
1165    LD_NAME=$DEFAULT_LD
1166
1167    # Enable Gold globally. It can be built for all hosts.
1168    BUILD_GOLD=true
1169
1170    # Special case, gold is not ready for mips yet.
1171    if [ "$TARGET" = "mipsel-linux-android" ]; then
1172        BUILD_GOLD=
1173    fi
1174
1175    # Another special case, gold in binutils-2.21 for arch-x86 is buggy
1176    # (i.e. when building the platform with it, the system doesn't boot)
1177    #
1178    if [ "$BINUTILS_VERSION" = "2.21" -a "$TARGET" = "i686-linux-android" ]; then
1179        USE_LD_DEFAULT=true
1180        BUILD_GOLD=
1181    fi
1182
1183    # Another special case, for arch-x86_64 gold supports x32 starting from 2.23
1184    #
1185    if [ "$TARGET" = "x86_64-linux-android" ]; then
1186       if ! version_is_at_least $BINUTILS_VERSION 2.23; then
1187        USE_LD_DEFAULT=true
1188        BUILD_GOLD=
1189       fi
1190    fi
1191
1192    # Another special case. Not or 2.19, it wasn't ready
1193    if [ "$BINUTILS_VERSION" = "2.19" ]; then
1194        BUILD_GOLD=
1195    fi
1196
1197    if [ "$DEFAULT_LD" = "gold" -a -z "$BUILD_GOLD" ]; then
1198        dump "$(host_text)$(target_text): Cannot build Gold for this toolchain!"
1199        BUILD_GOLD=
1200    fi
1201
1202    # Ok, if the user *really* wants it, we're going to build Gold anyway.
1203    # There are no guarantees about the correctness of the resulting binary.
1204    # --default-ld still determines the default linker to use by the toolchain.
1205    #
1206    if [ "$FORCE_GOLD_BUILD" -a -z "$BUILD_GOLD" ]; then
1207        dump "$(host_text)$(target_text): Warning: forcing build of potentially buggy Gold linker!"
1208        BUILD_GOLD=true
1209    fi
1210
1211    # The BFD linker is always built, but to build Gold, we need a specific
1212    # option for the binutils configure script. Note that its format has
1213    # changed during development.
1214    export host_configargs=
1215    if [ "$BUILD_GOLD" ]; then
1216        # The syntax of the --enable-gold option has changed.
1217        if version_is_at_least $BINUTILS_VERSION 2.20; then
1218            if [ "$DEFAULT_LD" = "bfd" ]; then
1219                ARGS=$ARGS" --enable-gold --enable-ld=default"
1220            else
1221                ARGS=$ARGS" --enable-gold=default --enable-ld"
1222            fi
1223        else
1224            if [ "$DEFAULT_LD" = "bfd" ]; then
1225                ARGS=$ARGS" --enable-gold=both"
1226            else
1227                ARGS=$ARGS" --enable-gold=both/gold"
1228            fi
1229        fi
1230	# This ARG needs quoting when passed to run2.
1231	GOLD_LDFLAGS_ARG=
1232        if [ "$HOST_OS" = 'windows' ]; then
1233            # gold may have runtime dependency on libgcc_sjlj_1.dll and
1234            # libstdc++-6.dll when built by newer versions of mingw.
1235            # Link them statically to avoid that.
1236            if version_is_at_least $BINUTILS_VERSION 2.22; then
1237                export host_configargs="--with-gold-ldflags='-static-libgcc -static-libstdc++'"
1238            elif version_is_at_least $BINUTILS_VERSION 2.21; then
1239                GOLD_LDFLAGS_ARG="--with-gold-ldflags=-static-libgcc -static-libstdc++"
1240            else
1241                export LDFLAGS=$LDFLAGS" -static-libgcc -static-libstdc++"
1242            fi
1243        fi
1244    fi
1245
1246    # This is used to install libbfd which is later used to compile
1247    # oprofile for the platform. This is not technically required for
1248    # the NDK, but allows us to use the same toolchain for the platform
1249    # build. TODO: Probably want to move this step to its own script
1250    # like build-host-libbfd.sh in the future.
1251    ARGS=$ARGS" --enable-install-libbfd"
1252
1253    # Enable plugins support for binutils-2.21+
1254    # This is common feature for binutils and gcc
1255    case "$BINUTILS_VERSION" in
1256      2.19)
1257        # Add nothing
1258        ;;
1259      *)
1260        ARGS=$ARGS" --enable-plugins"
1261        ;;
1262    esac
1263
1264    dump "$(host_text)$(target_text) Building binutils-$BINUTILS_VERSION"
1265    (
1266        setup_host_env &&
1267        BUILD_DIR="$(host_build_dir_for binutils-$BINUTILS_VERSION-$TARGET)" &&
1268        run2 mkdir -p "$BUILD_DIR" && run2 rm -rf "$BUILD_DIR"/* &&
1269        cd "$BUILD_DIR" &&
1270        run2 "$SRC_DIR"/configure \
1271            --prefix="$INSTALL_DIR" \
1272            --disable-shared \
1273            --disable-werror \
1274            --disable-nls \
1275            --build=$BUILD \
1276            --host=$HOST \
1277            --target=$TARGET \
1278            --with-sysroot="$INSTALL_DIR/sysroot" \
1279            $ARGS &&
1280        run2 make -j$NUM_JOBS &&
1281        run2 make -j$NUM_INSTALL_JOBS install &&
1282        # We need to take care of something weird, binutils-2.21 on mips
1283        # does not seem to build gold, and the Makefile script forgets to
1284        # copy it to $INSTALL/bin/mipsel-linux-android-ld. Take care of this
1285        # here with a symlink, which will be enough for now.
1286        if [ ! -f "$INSTALL_DIR/bin/$TARGET-ld" ]; then
1287            run2 ln -s "$TARGET-ld.bfd" "$INSTALL_DIR/bin/$TARGET-ld"
1288        fi
1289    )
1290    return $?
1291}
1292
1293copy_target_sysroot ()
1294{
1295    local SRC_SYSROOT=$(arch_sysroot_dir $TARGET_ARCH)
1296    local SYSROOT=$(host_sysroot)
1297
1298    # We need the arch-specific minimal sysroot
1299    stamps_do sysroot-arch-$TARGET_ARCH gen_minimal_sysroot $TARGET_ARCH
1300
1301    dump "$(host_text)$(toolchain_text) Copying $TARGET_ARCH sysroot"
1302    run2 rm -rf "$SYSROOT" &&
1303    run2 copy_directory "$SRC_SYSROOT" "$SYSROOT"
1304}
1305
1306build_host_gcc_core ()
1307{
1308    local SRC_DIR="$TOOLCHAIN_SRC_DIR/gcc/gcc-$GCC_VERSION"
1309    local INSTALL_DIR="$(host_gcc_install_dir)"
1310    local ARGS NEW_PATH
1311
1312    stamps_do build-binutils-$BINUTILS_VERSION-$HOST-$TARGET build_host_binutils
1313    stamps_do sysroot-gcc-$SYSTEM-$TOOLCHAIN copy_target_sysroot
1314
1315    build_host_prereqs
1316
1317    NEW_PATH=$(host_gcc_install_dir)/bin:$(host_binutils_install_dir)/bin
1318    if [ "$HOST" != "$BUILD" ]; then
1319        NEW_PATH=$(build_gcc_install_dir)/bin:$(build_binutils_install_dir)/bin
1320    fi
1321
1322    ARGS=$HOST_PREREQS_ARGS
1323
1324    case "$GCC_VERSION" in
1325      4.4.3)
1326        ARGS=$ARGS" --disable-plugin"
1327        ;;
1328    esac
1329
1330    ARGS=$ARGS" --with-gnu-as --with-gnu-ld"
1331    ARGS=$ARGS" --enable-threads --disable-libssp --disable-libmudflap --disable-libcilkrts --enable-gnu-indirect-function"
1332    ARGS=$ARGS" --disable-libstdc__-v3 --disable-sjlj-exceptions"
1333    ARGS=$ARGS" --disable-tls"
1334    ARGS=$ARGS" --disable-libquadmath --disable-libitm --disable-bootstrap"
1335    ARGS=$ARGS" --enable-languages=c,c++"
1336    ARGS=$ARGS" --disable-shared"
1337    ARGS=$ARGS" --disable-nls"
1338    ARGS=$ARGS" --disable-werror"
1339    ARGS=$ARGS" --enable-target-optspace"
1340    ARGS=$ARGS" --enable-eh-frame-hdr-for-static"
1341    # TODO: Build fails for libsanitizer which appears in 4.8. Disable for now.
1342    ARGS=$ARGS" --disable-libsanitizer"
1343
1344    case "$GCC_VERSION" in
1345     4.4.3)
1346       ARGS=$ARGS" --disable-libgomp"
1347       ;;
1348     *)
1349       case $TARGET_ARCH in
1350	     arm) ARGS=$ARGS" --enable-libgomp";;
1351	     x86*) ARGS=$ARGS" --enable-libgomp";;
1352	     mips|mipsel) ARGS=$ARGS" --disable-libgomp";;
1353	 esac
1354	 ;;
1355    esac
1356
1357    # Place constructors/destructors in .init_array/.fini_array, not in
1358    # .ctors/.dtors on Android. Note that upstream Linux GLibc is now doing
1359    # the same.
1360    ARGS=$ARGS" --enable-initfini-array"
1361
1362    case $TARGET_ARCH in
1363        arm)
1364            ARGS=$ARGS" --with-arch=armv5te --with-float=soft --with-fpu=vfpv3-d16"
1365            ;;
1366        x86)
1367            case "$GCC_VERSION" in
1368               4.4.3|4.7) ARGS=$ARGS" --with-arch=i686 --with-tune=atom --with-fpmath=sse" ;;
1369               *)         ARGS=$ARGS" --with-arch=i686 --with-tune=intel --with-fpmath=sse" ;;
1370            esac
1371            ;;
1372        x86_64)
1373            case "$GCC_VERSION" in
1374               4.4.3|4.7) ARGS=$ARGS" --with-arch=x86-64 --with-tune=atom --with-fpmath=sse --with-multilib-list=m32,m64,mx32" ;;
1375               *)         ARGS=$ARGS" --with-arch=x86-64 --with-tune=intel --with-fpmath=sse --with-multilib-list=m32,m64,mx32" ;;
1376            esac
1377            ;;
1378        mips)
1379            # Add --disable-fixed-point to disable fixed-point support
1380            ARGS=$ARGS" --with-arch=mips32 --disable-fixed-point"
1381            ;;
1382    esac
1383
1384    dump "$(host_text)$(toolchain_text) Building gcc-core"
1385    (
1386        setup_host_env &&
1387        BUILD_DIR="$(host_build_dir_for gcc-$GCC_VERSION-$TARGET)" &&
1388        run2 mkdir -p "$BUILD_DIR" && run2 rm -rf "$BUILD_DIR"/* &&
1389        cd "$BUILD_DIR" &&
1390        PATH=$NEW_PATH:$PATH &&
1391        run2 "$SRC_DIR"/configure \
1392            --prefix="$INSTALL_DIR" \
1393            --build=$BUILD \
1394            --host=$HOST \
1395            --target=$TARGET \
1396            --with-sysroot="$INSTALL_DIR/sysroot" \
1397            $HOST_PREREQS_ARGS $ARGS &&
1398        run2 make -j$NUM_JOBS all-gcc &&
1399        run2 make -j$NUM_INSTALL_JOBS install-gcc
1400    )
1401    return $?
1402}
1403
1404build_target_gcc_libs ()
1405{
1406    local SRC_DIR="$TOOLCHAIN_SRC_DIR/gcc/gcc-$GCC_VERSION"
1407    local INSTALL_DIR="$(host_gcc_install_dir)"
1408    local ARGS NEW_PATH
1409
1410    stamps_do gcc-core-$GCC_VERSION-$SYSTEM-$TOOLCHAIN build_host_gcc_core
1411
1412    NEW_PATH=$(host_gcc_install_dir)/bin:$(host_binutils_install_dir)/bin
1413
1414    dump "$(host_text)$(toolchain_text) Building target libraries"
1415    (
1416        setup_host_env &&
1417        BUILD_DIR="$(host_build_dir_for gcc-$GCC_VERSION-$TARGET)" &&
1418        cd "$BUILD_DIR" &&
1419        PATH=$NEW_PATH:$PATH &&
1420        run2 make -j$NUM_JOBS all &&
1421        run2 make -j$NUM_INSTALL_JOBS install
1422    )
1423    return $?
1424}
1425
1426copy_target_gcc_libs ()
1427{
1428    local SRC_DIR DST_DIR
1429    dump "$(host_text)$(toolchain_text) Copying target GCC libraries"
1430
1431    SRC_DIR="$(build_gcc_install_dir)/$TARGET"
1432    DST_DIR="$(host_gcc_install_dir)/$TARGET"
1433
1434    run2 copy_directory "$SRC_DIR" "$DST_DIR"
1435}
1436
1437build_host_gcc ()
1438{
1439    if [ "$SYSTEM" = "$BUILD_TAG" -a -z "$NO_TARGET_LIBS" ]; then
1440        # This is a regular-cross build, and we need to build the target GCC libraries.
1441        stamps_do gcc-all-$GCC_VERSION-$SYSTEM-$TOOLCHAIN build_target_gcc_libs
1442    else
1443        # This is a canadian-cross build, or we don't need the target GCC libraries.
1444        stamps_do gcc-core-$GCC_VERSION-$SYSTEM-$TOOLCHAIN build_host_gcc_core
1445    fi
1446}
1447
1448# $1: host system tag (e.g. linux-x86)
1449# $2: toolchain name (e.g. x86-4.4.3)
1450build_gcc ()
1451{
1452    local SYSTEM=$1
1453    local TOOLCHAIN=$2
1454
1455    # When performing canadian-cross builds, ensure we generate the
1456    # host toolchain first (even if we don't need target GCC libraries)
1457    if [ "$SYSTEM" != "$BUILD_TAG" ]; then
1458        build_gcc $BUILD_TAG $TOOLCHAIN
1459    fi
1460
1461    # We do this both in the setup and build phase to ensure we perform
1462    # as many checks as possible before launching the (long) build procedure.
1463    setup_build_for_host $SYSTEM
1464    setup_build_for_toolchain $TOOLCHAIN
1465
1466    if [ "$PHASE" = build ]; then
1467        stamps_do build-gcc-$SYSTEM-$TOOLCHAIN build_host_gcc
1468    fi
1469}
1470
1471do_relink ()
1472{
1473    log "Relink $1 --> $2"
1474    local BASENAME DIRNAME
1475    DIRNAME=$(dirname "$1")
1476    BASENAME=$(basename "$1")
1477    ( cd "$DIRNAME" && rm -f "$BASENAME" && ln -s "$2" "$BASENAME" )
1478}
1479
1480# $1: host system tag (e.g. linux-x86)
1481# $2: toolchain name (e.g. x86-4.4.3)
1482install_gcc ()
1483{
1484    local SYSTEM=$1
1485    local TOOLCHAIN=$2
1486    local BINUTILS_DIR GCC_DIR TARGET_LIBS_DIR INSTALL_DIR PROG
1487
1488    build_gcc $SYSTEM $TOOLCHAIN
1489
1490    dump "$(host_text)$(toolchain_text) Installing to NDK."
1491
1492    BINUTILS_DIR=$(host_binutils_install_dir)
1493    GCC_DIR=$(host_gcc_install_dir)
1494    TARGET_LIBS_DIR=$(build_gcc_install_dir)
1495    INSTALL_DIR=$TOOLCHAIN_INSTALL_DIR
1496
1497    # Copy binutils binaries
1498    run2 copy_directory "$BINUTILS_DIR/bin" "$INSTALL_DIR/bin" &&
1499    run2 copy_directory "$BINUTILS_DIR/$TARGET/lib" "$INSTALL_DIR/$TARGET/lib" &&
1500
1501    # The following is used to copy the libbfd. See --enable-install-libbfd
1502    # which is set in build_host_binutils above.
1503    run2 copy_directory "$BINUTILS_DIR/$HOST/$TARGET/include" "$INSTALL_DIR/include" &&
1504    run2 copy_directory "$BINUTILS_DIR/$HOST/$TARGET/lib"     "$INSTALL_DIR/lib$(tag_to_bits $SYSTEM)" &&
1505
1506    # Copy gcc core binaries
1507    run2 copy_directory "$GCC_DIR/bin" "$INSTALL_DIR/bin" &&
1508    run2 copy_directory "$GCC_DIR/lib/gcc/$TARGET" "$INSTALL_DIR/lib/gcc/$TARGET" &&
1509    run2 copy_directory "$GCC_DIR/libexec/gcc/$TARGET" "$INSTALL_DIR/libexec/gcc/$TARGET" &&
1510
1511    # Copy target gcc libraries
1512    run2 copy_directory "$TARGET_LIBS_DIR/lib/gcc/$TARGET" "$INSTALL_DIR/lib/gcc/$TARGET"
1513    run2 copy_directory "$TARGET_LIBS_DIR/$TARGET/lib" "$INSTALL_DIR/$TARGET/lib"
1514    # Multilib compiler should have these
1515    if [ -d "$TARGET_LIBS_DIR/$TARGET/libx32" ]; then
1516       run2 copy_directory "$TARGET_LIBS_DIR/$TARGET/libx32" "$INSTALL_DIR/$TARGET/libx32"
1517    fi
1518    if [ -d "$TARGET_LIBS_DIR/$TARGET/lib32" ]; then
1519       run2 copy_directory "$TARGET_LIBS_DIR/$TARGET/lib32" "$INSTALL_DIR/$TARGET/lib32"
1520    fi
1521    if [ -d "$TARGET_LIBS_DIR/$TARGET/lib64" ]; then
1522       run2 copy_directory "$TARGET_LIBS_DIR/$TARGET/lib64" "$INSTALL_DIR/$TARGET/lib64"
1523    fi
1524
1525    # We need to generate symlinks for the binutils binaries from
1526    # $INSTALL_DIR/$TARGET/bin/$PROG to $INSTALL_DIR/bin/$TARGET-$PROG
1527    mkdir -p "$INSTALL_DIR/$TARGET/bin" &&
1528    for PROG in $(cd $INSTALL_DIR/$TARGET/bin && ls * 2>/dev/null); do
1529        do_relink "$INSTALL_DIR/$TARGET/bin/$PROG" ../../bin/$TARGET-$PROG
1530        fail_panic
1531    done
1532
1533    # Also relink a few files under $INSTALL_DIR/bin/
1534    do_relink "$INSTALL_DIR"/bin/$TARGET-c++ $TARGET-g++ &&
1535    do_relink "$INSTALL_DIR"/bin/$TARGET-gcc-$GCC_VERSION $TARGET-gcc &&
1536    if [ -f "$INSTALL_DIR"/bin/$TARGET-ld.gold ]; then
1537      do_relink "$INSTALL_DIR"/bin/$TARGET-ld $TARGET-ld.gold
1538    else
1539      do_relink "$INSTALL_DIR"/bin/$TARGET-ld $TARGET-ld.bfd
1540    fi
1541    fail_panic
1542
1543    # Remove unwanted $TARGET-run simulator to save about 800 KB.
1544    run2 rm -f "$INSTALL_DIR"/bin/$TARGET-run
1545
1546    # Copy the license files
1547    local TOOLCHAIN_LICENSES="$ANDROID_NDK_ROOT"/build/tools/toolchain-licenses
1548    run cp -f "$TOOLCHAIN_LICENSES"/COPYING "$TOOLCHAIN_LICENSES"/COPYING.LIB "$INSTALL_DIR"
1549}
1550
1551# $1: host system tag (e.g. linux-x86)
1552# $2: toolchain name (e.g. x86-4.4.3)
1553# $3: package directory.
1554package_gcc ()
1555{
1556    local SYSTEM=$1
1557    local TOOLCHAIN=$2
1558    local PACKAGE_DIR="$3"
1559    local PACKAGE_NAME="$TOOLCHAIN-$SYSTEM.tar.bz2"
1560    local PACKAGE_FILE="$PACKAGE_DIR/$PACKAGE_NAME"
1561
1562    setup_build_for_toolchain $TOOLCHAIN
1563
1564    dump "Packaging $PACKAGE_NAME."
1565    pack_archive "$PACKAGE_FILE" "$NDK_DIR" "$TOOLCHAIN_SUB_DIR"
1566}
1567
1568setup_build
1569
1570for PHASE in setup build; do
1571    for SYSTEM in $HOST_SYSTEMS; do
1572        setup_build_for_host $SYSTEM
1573        for TOOLCHAIN in $TOOLCHAINS; do
1574            build_gcc $SYSTEM $TOOLCHAIN
1575        done
1576    done
1577done
1578
1579for SYSTEM in $HOST_SYSTEMS; do
1580    setup_build_for_host $SYSTEM
1581    for TOOLCHAIN in $TOOLCHAINS; do
1582        install_gcc $SYSTEM $TOOLCHAIN
1583    done
1584done
1585
1586if [ "$PACKAGE_DIR" ]; then
1587    for SYSTEM in $HOST_SYSTEMS; do
1588        setup_build_for_host $SYSTEM
1589        for TOOLCHAIN in $TOOLCHAINS; do
1590            package_gcc $SYSTEM $TOOLCHAIN "$PACKAGE_DIR"
1591        done
1592    done
1593    echo "Done. See the content of $PACKAGE_DIR:"
1594    ls -l "$PACKAGE_DIR"
1595    echo ""
1596fi
1597