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