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