prebuilt-common.sh revision 61c1722b71ed63f0a3098610459459a51ca041b8
1# Common functions for all prebuilt-related scripts
2# This is included/sourced by other scripts
3#
4
5# ensure stable sort order
6export LC_ALL=C
7
8# NDK_BUILDTOOLS_PATH should point to the directory containing
9# this script. If it is not defined, assume that this is one of
10# the scripts in the same directory that sourced this file.
11#
12if [ -z "$NDK_BUILDTOOLS_PATH" ]; then
13    NDK_BUILDTOOLS_PATH=$(dirname $0)
14    if [ ! -f "$NDK_BUILDTOOLS_PATH/prebuilt-common.sh" ]; then
15        echo "INTERNAL ERROR: Please define NDK_BUILDTOOLS_PATH to point to $$NDK/build/tools"
16        exit 1
17    fi
18fi
19
20NDK_BUILDTOOLS_ABSPATH=$(cd $NDK_BUILDTOOLS_PATH && pwd)
21
22. $NDK_BUILDTOOLS_PATH/../core/ndk-common.sh
23. $NDK_BUILDTOOLS_PATH/dev-defaults.sh
24
25#====================================================
26#
27#  UTILITY FUNCTIONS
28#
29#====================================================
30
31# Return the maximum length of a series of strings
32#
33# Usage:  len=`max_length <string1> <string2> ...`
34#
35max_length ()
36{
37    echo "$@" | tr ' ' '\n' | awk 'BEGIN {max=0} {len=length($1); if (len > max) max=len} END {print max}'
38}
39
40# Translate dashes to underscores
41# Usage:  str=`dashes_to_underscores <values>`
42dashes_to_underscores ()
43{
44    echo "$@" | tr '-' '_'
45}
46
47# Translate underscores to dashes
48# Usage: str=`underscores_to_dashes <values>`
49underscores_to_dashes ()
50{
51    echo "$@" | tr '_' '-'
52}
53
54# Translate commas to spaces
55# Usage: str=`commas_to_spaces <list>`
56commas_to_spaces ()
57{
58    echo "$@" | tr ',' ' '
59}
60
61# Translate spaces to commas
62# Usage: list=`spaces_to_commas <string>`
63spaces_to_commas ()
64{
65    echo "$@" | tr ' ' ','
66}
67
68# Remove trailing path of a path
69# $1: path
70remove_trailing_slash () {
71    echo ${1%%/}
72}
73
74# Reverse a file path directory
75# foo -> .
76# foo/bar -> ..
77# foo/bar/zoo -> ../..
78reverse_path ()
79{
80    local path cur item
81    path=${1%%/} # remove trailing slash
82    cur="."
83    if [ "$path" != "." ] ; then
84        for item in $(echo "$path" | tr '/' ' '); do
85            cur="../$cur"
86        done
87    fi
88    echo ${cur%%/.}
89}
90
91# test_reverse_path ()
92# {
93#     rr=`reverse_path $1`
94#     if [ "$rr" != "$2" ] ; then
95#         echo "ERROR: reverse_path '$1' -> '$rr' (expected '$2')"
96#     fi
97# }
98#
99# test_reverse_path . .
100# test_reverse_path ./ .
101# test_reverse_path foo ..
102# test_reverse_path foo/ ..
103# test_reverse_path foo/bar ../..
104# test_reverse_path foo/bar/ ../..
105# test_reverse_path foo/bar/zoo ../../..
106# test_reverse_path foo/bar/zoo/ ../../..
107
108# Sort a space-separated list and remove duplicates
109# $1+: slist
110# Output: new slist
111sort_uniq ()
112{
113    local RET
114    RET=$(echo "$@" | tr ' ' '\n' | sort -u)
115    echo $RET
116}
117
118# Return the list of all regular files under a given directory
119# $1: Directory path
120# Output: list of files, relative to $1
121list_files_under ()
122{
123    if [ -d "$1" ]; then
124        (cd $1 && find . -type f | sed -e "s!./!!" | sort -u)
125    else
126        echo ""
127    fi
128}
129
130#====================================================
131#
132#  OPTION PROCESSING
133#
134#====================================================
135
136# We recognize the following option formats:
137#
138#  -f
139#  --flag
140#
141#  -s<value>
142#  --setting=<value>
143#
144
145# NOTE: We translate '-' into '_' when storing the options in global variables
146#
147
148OPTIONS=""
149OPTION_FLAGS=""
150OPTION_SETTINGS=""
151
152# Set a given option attribute
153# $1: option name
154# $2: option attribute
155# $3: attribute value
156#
157option_set_attr ()
158{
159    eval OPTIONS_$1_$2=\"$3\"
160}
161
162# Get a given option attribute
163# $1: option name
164# $2: option attribute
165#
166option_get_attr ()
167{
168    echo `var_value OPTIONS_$1_$2`
169}
170
171# Register a new option
172# $1: option
173# $2: small abstract for the option
174# $3: optional. default value
175#
176register_option_internal ()
177{
178    optlabel=
179    optname=
180    optvalue=
181    opttype=
182    while [ -n "1" ] ; do
183        # Check for something like --setting=<value>
184        echo "$1" | grep -q -E -e '^--[^=]+=<.+>$'
185        if [ $? = 0 ] ; then
186            optlabel=`expr -- "$1" : '\(--[^=]*\)=.*'`
187            optvalue=`expr -- "$1" : '--[^=]*=\(<.*>\)'`
188            opttype="long_setting"
189            break
190        fi
191
192        # Check for something like --flag
193        echo "$1" | grep -q -E -e '^--[^=]+$'
194        if [ $? = 0 ] ; then
195            optlabel="$1"
196            opttype="long_flag"
197            break
198        fi
199
200        # Check for something like -f<value>
201        echo "$1" | grep -q -E -e '^-[A-Za-z0-9]<.+>$'
202        if [ $? = 0 ] ; then
203            optlabel=`expr -- "$1" : '\(-.\).*'`
204            optvalue=`expr -- "$1" : '-.\(<.+>\)'`
205            opttype="short_setting"
206            break
207        fi
208
209        # Check for something like -f
210        echo "$1" | grep -q -E -e '^-.$'
211        if [ $? = 0 ] ; then
212            optlabel="$1"
213            opttype="short_flag"
214            break
215        fi
216
217        echo "ERROR: Invalid option format: $1"
218        echo "       Check register_option call"
219        exit 1
220    done
221
222    log "new option: type='$opttype' name='$optlabel' value='$optvalue'"
223
224    optname=`dashes_to_underscores $optlabel`
225    OPTIONS="$OPTIONS $optname"
226    OPTIONS_TEXT="$OPTIONS_TEXT $1"
227    option_set_attr $optname label "$optlabel"
228    option_set_attr $optname otype "$opttype"
229    option_set_attr $optname value "$optvalue"
230    option_set_attr $optname text "$1"
231    option_set_attr $optname abstract "$2"
232    option_set_attr $optname default "$3"
233}
234
235# Register a new option with a function callback.
236#
237# $1: option
238# $2: name of function that will be called when the option is parsed
239# $3: small abstract for the option
240# $4: optional. default value
241#
242register_option ()
243{
244    local optname optvalue opttype optlabel
245    register_option_internal "$1" "$3" "$4"
246    option_set_attr $optname funcname "$2"
247}
248
249# Register a new option with a variable store
250#
251# $1: option
252# $2: name of variable that will be set by this option
253# $3: small abstract for the option
254#
255# NOTE: The current value of $2 is used as the default
256#
257register_var_option ()
258{
259    local optname optvalue opttype optlabel
260    register_option_internal "$1" "$3" "`var_value $2`"
261    option_set_attr $optname varname "$2"
262}
263
264
265MINGW=no
266do_mingw_option () { MINGW=yes; }
267
268register_mingw_option ()
269{
270    if [ "$HOST_OS" = "linux" ] ; then
271        register_option "--mingw" do_mingw_option "Generate windows binaries on Linux."
272    fi
273}
274
275TRY64=no
276do_try64_option () { TRY64=yes; }
277
278register_try64_option ()
279{
280    register_option "--try-64" do_try64_option "Generate 64-bit binaries."
281}
282
283
284register_jobs_option ()
285{
286    NUM_JOBS=$BUILD_NUM_CPUS
287    register_var_option "-j<number>" NUM_JOBS "Use <number> parallel build jobs"
288}
289
290# Print the help, including a list of registered options for this program
291# Note: Assumes PROGRAM_PARAMETERS and PROGRAM_DESCRIPTION exist and
292#       correspond to the parameters list and the program description
293#
294print_help ()
295{
296    local opt text abstract default
297
298    echo "Usage: $PROGNAME [options] $PROGRAM_PARAMETERS"
299    echo ""
300    if [ -n "$PROGRAM_DESCRIPTION" ] ; then
301        echo "$PROGRAM_DESCRIPTION"
302        echo ""
303    fi
304    echo "Valid options (defaults are in brackets):"
305    echo ""
306
307    maxw=`max_length "$OPTIONS_TEXT"`
308    AWK_SCRIPT=`echo "{ printf \"%-${maxw}s\", \\$1 }"`
309    for opt in $OPTIONS; do
310        text=`option_get_attr $opt text | awk "$AWK_SCRIPT"`
311        abstract=`option_get_attr $opt abstract`
312        default=`option_get_attr $opt default`
313        if [ -n "$default" ] ; then
314            echo "  $text     $abstract [$default]"
315        else
316            echo "  $text     $abstract"
317        fi
318    done
319    echo ""
320}
321
322option_panic_no_args ()
323{
324    echo "ERROR: Option '$1' does not take arguments. See --help for usage."
325    exit 1
326}
327
328option_panic_missing_arg ()
329{
330    echo "ERROR: Option '$1' requires an argument. See --help for usage."
331    exit 1
332}
333
334extract_parameters ()
335{
336    local opt optname otype value name fin funcname
337    PARAMETERS=""
338    while [ -n "$1" ] ; do
339        # If the parameter does not begin with a dash
340        # it is not an option.
341        param=`expr -- "$1" : '^\([^\-].*\)$'`
342        if [ -n "$param" ] ; then
343            if [ -z "$PARAMETERS" ] ; then
344                PARAMETERS="$1"
345            else
346                PARAMETERS="$PARAMETERS $1"
347            fi
348            shift
349            continue
350        fi
351
352        while [ -n "1" ] ; do
353            # Try to match a long setting, i.e. --option=value
354            opt=`expr -- "$1" : '^\(--[^=]*\)=.*$'`
355            if [ -n "$opt" ] ; then
356                otype="long_setting"
357                value=`expr -- "$1" : '^--[^=]*=\(.*\)$'`
358                break
359            fi
360
361            # Try to match a long flag, i.e. --option
362            opt=`expr -- "$1" : '^\(--.*\)$'`
363            if [ -n "$opt" ] ; then
364                otype="long_flag"
365                value="yes"
366                break
367            fi
368
369            # Try to match a short setting, i.e. -o<value>
370            opt=`expr -- "$1" : '^\(-[A-Za-z0-9]\)..*$'`
371            if [ -n "$opt" ] ; then
372                otype="short_setting"
373                value=`expr -- "$1" : '^-.\(.*\)$'`
374                break
375            fi
376
377            # Try to match a short flag, i.e. -o
378            opt=`expr -- "$1" : '^\(-.\)$'`
379            if [ -n "$opt" ] ; then
380                otype="short_flag"
381                value="yes"
382                break
383            fi
384
385            echo "ERROR: Unknown option '$1'. Use --help for list of valid values."
386            exit 1
387        done
388
389        #echo "Found opt='$opt' otype='$otype' value='$value'"
390
391        name=`dashes_to_underscores $opt`
392        found=0
393        for xopt in $OPTIONS; do
394            if [ "$name" != "$xopt" ] ; then
395                continue
396            fi
397            # Check that the type is correct here
398            #
399            # This also allows us to handle -o <value> as -o<value>
400            #
401            xotype=`option_get_attr $name otype`
402            if [ "$otype" != "$xotype" ] ; then
403                case "$xotype" in
404                "short_flag")
405                    option_panic_no_args $opt
406                    ;;
407                "short_setting")
408                    if [ -z "$2" ] ; then
409                        option_panic_missing_arg $opt
410                    fi
411                    value="$2"
412                    shift
413                    ;;
414                "long_flag")
415                    option_panic_no_args $opt
416                    ;;
417                "long_setting")
418                    option_panic_missing_arg $opt
419                    ;;
420                esac
421            fi
422            found=1
423            break
424            break
425        done
426        if [ "$found" = "0" ] ; then
427            echo "ERROR: Unknown option '$opt'. See --help for usage."
428            exit 1
429        fi
430        # Set variable or launch option-specific function.
431        varname=`option_get_attr $name varname`
432        if [ -n "$varname" ] ; then
433            eval ${varname}=\"$value\"
434        else
435            eval `option_get_attr $name funcname` \"$value\"
436        fi
437        shift
438    done
439}
440
441do_option_help ()
442{
443    print_help
444    exit 0
445}
446
447VERBOSE=no
448VERBOSE2=no
449do_option_verbose ()
450{
451    if [ $VERBOSE = "yes" ] ; then
452        VERBOSE2=yes
453    else
454        VERBOSE=yes
455    fi
456}
457
458register_option "--help"          do_option_help     "Print this help."
459register_option "--verbose"       do_option_verbose  "Enable verbose mode."
460
461#====================================================
462#
463#  TOOLCHAIN AND ABI PROCESSING
464#
465#====================================================
466
467# Determine optional variable value
468# $1: final variable name
469# $2: option variable name
470# $3: small description for the option
471fix_option ()
472{
473    if [ -n "$2" ] ; then
474        eval $1="$2"
475        log "Using specific $3: $2"
476    else
477        log "Using default $3: `var_value $1`"
478    fi
479}
480
481
482# If SYSROOT is empty, check that $1/$2 contains a sysroot
483# and set the variable to it.
484#
485# $1: sysroot path
486# $2: platform/arch suffix
487check_sysroot ()
488{
489    if [ -z "$SYSROOT" ] ; then
490        log "Probing directory for sysroot: $1/$2"
491        if [ -d $1/$2 ] ; then
492            SYSROOT=$1/$2
493        fi
494    fi
495}
496
497# Determine sysroot
498# $1: Option value (or empty)
499#
500fix_sysroot ()
501{
502    if [ -n "$1" ] ; then
503        eval SYSROOT="$1"
504        log "Using specified sysroot: $1"
505    else
506        SYSROOT_SUFFIX=$PLATFORM/arch-$ARCH
507        SYSROOT=
508        check_sysroot $NDK_DIR/platforms $SYSROOT_SUFFIX
509        check_sysroot $ANDROID_NDK_ROOT/platforms $SYSROOT_SUFFIX
510        check_sysroot `dirname $ANDROID_NDK_ROOT`/development/ndk/platforms $SYSROOT_SUFFIX
511
512        if [ -z "$SYSROOT" ] ; then
513            echo "ERROR: Could not find NDK sysroot path for $SYSROOT_SUFFIX."
514            echo "       Use --sysroot=<path> to specify one."
515            exit 1
516        fi
517    fi
518
519    if [ ! -f $SYSROOT/usr/include/stdlib.h ] ; then
520        echo "ERROR: Invalid sysroot path: $SYSROOT"
521        echo "       Use --sysroot=<path> to indicate a valid one."
522        exit 1
523    fi
524}
525
526# Use the check for the availability of a compatibility SDK in Darwin
527# this can be used to generate binaries compatible with either Tiger or
528# Leopard.
529#
530# $1: SDK root path
531# $2: MacOS X minimum version (e.g. 10.4)
532check_darwin_sdk ()
533{
534    if [ -d "$1" ] ; then
535        HOST_CFLAGS="-isysroot $1 -mmacosx-version-min=$2 -DMAXOSX_DEPLOYEMENT_TARGET=$2"
536        HOST_LDFLAGS="-Wl,-syslibroot,$sdk -mmacosx-version-min=$2"
537        return 0  # success
538    fi
539    return 1
540}
541
542
543handle_mingw ()
544{
545    # Now handle the --mingw flag
546    HOST_EXE=
547    if [ "$MINGW" = "yes" ] ; then
548        case $HOST_TAG in
549            linux-*)
550                ;;
551            *)
552                echo "ERROR: Can only enable mingw on Linux platforms !"
553                exit 1
554                ;;
555        esac
556        if [ "$TRY64" = "yes" ]; then
557            ABI_CONFIGURE_HOST=amd64-mingw32msvc
558        else
559            # NOTE: The canadian-cross build of Binutils 2.19 will fail if you
560            #        use i586-pc-mingw32msvc here. Binutils 2.21 will work ok
561            #        with both names.
562            ABI_CONFIGURE_HOST=i586-mingw32msvc
563        fi
564        HOST_OS=windows
565        HOST_TAG=windows
566        HOST_EXE=.exe
567    fi
568}
569
570# If --mingw option is used, check that there is a working
571# mingw32 toolchain installed.
572#
573# If there is, check that it's working
574#
575# $1: install directory for wrapper toolchain
576#
577prepare_mingw_toolchain ()
578{
579    if [ "$MINGW" != "yes" ]; then
580        return
581    fi
582
583    # IMPORTANT NOTE: binutils 2.21 requires a cross toolchain named
584    # i585-pc-mingw32msvc-gcc, or it will fail its configure step late
585    # in the toolchain build. Note that binutils 2.19 can build properly
586    # with i585-mingw32mvsc-gcc, which is the name used by the 'mingw32'
587    # toolchain install on Debian/Ubuntu.
588    #
589    # To solve this dilemma, we create a wrapper toolchain named
590    # i586-pc-mingw32msvc-gcc that really calls i586-mingw32msvc-gcc,
591    # this works with all versions of binutils.
592    #
593    # We apply the same logic to the 64-bit Windows cross-toolchain
594    #
595    if [ "$HOST_ARCH" = "x86_64" -a "$TRY64" = "yes" ]; then
596        BINPREFIX1=x86_64-pc-mingw32msvc-
597        BINPREFIX2=amd64-mingw32msvc-
598        DEBIAN_NAME=mingw64
599    else
600        BINPREFIX1=i586-pc-mingw32msvc-
601        BINPREFIX2=i586-mingw32msvc-
602        DEBIAN_NAME=mingw32
603    fi
604
605    # First, check that there is ${BINPREFIX1}gcc is installed and
606    # in our PATH. This is very unlikely, but use it if it's there.
607    find_program MINGW_GCC ${BINPREFIX1}gcc
608    if [ -n "$MINGW_GCC" ]; then
609        dump "Found mingw toolchain: $MINGW_GCC"
610    else
611        # We didn't find it, that's ok, try to find ${BINPREFIX2}gcc
612        # then, if it is there, create a wrapper toolchain for it
613        find_program MINGW_GCC ${BINPREFIX2}gcc
614        if [ -z "$MINGW_GCC" ]; then
615            echo "ERROR: Could not find ${BINPREFIX1}gcc or ${BINPREFIX2}gcc in your PATH"
616            echo "Please install the corresponding cross-toolchain and re-run this script"
617            echo "TIP: On Debian or Ubuntu, try: sudo apt-get install $DEBIAN_NAME"
618            exit 1
619        fi
620        # Create a wrapper toolchain, and prepend its dir to our PATH
621        MINGW_WRAP_DIR="$1"/$DEBIAN_NAME-wrapper
622        rm -rf "$MINGW_WRAP_DIR"
623
624        DST_PREFIX=${MINGW_GCC%gcc}
625        if [ "$NDK_CCACHE" ]; then
626            DST_PREFIX="$NDK_CCACHE $DST_PREFIX"
627        fi
628
629        $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=$BINPREFIX1 --dst-prefix="$DST_PREFIX" "$MINGW_WRAP_DIR"
630        fail_panic "Could not create mingw wrapper toolchain in $MINGW_WRAP_DIR"
631
632        export PATH=$MINGW_WRAP_DIR:$PATH
633        dump "Using mingw wrapper: $MINGW_WRAP_DIR/${BINPREFIX1}gcc"
634    fi
635}
636
637handle_host ()
638{
639    # For now, we only support building 32-bit binaries anyway
640    if [ "$TRY64" != "yes" ]; then
641        force_32bit_binaries  # to modify HOST_TAG and others
642        HOST_BITS=32
643    fi
644    handle_mingw
645}
646
647setup_ccache ()
648{
649    # Support for ccache compilation
650    # We can't use this here when building Windows binaries on Linux with
651    # binutils 2.21, because defining CC/CXX in the environment makes the
652    # configure script fail later
653    #
654    if [ "$NDK_CCACHE" -a "$MINGW" != "yes" ]; then
655        NDK_CCACHE_CC=$CC
656        NDK_CCACHE_CXX=$CXX
657        # Unfortunately, we can just do CC="$NDK_CCACHE $CC" because some
658        # configure scripts are not capable of dealing with this properly
659        # E.g. the ones used to rebuild the GCC toolchain from scratch.
660        # So instead, use a wrapper script
661        CC=$NDK_BUILDTOOLS_ABSPATH/ndk-ccache-gcc.sh
662        CXX=$NDK_BUILDTOOLS_ABSPATH/ndk-ccache-g++.sh
663        export NDK_CCACHE_CC NDK_CCACHE_CXX
664        log "Using ccache compilation"
665        log "NDK_CCACHE_CC=$NDK_CCACHE_CC"
666        log "NDK_CCACHE_CXX=$NDK_CCACHE_CXX"
667    fi
668}
669
670prepare_common_build ()
671{
672    if [ "$MINGW" = "yes" ]; then
673        if [ "$TRY64" = "yes" ]; then
674            log "Generating 64-bit Windows binaries"
675            HOST_BITS=64
676        else
677            log "Generating 32-bit Windows binaries"
678            HOST_BITS=32
679        fi
680        # Do *not* set CC and CXX when building the Windows binaries
681        # Otherwise, the GCC configure/build script will mess that Canadian cross
682        # build in weird ways. Instead we rely on the toolchain detected or generated
683        # previously in prepare_mingw_toolchain.
684        unset CC CXX STRIP
685        return
686    fi
687
688    # On Linux, detect our legacy-compatible toolchain when in the Android
689    # source tree, and use it to force the generation of glibc-2.7 compatible
690    # binaries.
691    #
692    # We only do this if the CC variable is not defined to a given value
693    # and the --mingw or --try-64 options are not used.
694    #
695    if [ "$HOST_OS" = "linux" -a -z "$CC" -a "$MINGW" != "yes" -a "$TRY64" != "yes" ]; then
696        LEGACY_TOOLCHAIN_DIR="$ANDROID_NDK_ROOT/../prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6"
697        if [ -d "$LEGACY_TOOLCHAIN_DIR" ] ; then
698            log "Forcing generation of Linux binaries with legacy toolchain"
699            CC="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-gcc"
700            CXX="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-g++"
701        fi
702    fi
703
704    # Force generation of 32-bit binaries on 64-bit systems
705    CC=${CC:-gcc}
706    CXX=${CXX:-g++}
707    STRIP=${STRIP:-strip}
708    case $HOST_TAG in
709        darwin-*)
710            # Try to build with Tiger SDK if available
711            if check_darwin_sdk /Developer/SDKs/MacOSX10.4.sdku 10.4; then
712                log "Generating Tiger-compatible binaries!"
713            # Otherwise with Leopard SDK
714            elif check_darwin_sdk /Developer/SDKs/MacOSX10.5.sdk 10.5; then
715                log "Generating Leopard-compatible binaries!"
716            else
717                local version=`sw_vers -productVersion`
718                log "Generating $version-compatible binaries!"
719            fi
720            ;;
721    esac
722
723    # Force generation of 32-bit binaries on 64-bit systems.
724    # We used to test the value of $HOST_TAG for *-x86_64, but this is
725    # not sufficient on certain systems.
726    #
727    # For example, Snow Leopard can be booted with a 32-bit kernel, running
728    # a 64-bit userland, with a compiler that generates 64-bit binaries by
729    # default *even* though "gcc -v" will report --target=i686-apple-darwin10!
730    #
731    # So know, simply probe for the size of void* by performing a small runtime
732    # compilation test.
733    #
734    cat > $TMPC <<EOF
735    /* this test should fail if the compiler generates 64-bit machine code */
736    int test_array[1-2*(sizeof(void*) != 4)];
737EOF
738    log -n "Checking whether the compiler generates 32-bit binaries..."
739    HOST_BITS=32
740    log2 $CC $HOST_CFLAGS -c -o $TMPO $TMPC
741    $NDK_CCACHE $CC $HOST_CFLAGS -c -o $TMPO $TMPC >$TMPL 2>&1
742    if [ $? != 0 ] ; then
743        log "no"
744        if [ "$TRY64" != "yes" ]; then
745            # NOTE: We need to modify the definitions of CC and CXX directly
746            #        here. Just changing the value of CFLAGS / HOST_CFLAGS
747            #        will not work well with the GCC toolchain scripts.
748            CC="$CC -m32"
749            CXX="$CXX -m32"
750        else
751            HOST_BITS=64
752        fi
753    else
754        log "yes"
755    fi
756
757    # For now, we only support building 32-bit binaries anyway
758    if [ "$TRY64" != "yes" ]; then
759        force_32bit_binaries  # to modify HOST_TAG and others
760        HOST_BITS=32
761    fi
762}
763
764prepare_host_build ()
765{
766    prepare_common_build
767
768    # Now deal with mingw
769    if [ "$MINGW" = "yes" ]; then
770        handle_mingw
771        CC=$ABI_CONFIGURE_HOST-gcc
772        CXX=$ABI_CONFIGURE_HOST-g++
773        LD=$ABI_CONFIGURE_HOST-ld
774        AR=$ABI_CONFIGURE_HOST-ar
775        AS=$ABI_CONFIGURE_HOST-as
776        RANLIB=$ABI_CONFIGURE_HOST-ranlib
777        STRIP=$ABI_CONFIGURE_HOST-strip
778        export CC CXX LD AR AS RANLIB STRIP
779    fi
780
781    setup_ccache
782}
783
784
785prepare_target_build ()
786{
787    # detect build tag
788    case $HOST_TAG in
789        linux-x86)
790            ABI_CONFIGURE_BUILD=i386-linux-gnu
791            ;;
792        linux-x86_64)
793            ABI_CONFIGURE_BUILD=x86_64-linux-gnu
794            ;;
795        darwin-x86)
796            ABI_CONFIGURE_BUILD=i686-apple-darwin
797            ;;
798        darwin-x86_64)
799            ABI_CONFIGURE_BUILD=x86_64-apple-darwin
800            ;;
801        windows)
802            ABI_CONFIGURE_BUILD=i686-pc-cygwin
803            ;;
804        *)
805            echo "ERROR: Unsupported HOST_TAG: $HOST_TAG"
806            echo "Please update 'prepare_host_flags' in build/tools/prebuilt-common.sh"
807            ;;
808    esac
809
810    # By default, assume host == build
811    ABI_CONFIGURE_HOST="$ABI_CONFIGURE_BUILD"
812
813    prepare_common_build
814    HOST_GMP_ABI=$HOST_BITS
815
816    # Now handle the --mingw flag
817    if [ "$MINGW" = "yes" ] ; then
818        handle_mingw
819        # It turns out that we need to undefine this to be able to
820        # perform a canadian-cross build with mingw. Otherwise, the
821        # GMP configure scripts will not be called with the right options
822        HOST_GMP_ABI=
823    fi
824
825    setup_ccache
826}
827
828# $1: Toolchain name
829#
830parse_toolchain_name ()
831{
832    TOOLCHAIN=$1
833    if [ -z "$TOOLCHAIN" ] ; then
834        echo "ERROR: Missing toolchain name!"
835        exit 1
836    fi
837
838    ABI_CFLAGS_FOR_TARGET=
839    ABI_CXXFLAGS_FOR_TARGET=
840
841    # Determine ABI based on toolchain name
842    #
843    case "$TOOLCHAIN" in
844    arm-linux-androideabi-*)
845        ARCH="arm"
846        ABI="armeabi"
847        ABI_CONFIGURE_TARGET="arm-linux-androideabi"
848        ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=armv5te"
849        # Disable ARM Gold linker for now, it doesn't build on Windows, it
850        # crashes with SIGBUS on Darwin, and produces weird executables on
851        # linux that strip complains about... Sigh.
852        #ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --enable-gold=both/gold"
853
854        ;;
855    x86-*)
856        ARCH="x86"
857        ABI=$ARCH
858        ABI_INSTALL_NAME="x86"
859        ABI_CONFIGURE_TARGET="i686-linux-android"
860        # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time
861        # You can't really build these separately at the moment.
862        ABI_CFLAGS_FOR_TARGET="-fPIC"
863        ;;
864    mips*)
865        ARCH="mips"
866        ABI=$ARCH
867        ABI_INSTALL_NAME="mips"
868        ABI_CONFIGURE_TARGET="mipsel-linux-android"
869        # Set default to mips32
870        ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=mips32"
871        # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time
872        # You can't really build these separately at the moment.
873        # Add -fpic, because MIPS NDK will need to link .a into .so.
874        ABI_CFLAGS_FOR_TARGET="-fexceptions -fpic"
875        ABI_CXXFLAGS_FOR_TARGET="-frtti -fpic"
876        # Add --disable-fixed-point to disable fixed-point support
877        # Add --disable-threads for eh_frame handling in a single thread
878        ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --disable-fixed-point --disable-threads"
879        ;;
880    * )
881        echo "Invalid toolchain specified. Expected (arm-linux-androideabi-*|x86-*|mips*)"
882        echo ""
883        print_help
884        exit 1
885        ;;
886    esac
887
888    log "Targetting CPU: $ARCH"
889
890    GCC_VERSION=`expr -- "$TOOLCHAIN" : '.*-\([0-9x\.]*\)'`
891    log "Using GCC version: $GCC_VERSION"
892
893    # Determine --host value when building gdbserver
894    case "$TOOLCHAIN" in
895    arm-*)
896        GDBSERVER_HOST=arm-eabi-linux
897        GDBSERVER_CFLAGS="-fno-short-enums"
898        GDBSERVER_LDFLAGS=
899        ;;
900    x86-*)
901        GDBSERVER_HOST=i686-android-linux-gnu  # GDB<7.3 doesn't support i686-linux-android-gnu
902        GDBSERVER_CFLAGS=
903        GDBSERVER_LDFLAGS=
904        ;;
905    mips*)
906        GDBSERVER_HOST=mipsel-linux-gnu
907        GDBSERVER_CFLAGS=
908        GDBSERVER_LDFLAGS=
909        ;;
910    esac
911
912}
913
914# Return the host "tag" used to identify prebuilt host binaries.
915# NOTE: Handles the case where '$MINGW = true'
916# For now, valid values are: linux-x86, darwin-x86 and windows
917get_prebuilt_host_tag ()
918{
919    local RET=$HOST_TAG
920    if [ "$MINGW" = "yes" ]; then
921        RET=windows
922    fi
923    case $RET in
924        linux-x86_64)
925            if [ "$TRY64" = "no" ]; then
926                RET=linux-x86
927            fi
928            ;;
929        darwin-x86_64)
930            if [ "$TRY64" = "no" ]; then
931                RET=darwin-x86
932            fi
933            ;;
934    esac
935    echo $RET
936}
937
938# Return the executable suffix corresponding to host executables
939get_prebuilt_host_exe_ext ()
940{
941    if [ "$MINGW" = "yes" ]; then
942        echo ".exe"
943    else
944        echo ""
945    fi
946}
947
948# Convert an ABI name into an Architecture name
949# $1: ABI name
950# Result: Arch name
951convert_abi_to_arch ()
952{
953    local RET
954    case $1 in
955        armeabi|armeabi-v7a)
956            RET=arm
957            ;;
958        x86)
959            RET=x86
960            ;;
961        mips)
962            RET=mips
963            ;;
964        *)
965            2> echo "ERROR: Unsupported ABI name: $1, use one of: armeabi, armeabi-v7a or x86 or mips"
966            exit 1
967            ;;
968    esac
969    echo "$RET"
970}
971
972# Return the default binary path prefix for a given architecture
973# For example: arm -> toolchains/arm-linux-androideabi-4.4.3/prebuilt/<system>/bin/arm-linux-androideabi-
974# $1: Architecture name
975# $2: optional, system name, defaults to $HOST_TAG
976get_default_toolchain_binprefix_for_arch ()
977{
978    local NAME PREFIX DIR BINPREFIX
979    local SYSTEM=${2:-$(get_prebuilt_host_tag)}
980    NAME=$(get_default_toolchain_name_for_arch $1)
981    PREFIX=$(get_default_toolchain_prefix_for_arch $1)
982    DIR=$(get_toolchain_install . $NAME $SYSTEM)
983    BINPREFIX=${DIR#./}/bin/$PREFIX-
984    echo "$BINPREFIX"
985}
986
987# Return default API level for a given arch
988# This is the level used to build the toolchains.
989#
990# $1: Architecture name
991get_default_api_level_for_arch ()
992{
993    # For now, always build the toolchain against API level 9
994    # (We have local toolchain patches under build/tools/toolchain-patches
995    # to ensure that the result works on previous platforms properly).
996    local LEVEL=9
997    echo $LEVEL
998}
999
1000# Return the default platform sysroot corresponding to a given architecture
1001# This is the sysroot used to build the toolchain and other binaries like
1002# the STLport libraries.
1003# $1: Architecture name
1004get_default_platform_sysroot_for_arch ()
1005{
1006    local LEVEL=$(get_default_api_level_for_arch $1)
1007    echo "platforms/android-$LEVEL/arch-$1"
1008}
1009
1010# Guess what?
1011get_default_platform_sysroot_for_abi ()
1012{
1013    local ARCH=$(convert_abi_to_arch $1)
1014    $(get_default_platform_sysroot_for_arch $ARCH)
1015}
1016
1017
1018
1019# Return the host/build specific path for prebuilt toolchain binaries
1020# relative to $1.
1021#
1022# $1: target root NDK directory
1023# $2: toolchain name
1024# $3: optional, host system name
1025#
1026get_toolchain_install ()
1027{
1028    local NDK="$1"
1029    shift
1030    echo "$NDK/$(get_toolchain_install_subdir "$@")"
1031}
1032
1033# $1: toolchain name
1034# $2: optional, host system name
1035get_toolchain_install_subdir ()
1036{
1037    local SYSTEM=${2:-$(get_prebuilt_host_tag)}
1038    echo "toolchains/$1/prebuilt/$SYSTEM"
1039}
1040
1041# Return the relative install prefix for prebuilt host
1042# executables (relative to the NDK top directory).
1043# NOTE: This deals with MINGW==yes appropriately
1044#
1045# $1: optional, system name
1046# Out: relative path to prebuilt install prefix
1047get_prebuilt_install_prefix ()
1048{
1049    local TAG=${1:-$(get_prebuilt_host_tag)}
1050    echo "prebuilt/$TAG"
1051}
1052
1053# Return the relative path of an installed prebuilt host
1054# executable
1055# NOTE: This deals with MINGW==yes appropriately.
1056#
1057# $1: executable name
1058# $2: optional, host system name
1059# Out: path to prebuilt host executable, relative
1060get_prebuilt_host_exec ()
1061{
1062    local PREFIX EXE
1063    PREFIX=$(get_prebuilt_install_prefix $2)
1064    EXE=$(get_prebuilt_host_exe_ext)
1065    echo "$PREFIX/bin/$1$EXE"
1066}
1067
1068# Return the name of a given host executable
1069# $1: executable base name
1070# Out: executable name, with optional suffix (e.g. .exe for windows)
1071get_host_exec_name ()
1072{
1073    local EXE=$(get_prebuilt_host_exe_ext)
1074    echo "$1$EXE"
1075}
1076
1077# Return the directory where host-specific binaries are installed.
1078# $1: target root NDK directory
1079get_host_install ()
1080{
1081    echo "$1/$(get_prebuilt_install_prefix)"
1082}
1083
1084# Set the toolchain target NDK location.
1085# this sets TOOLCHAIN_PATH and TOOLCHAIN_PREFIX
1086# $1: target NDK path
1087# $2: toolchain name
1088set_toolchain_ndk ()
1089{
1090    TOOLCHAIN_PATH=`get_toolchain_install "$1" $2`
1091    log "Using toolchain path: $TOOLCHAIN_PATH"
1092
1093    TOOLCHAIN_PREFIX=$TOOLCHAIN_PATH/bin/$ABI_CONFIGURE_TARGET
1094    log "Using toolchain prefix: $TOOLCHAIN_PREFIX"
1095}
1096
1097# Check that a toolchain is properly installed at a target NDK location
1098#
1099# $1: target root NDK directory
1100# $2: toolchain name
1101#
1102check_toolchain_install ()
1103{
1104    TOOLCHAIN_PATH=`get_toolchain_install "$1" $2`
1105    if [ ! -d "$TOOLCHAIN_PATH" ] ; then
1106        echo "ERROR: Cannot find directory '$TOOLCHAIN_PATH'!"
1107        echo "       Toolchain '$2' not installed in '$NDK_DIR'!"
1108        echo "       Ensure that the toolchain has been installed there before."
1109        exit 1
1110    fi
1111
1112    set_toolchain_ndk $1 $2
1113}
1114
1115# $1: toolchain source directory
1116check_toolchain_src_dir ()
1117{
1118    local SRC_DIR="$1"
1119    if [ -z "$SRC_DIR" ]; then
1120        echo "ERROR: Please provide the path to the toolchain source tree. See --help"
1121        exit 1
1122    fi
1123
1124    if [ ! -d "$SRC_DIR" ]; then
1125        echo "ERROR: Not a directory: '$SRC_DIR'"
1126        exit 1
1127    fi
1128
1129    if [ ! -f "$SRC_DIR/build/configure" -o ! -d "$SRC_DIR/gcc" ]; then
1130        echo "ERROR: Either the file $SRC_DIR/build/configure or"
1131        echo "       the directory $SRC_DIR/gcc does not exist."
1132        echo "This is not the top of a toolchain tree: $SRC_DIR"
1133        echo "You must give the path to a copy of the toolchain source directories"
1134        echo "created by 'download-toolchain-sources.sh."
1135        exit 1
1136    fi
1137}
1138
1139#
1140# The NDK_TMPDIR variable is used to specify a root temporary directory
1141# when invoking toolchain build scripts. If it is not defined, we will
1142# create one here, and export the value to ensure that any scripts we
1143# call after that use the same one.
1144#
1145if [ -z "$NDK_TMPDIR" ]; then
1146    NDK_TMPDIR=/tmp/ndk-$USER/tmp/build-$$
1147    mkdir -p $NDK_TMPDIR
1148    if [ $? != 0 ]; then
1149        echo "ERROR: Could not create NDK_TMPDIR: $NDK_TMPDIR"
1150        exit 1
1151    fi
1152    export NDK_TMPDIR
1153fi
1154
1155# Define HOST_TAG32, as the 32-bit version of HOST_TAG
1156# We do this by replacing an -x86_64 suffix by -x86
1157HOST_TAG32=$HOST_TAG
1158case $HOST_TAG32 in
1159    *-x86_64)
1160        HOST_TAG32=${HOST_TAG%%_64}
1161        ;;
1162esac
1163