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