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