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
20# Warn if /bin/sh isn't bash.
21if [ -z "$BASH_VERSION" ] ; then
22    echo "WARNING: The shell running this script isn't bash.  Although we try to avoid bashism in scripts, things can happen."
23fi
24
25NDK_BUILDTOOLS_ABSPATH=$(cd $NDK_BUILDTOOLS_PATH && pwd)
26
27. $NDK_BUILDTOOLS_PATH/ndk-common.sh
28. $NDK_BUILDTOOLS_PATH/dev-defaults.sh
29
30
31# Given an input string of the form <foo>-<bar>-<version>, where
32# <version> can be <major>.<minor>, extract <major>
33extract_version ()
34{
35    echo $1 | tr '-' '\n' | tail -1
36}
37
38# $1: versioned name (e.g. arm-linux-androideabi-4.8)
39# Out: major version (e.g. 4)
40#
41# Examples:  arm-linux-androideabi-4.4.3 -> 4
42#            gmp-0.81 -> 0
43#
44extract_major_version ()
45{
46    local RET=$(extract_version $1 | cut -d . -f 1)
47    RET=${RET:-0}
48    echo $RET
49}
50
51# Same as extract_major_version, but for the minor version number
52# $1: versioned named
53# Out: minor version
54#
55extract_minor_version ()
56{
57    local RET=$(extract_version $1 | cut -d . -f 2)
58    RET=${RET:-0}
59    echo $RET
60}
61
62# Compare two version numbers and only succeeds if the first one is
63# greater than or equal to the second one.
64#
65# $1: first version (e.g. 4.9)
66# $2: second version (e.g. 4.8)
67#
68# Example: version_is_at_least 4.9 4.8 --> success
69#
70version_is_at_least ()
71{
72    local A_MAJOR A_MINOR B_MAJOR B_MINOR
73    A_MAJOR=$(extract_major_version $1)
74    B_MAJOR=$(extract_major_version $2)
75
76    if [ $A_MAJOR -lt $B_MAJOR ]; then
77        return 1
78    elif [ $A_MAJOR -gt $B_MAJOR ]; then
79        return 0
80    fi
81
82    # We have A_MAJOR == B_MAJOR here
83
84    A_MINOR=$(extract_minor_version $1)
85    B_MINOR=$(extract_minor_version $2)
86
87    if [ $A_MINOR -lt $B_MINOR ]; then
88        return 1
89    else
90        return 0
91    fi
92}
93
94#====================================================
95#
96#  UTILITY FUNCTIONS
97#
98#====================================================
99
100# Return the maximum length of a series of strings
101#
102# Usage:  len=`max_length <string1> <string2> ...`
103#
104max_length ()
105{
106    echo "$@" | tr ' ' '\n' | awk 'BEGIN {max=0} {len=length($1); if (len > max) max=len} END {print max}'
107}
108
109# Translate dashes to underscores
110# Usage:  str=`dashes_to_underscores <values>`
111dashes_to_underscores ()
112{
113    echo "$@" | tr '-' '_'
114}
115
116# Translate underscores to dashes
117# Usage: str=`underscores_to_dashes <values>`
118underscores_to_dashes ()
119{
120    echo "$@" | tr '_' '-'
121}
122
123# Translate commas to spaces
124# Usage: str=`commas_to_spaces <list>`
125commas_to_spaces ()
126{
127    echo "$@" | tr ',' ' '
128}
129
130# Translate spaces to commas
131# Usage: list=`spaces_to_commas <string>`
132spaces_to_commas ()
133{
134    echo "$@" | tr ' ' ','
135}
136
137# Remove trailing path of a path
138# $1: path
139remove_trailing_slash () {
140    echo ${1%%/}
141}
142
143# Reverse a file path directory
144# foo -> .
145# foo/bar -> ..
146# foo/bar/zoo -> ../..
147reverse_path ()
148{
149    local path cur item
150    path=${1%%/} # remove trailing slash
151    cur="."
152    if [ "$path" != "." ] ; then
153        for item in $(echo "$path" | tr '/' ' '); do
154            cur="../$cur"
155        done
156    fi
157    echo ${cur%%/.}
158}
159
160# test_reverse_path ()
161# {
162#     rr=`reverse_path $1`
163#     if [ "$rr" != "$2" ] ; then
164#         echo "ERROR: reverse_path '$1' -> '$rr' (expected '$2')"
165#     fi
166# }
167#
168# test_reverse_path . .
169# test_reverse_path ./ .
170# test_reverse_path foo ..
171# test_reverse_path foo/ ..
172# test_reverse_path foo/bar ../..
173# test_reverse_path foo/bar/ ../..
174# test_reverse_path foo/bar/zoo ../../..
175# test_reverse_path foo/bar/zoo/ ../../..
176
177# Sort a space-separated list and remove duplicates
178# $1+: slist
179# Output: new slist
180sort_uniq ()
181{
182    local RET
183    RET=$(echo "$@" | tr ' ' '\n' | sort -u)
184    echo $RET
185}
186
187# Return the list of all regular files under a given directory
188# $1: Directory path
189# Output: list of files, relative to $1
190list_files_under ()
191{
192    if [ -d "$1" ]; then
193        (cd $1 && find . -type f | sed -e "s!./!!" | sort -u)
194    else
195        echo ""
196    fi
197}
198
199# Returns all words in text that do not match any of the pattern
200# $1: pattern
201# $2: text
202filter_out ()
203{
204    local PATTERN="$1"
205    local TEXT="$2"
206    for pat in $PATTERN; do
207        pat=$"${pat//\//\\/}"
208        TEXT=$(echo $TEXT | sed -e 's/'$pat' //g' -e 's/'$pat'$//g')
209    done
210    echo $TEXT
211}
212
213# Assign a value to a variable
214# $1: Variable name
215# $2: Value
216var_assign ()
217{
218    eval $1=\"$2\"
219}
220
221#====================================================
222#
223#  OPTION PROCESSING
224#
225#====================================================
226
227# We recognize the following option formats:
228#
229#  -f
230#  --flag
231#
232#  -s<value>
233#  --setting=<value>
234#
235
236# NOTE: We translate '-' into '_' when storing the options in global variables
237#
238
239OPTIONS=""
240OPTION_FLAGS=""
241OPTION_SETTINGS=""
242
243# Set a given option attribute
244# $1: option name
245# $2: option attribute
246# $3: attribute value
247#
248option_set_attr ()
249{
250    eval OPTIONS_$1_$2=\"$3\"
251}
252
253# Get a given option attribute
254# $1: option name
255# $2: option attribute
256#
257option_get_attr ()
258{
259    echo `var_value OPTIONS_$1_$2`
260}
261
262# Register a new option
263# $1: option
264# $2: small abstract for the option
265# $3: optional. default value
266#
267register_option_internal ()
268{
269    optlabel=
270    optname=
271    optvalue=
272    opttype=
273    while [ -n "1" ] ; do
274        # Check for something like --setting=<value>
275        echo "$1" | grep -q -E -e '^--[^=]+=<.+>$'
276        if [ $? = 0 ] ; then
277            optlabel=`expr -- "$1" : '\(--[^=]*\)=.*'`
278            optvalue=`expr -- "$1" : '--[^=]*=\(<.*>\)'`
279            opttype="long_setting"
280            break
281        fi
282
283        # Check for something like --flag
284        echo "$1" | grep -q -E -e '^--[^=]+$'
285        if [ $? = 0 ] ; then
286            optlabel="$1"
287            opttype="long_flag"
288            break
289        fi
290
291        # Check for something like -f<value>
292        echo "$1" | grep -q -E -e '^-[A-Za-z0-9]<.+>$'
293        if [ $? = 0 ] ; then
294            optlabel=`expr -- "$1" : '\(-.\).*'`
295            optvalue=`expr -- "$1" : '-.\(<.+>\)'`
296            opttype="short_setting"
297            break
298        fi
299
300        # Check for something like -f
301        echo "$1" | grep -q -E -e '^-.$'
302        if [ $? = 0 ] ; then
303            optlabel="$1"
304            opttype="short_flag"
305            break
306        fi
307
308        echo "ERROR: Invalid option format: $1"
309        echo "       Check register_option call"
310        exit 1
311    done
312
313    log "new option: type='$opttype' name='$optlabel' value='$optvalue'"
314
315    optname=`dashes_to_underscores $optlabel`
316    OPTIONS="$OPTIONS $optname"
317    OPTIONS_TEXT="$OPTIONS_TEXT $1"
318    option_set_attr $optname label "$optlabel"
319    option_set_attr $optname otype "$opttype"
320    option_set_attr $optname value "$optvalue"
321    option_set_attr $optname text "$1"
322    option_set_attr $optname abstract "$2"
323    option_set_attr $optname default "$3"
324}
325
326# Register a new option with a function callback.
327#
328# $1: option
329# $2: name of function that will be called when the option is parsed
330# $3: small abstract for the option
331# $4: optional. default value
332#
333register_option ()
334{
335    local optname optvalue opttype optlabel
336    register_option_internal "$1" "$3" "$4"
337    option_set_attr $optname funcname "$2"
338}
339
340# Register a new option with a variable store
341#
342# $1: option
343# $2: name of variable that will be set by this option
344# $3: small abstract for the option
345#
346# NOTE: The current value of $2 is used as the default
347#
348register_var_option ()
349{
350    local optname optvalue opttype optlabel
351    register_option_internal "$1" "$3" "`var_value $2`"
352    option_set_attr $optname varname "$2"
353}
354
355
356MINGW=no
357DARWIN=no
358do_mingw_option ()
359{
360    if [ "$DARWIN" = "yes" ]; then
361        echo "Can not have both --mingw and --darwin"
362        exit 1
363    fi
364    MINGW=yes;
365}
366do_darwin_option ()
367{
368    if [ "$MINGW" = "yes" ]; then
369        echo "Can not have both --mingw and --darwin"
370        exit 1
371    fi
372    DARWIN=yes;
373}
374
375register_canadian_option ()
376{
377    if [ "$HOST_OS" = "linux" ] ; then
378        register_option "--mingw" do_mingw_option "Generate windows binaries on Linux."
379        register_option "--darwin" do_darwin_option "Generate darwin binaries on Linux."
380    fi
381}
382
383TRY64=no
384do_try64_option () { TRY64=yes; }
385
386register_try64_option ()
387{
388    register_option "--try-64" do_try64_option "Generate 64-bit only binaries."
389}
390
391
392register_jobs_option ()
393{
394    NUM_JOBS=$BUILD_NUM_CPUS
395    register_var_option "-j<number>" NUM_JOBS "Use <number> parallel build jobs"
396}
397
398# Print the help, including a list of registered options for this program
399# Note: Assumes PROGRAM_PARAMETERS and PROGRAM_DESCRIPTION exist and
400#       correspond to the parameters list and the program description
401#
402print_help ()
403{
404    local opt text abstract default
405
406    echo "Usage: $PROGNAME [options] $PROGRAM_PARAMETERS"
407    echo ""
408    if [ -n "$PROGRAM_DESCRIPTION" ] ; then
409        echo "$PROGRAM_DESCRIPTION"
410        echo ""
411    fi
412    echo "Valid options (defaults are in brackets):"
413    echo ""
414
415    maxw=`max_length "$OPTIONS_TEXT"`
416    AWK_SCRIPT=`echo "{ printf \"%-${maxw}s\", \\$1 }"`
417    for opt in $OPTIONS; do
418        text=`option_get_attr $opt text | awk "$AWK_SCRIPT"`
419        abstract=`option_get_attr $opt abstract`
420        default=`option_get_attr $opt default`
421        if [ -n "$default" ] ; then
422            echo "  $text     $abstract [$default]"
423        else
424            echo "  $text     $abstract"
425        fi
426    done
427    echo ""
428}
429
430option_panic_no_args ()
431{
432    echo "ERROR: Option '$1' does not take arguments. See --help for usage."
433    exit 1
434}
435
436option_panic_missing_arg ()
437{
438    echo "ERROR: Option '$1' requires an argument. See --help for usage."
439    exit 1
440}
441
442extract_parameters ()
443{
444    local opt optname otype value name fin funcname
445    PARAMETERS=""
446    while [ -n "$1" ] ; do
447        # If the parameter does not begin with a dash
448        # it is not an option.
449        param=`expr -- "$1" : '^\([^\-].*\)$'`
450        if [ -n "$param" ] ; then
451            if [ -z "$PARAMETERS" ] ; then
452                PARAMETERS="$1"
453            else
454                PARAMETERS="$PARAMETERS $1"
455            fi
456            shift
457            continue
458        fi
459
460        while [ -n "1" ] ; do
461            # Try to match a long setting, i.e. --option=value
462            opt=`expr -- "$1" : '^\(--[^=]*\)=.*$'`
463            if [ -n "$opt" ] ; then
464                otype="long_setting"
465                value=`expr -- "$1" : '^--[^=]*=\(.*\)$'`
466                break
467            fi
468
469            # Try to match a long flag, i.e. --option
470            opt=`expr -- "$1" : '^\(--.*\)$'`
471            if [ -n "$opt" ] ; then
472                otype="long_flag"
473                value="yes"
474                break
475            fi
476
477            # Try to match a short setting, i.e. -o<value>
478            opt=`expr -- "$1" : '^\(-[A-Za-z0-9]\)..*$'`
479            if [ -n "$opt" ] ; then
480                otype="short_setting"
481                value=`expr -- "$1" : '^-.\(.*\)$'`
482                break
483            fi
484
485            # Try to match a short flag, i.e. -o
486            opt=`expr -- "$1" : '^\(-.\)$'`
487            if [ -n "$opt" ] ; then
488                otype="short_flag"
489                value="yes"
490                break
491            fi
492
493            echo "ERROR: Unknown option '$1'. Use --help for list of valid values."
494            exit 1
495        done
496
497        #echo "Found opt='$opt' otype='$otype' value='$value'"
498
499        name=`dashes_to_underscores $opt`
500        found=0
501        for xopt in $OPTIONS; do
502            if [ "$name" != "$xopt" ] ; then
503                continue
504            fi
505            # Check that the type is correct here
506            #
507            # This also allows us to handle -o <value> as -o<value>
508            #
509            xotype=`option_get_attr $name otype`
510            if [ "$otype" != "$xotype" ] ; then
511                case "$xotype" in
512                "short_flag")
513                    option_panic_no_args $opt
514                    ;;
515                "short_setting")
516                    if [ -z "$2" ] ; then
517                        option_panic_missing_arg $opt
518                    fi
519                    value="$2"
520                    shift
521                    ;;
522                "long_flag")
523                    option_panic_no_args $opt
524                    ;;
525                "long_setting")
526                    option_panic_missing_arg $opt
527                    ;;
528                esac
529            fi
530            found=1
531            break
532            break
533        done
534        if [ "$found" = "0" ] ; then
535            echo "ERROR: Unknown option '$opt'. See --help for usage."
536            exit 1
537        fi
538        # Set variable or launch option-specific function.
539        varname=`option_get_attr $name varname`
540        if [ -n "$varname" ] ; then
541            eval ${varname}=\"$value\"
542        else
543            eval `option_get_attr $name funcname` \"$value\"
544        fi
545        shift
546    done
547}
548
549do_option_help ()
550{
551    print_help
552    exit 0
553}
554
555VERBOSE=no
556do_option_verbose ()
557{
558    VERBOSE=yes
559}
560
561DRYRUN=no
562do_option_dryrun ()
563{
564    DRYRUN=yes
565}
566
567register_option "--help"          do_option_help     "Print this help."
568register_option "--verbose"       do_option_verbose  "Enable verbose mode."
569register_option "--dryrun"        do_option_dryrun   "Set to dryrun mode."
570
571#====================================================
572#
573#  TOOLCHAIN AND ABI PROCESSING
574#
575#====================================================
576
577# Determine optional variable value
578# $1: final variable name
579# $2: option variable name
580# $3: small description for the option
581fix_option ()
582{
583    if [ -n "$2" ] ; then
584        eval $1="$2"
585        log "Using specific $3: $2"
586    else
587        log "Using default $3: `var_value $1`"
588    fi
589}
590
591
592# If SYSROOT is empty, check that $1/$2 contains a sysroot
593# and set the variable to it.
594#
595# $1: sysroot path
596# $2: platform/arch suffix
597check_sysroot ()
598{
599    if [ -z "$SYSROOT" ] ; then
600        log "Probing directory for sysroot: $1/$2"
601        if [ -d $1/$2 ] ; then
602            SYSROOT=$1/$2
603        fi
604    fi
605}
606
607# Determine sysroot
608# $1: Option value (or empty)
609#
610fix_sysroot ()
611{
612    if [ -n "$1" ] ; then
613        eval SYSROOT="$1"
614        log "Using specified sysroot: $1"
615    else
616        SYSROOT_SUFFIX=$PLATFORM/arch-$ARCH
617        SYSROOT=
618        check_sysroot $ANDROID_BUILD_TOP/prebuilts/ndk/current/platforms $SYSROOT_SUFFIX
619        check_sysroot $ANDROID_NDK_ROOT/platforms $SYSROOT_SUFFIX
620        check_sysroot `dirname $ANDROID_NDK_ROOT`/development/ndk/platforms $SYSROOT_SUFFIX
621
622        if [ -z "$SYSROOT" ] ; then
623            echo "ERROR: Could not find NDK sysroot path for $SYSROOT_SUFFIX."
624            echo "       Use --sysroot=<path> to specify one."
625            exit 1
626        fi
627    fi
628
629    if [ ! -f $SYSROOT/usr/include/stdlib.h ] ; then
630        echo "ERROR: Invalid sysroot path: $SYSROOT"
631        echo "       Use --sysroot=<path> to indicate a valid one."
632        exit 1
633    fi
634}
635
636# Check for the availability of a compatibility SDK in Darwin
637# this can be used to generate binaries compatible with either Tiger or
638# Leopard.
639#
640# $1: SDK root path
641# $2: Optional MacOS X minimum version (e.g. 10.5)
642DARWIN_MINVER=10.6
643check_darwin_sdk ()
644{
645    local MACSDK="$1"
646    local MINVER=$2
647
648    if [ -z "$MINVER" ] ; then
649        # expect SDK root path ended up with either MacOSX##.#.sdk or MacOSX##.#u.sdk
650        MINVER=${MACSDK##*MacOSX}
651        MINVER=${MINVER%%.sdk*}
652        if [ "$MINVER" = "10.4u" ]; then
653            MINVER=10.4
654        fi
655    fi
656    if [ -d "$MACSDK" ] ; then
657        HOST_CFLAGS=$HOST_CFLAGS" -isysroot $MACSDK -mmacosx-version-min=$MINVER -DMAXOSX_DEPLOYEMENT_TARGET=$MINVER"
658        HOST_LDFLAGS=$HOST_LDFLAGS" -Wl,-syslibroot,$MACSDK -mmacosx-version-min=$MINVER"
659        DARWIN_MINVER=$MINVER
660        return 0  # success
661    fi
662    return 1
663}
664
665# Probe Darwin SDK in specified diectory $DARWIN_SYSROOT, or
666# /Developer/SDKs/MacOSX10.6.sdk
667#
668probe_darwin_sdk ()
669{
670    if [ -n "$DARWIN_SYSROOT" ]; then
671        if check_darwin_sdk "$DARWIN_SYSROOT"; then
672            log "Use darwin sysroot $DARWIN_SYSROOT"
673        else
674            echo "darwin sysroot $DARWIN_SYSROOT is not valid"
675            exit 1
676        fi
677    elif check_darwin_sdk /Developer/SDKs/MacOSX10.6.sdk 10.6; then
678        log "Generating Snow Leopard-compatible binaries!"
679    else
680        local version=`sw_vers -productVersion`
681        log "Generating $version-compatible binaries!"
682    fi
683}
684
685handle_canadian_build ()
686{
687    HOST_EXE=
688    if [ "$MINGW" = "yes" -o "$DARWIN" = "yes" ] ; then
689        case $HOST_TAG in
690            linux-*)
691                ;;
692            *)
693                echo "ERROR: Can only enable --mingw or --darwin on Linux platforms !"
694                exit 1
695                ;;
696        esac
697        if [ "$MINGW" = "yes" ] ; then
698            # NOTE: Use x86_64-pc-mingw32msvc or i586-pc-mingw32msvc because wrappers are generated
699            #       using these names
700            if [ "$TRY64" = "yes" ]; then
701                ABI_CONFIGURE_HOST=x86_64-pc-mingw32msvc
702                HOST_TAG=windows-x86_64
703            else
704                ABI_CONFIGURE_HOST=i586-pc-mingw32msvc
705                HOST_TAG=windows
706            fi
707            HOST_OS=windows
708            HOST_EXE=.exe
709        else
710            if [ "$TRY64" = "yes" ]; then
711                ABI_CONFIGURE_HOST=x86_64-apple-darwin
712                HOST_TAG=darwin-x86_64
713            else
714                ABI_CONFIGURE_HOST=i686-apple-darwin
715                HOST_TAG=darwin-x86
716            fi
717            HOST_OS=darwin
718        fi
719    fi
720}
721
722# Find mingw toolchain
723#
724# Set MINGW_GCC to the found mingw toolchain
725#
726find_mingw_toolchain ()
727{
728    if [ "$DEBIAN_NAME" -a "$BINPREFIX" -a "$MINGW_GCC" ]; then
729        return
730    fi
731    # IMPORTANT NOTE: binutils 2.21 requires a cross toolchain named
732    # i585-pc-mingw32msvc-gcc, or it will fail its configure step late
733    # in the toolchain build. Note that binutils 2.19 can build properly
734    # with i585-mingw32mvsc-gcc, which is the name used by the 'mingw32'
735    # toolchain install on Debian/Ubuntu.
736    #
737    # To solve this dilemma, we create a wrapper toolchain named
738    # i586-pc-mingw32msvc-gcc that really calls i586-mingw32msvc-gcc,
739    # this works with all versions of binutils.
740    #
741    # We apply the same logic to the 64-bit Windows cross-toolchain
742    #
743    # Fedora note: On Fedora it's x86_64-w64-mingw32- or i686-w64-mingw32-
744    # On older Fedora it's 32-bit only and called i686-pc-mingw32-
745    # so we just add more prefixes to the list to check.
746    if [ "$HOST_ARCH" = "x86_64" -a "$TRY64" = "yes" ]; then
747        BINPREFIX=x86_64-pc-mingw32msvc-
748        BINPREFIXLST="x86_64-pc-mingw32msvc- x86_64-w64-mingw32- amd64-mingw32msvc-"
749        DEBIAN_NAME=mingw-w64
750    else
751        # we are trying 32 bit anyway, so forcing it to avoid build issues
752        force_32bit_binaries
753        BINPREFIX=i586-pc-mingw32msvc-
754        BINPREFIXLST="i586-pc-mingw32msvc- i686-pc-mingw32- i586-mingw32msvc- i686-w64-mingw32-"
755        DEBIAN_NAME=mingw-w64
756    fi
757
758    # Scan $BINPREFIXLST list to find installed mingw toolchain. It will be
759    # wrapped later with $BINPREFIX.
760    for i in $BINPREFIXLST; do
761        find_program MINGW_GCC ${i}gcc
762        if [ -n "$MINGW_GCC" ]; then
763            dump "Found mingw toolchain: $MINGW_GCC"
764            break
765        fi
766    done
767}
768
769# Check there is a working cross-toolchain installed.
770#
771# $1: install directory for mingw/darwin wrapper toolchain
772#
773prepare_canadian_toolchain ()
774{
775    if [ "$MINGW" != "yes" -a "$DARWIN" != "yes" ]; then
776        return
777    fi
778    CROSS_GCC=
779    if [ "$MINGW" = "yes" ]; then
780        find_mingw_toolchain
781        if [ -z "$MINGW_GCC" ]; then
782            echo "ERROR: Could not find in your PATH any of:"
783            for i in $BINPREFIXLST; do echo "   ${i}gcc"; done
784            echo "Please install the corresponding cross-toolchain and re-run this script"
785            echo "TIP: On Debian or Ubuntu, try: sudo apt-get install $DEBIAN_NAME"
786            exit 1
787        fi
788        CROSS_GCC=$MINGW_GCC
789    else
790        if [ -z "$DARWIN_TOOLCHAIN" ]; then
791            echo "Please set DARWIN_TOOLCHAIN to darwin cross-toolchain"
792            exit 1
793        fi
794        if [ ! -f "${DARWIN_TOOLCHAIN}-gcc" ]; then
795            echo "darwin cross-toolchain $DARWIN_TOOLCHAIN-gcc doesn't exist"
796            exit 1
797        fi
798        if [ "$HOST_ARCH" = "x86_64" -a "$TRY64" = "yes" ]; then
799            BINPREFIX=x86_64-apple-darwin-
800            DEBIAN_NAME=darwin64
801            HOST_CFLAGS=$HOST_CFLAGS" -m64"
802        else
803            force_32bit_binaries
804            BINPREFIX=i686-apple-darwin-
805            DEBIAN_NAME=darwin32
806            HOST_CFLAGS=$HOST_CFLAGS" -m32"
807        fi
808        CROSS_GCC=${DARWIN_TOOLCHAIN}-gcc
809        probe_darwin_sdk
810    fi
811
812    # Create a wrapper toolchain, and prepend its dir to our PATH
813    CROSS_WRAP_DIR="$1"/$DEBIAN_NAME-wrapper
814    rm -rf "$CROSS_WRAP_DIR"
815    mkdir -p "$CROSS_WRAP_DIR"
816
817    if [ "$DARWIN" = "yes" ] ; then
818        cat > "$CROSS_WRAP_DIR/sw_vers" <<EOF
819#!/bin/sh
820# Tiny utility for the real sw_vers some Makefiles need
821case \$1 in
822    -productVersion)
823        echo $DARWIN_MINVER
824        ;;
825    *)
826        echo "ERROR: Unknown switch \$1"
827        exit 1
828esac
829EOF
830    chmod 0755 "$CROSS_WRAP_DIR/sw_vers"
831    fi
832
833    DST_PREFIX=${CROSS_GCC%gcc}
834    if [ "$NDK_CCACHE" ]; then
835        DST_PREFIX="$NDK_CCACHE $DST_PREFIX"
836    fi
837    $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=$BINPREFIX --dst-prefix="$DST_PREFIX" "$CROSS_WRAP_DIR" \
838        --cflags="$HOST_CFLAGS" --cxxflags="$HOST_CFLAGS" --ldflags="$HOST_LDFLAGS"
839    # generate wrappers for BUILD toolchain
840    # this is required for mingw/darwin build to avoid tools canadian cross configuration issues
841    # 32-bit BUILD toolchain
842    LEGACY_TOOLCHAIN_DIR="$ANDROID_BUILD_TOP/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8"
843    $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=i386-linux-gnu- \
844            --cflags="-m32" --cxxflags="-m32" --ldflags="-m elf_i386" --asflags="--32" \
845            --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/x86_64-linux-" "$CROSS_WRAP_DIR"
846    $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=i386-pc-linux-gnu- \
847            --cflags="-m32" --cxxflags="-m32" --ldflags="-m elf_i386" --asflags="--32" \
848            --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/x86_64-linux-" "$CROSS_WRAP_DIR"
849    # 64-bit BUILD toolchain.  libbfd is still built in 32-bit.
850    $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=x86_64-linux-gnu- \
851            --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/x86_64-linux-" "$CROSS_WRAP_DIR"
852    $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=x86_64-pc-linux-gnu- \
853            --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/x86_64-linux-" "$CROSS_WRAP_DIR"
854    fail_panic "Could not create $DEBIAN_NAME wrapper toolchain in $CROSS_WRAP_DIR"
855
856    export PATH=$CROSS_WRAP_DIR:$PATH
857    dump "Using $DEBIAN_NAME wrapper: $CROSS_WRAP_DIR/${BINPREFIX}gcc"
858}
859
860handle_host ()
861{
862    if [ "$TRY64" != "yes" ]; then
863        force_32bit_binaries  # to modify HOST_TAG and others
864        HOST_BITS=32
865    fi
866    handle_canadian_build
867}
868
869setup_ccache ()
870{
871    # Support for ccache compilation
872    # We can't use this here when building Windows/darwin binaries on Linux with
873    # binutils 2.21, because defining CC/CXX in the environment makes the
874    # configure script fail later
875    #
876    if [ "$NDK_CCACHE" -a "$MINGW" != "yes" -a "$DARWIN" != "yes" ]; then
877        NDK_CCACHE_CC=$CC
878        NDK_CCACHE_CXX=$CXX
879        # Unfortunately, we can just do CC="$NDK_CCACHE $CC" because some
880        # configure scripts are not capable of dealing with this properly
881        # E.g. the ones used to rebuild the GCC toolchain from scratch.
882        # So instead, use a wrapper script
883        CC=$NDK_BUILDTOOLS_ABSPATH/ndk-ccache-gcc.sh
884        CXX=$NDK_BUILDTOOLS_ABSPATH/ndk-ccache-g++.sh
885        export NDK_CCACHE_CC NDK_CCACHE_CXX
886        log "Using ccache compilation"
887        log "NDK_CCACHE_CC=$NDK_CCACHE_CC"
888        log "NDK_CCACHE_CXX=$NDK_CCACHE_CXX"
889    fi
890}
891
892prepare_common_build ()
893{
894    if [ "$MINGW" = "yes" -o "$DARWIN" = "yes" ]; then
895        if [ "$TRY64" = "yes" ]; then
896            HOST_BITS=64
897        else
898            HOST_BITS=32
899        fi
900        if [ "$MINGW" = "yes" ]; then
901            log "Generating $HOST_BITS-bit Windows binaries"
902        else
903            log "Generating $HOST_BITS-bit Darwin binaries"
904        fi
905        # Do *not* set CC and CXX when building the Windows/Darwin binaries in canadian build.
906        # Otherwise, the GCC configure/build script will mess that Canadian cross
907        # build in weird ways. Instead we rely on the toolchain detected or generated
908        # previously in prepare_canadian_toolchain.
909        unset CC CXX
910        return
911    fi
912
913    # On Linux, detect our legacy-compatible toolchain when in the Android
914    # source tree, and use it to force the generation of glibc-2.7 compatible
915    # binaries.
916    #
917    # We only do this if the CC variable is not defined to a given value
918    if [ -z "$CC" ]; then
919        LEGACY_TOOLCHAIN_DIR=
920        if [ "$HOST_OS" = "linux" ]; then
921            LEGACY_TOOLCHAIN_DIR="$ANDROID_BUILD_TOP/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8/bin"
922            LEGACY_TOOLCHAIN_PREFIX="$LEGACY_TOOLCHAIN_DIR/x86_64-linux-"
923        elif [ "$HOST_OS" = "darwin" ]; then
924            LEGACY_TOOLCHAIN_DIR="$ANDROID_BUILD_TOP/prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1/bin"
925            LEGACY_TOOLCHAIN_PREFIX="$LEGACY_TOOLCHAIN_DIR/i686-apple-darwin10-"
926        fi
927        if [ -d "$LEGACY_TOOLCHAIN_DIR" ] ; then
928            log "Forcing generation of $HOST_OS binaries with legacy toolchain"
929            CC="${LEGACY_TOOLCHAIN_PREFIX}gcc"
930            CXX="${LEGACY_TOOLCHAIN_PREFIX}g++"
931        fi
932    fi
933
934    CC=${CC:-gcc}
935    CXX=${CXX:-g++}
936    STRIP=${STRIP:-strip}
937    case $HOST_TAG in
938        darwin-*)
939            probe_darwin_sdk
940            ;;
941    esac
942
943    # Force generation of 32-bit binaries on 64-bit systems.
944    # We used to test the value of $HOST_TAG for *-x86_64, but this is
945    # not sufficient on certain systems.
946    #
947    # For example, Snow Leopard can be booted with a 32-bit kernel, running
948    # a 64-bit userland, with a compiler that generates 64-bit binaries by
949    # default *even* though "gcc -v" will report --target=i686-apple-darwin10!
950    #
951    # So know, simply probe for the size of void* by performing a small runtime
952    # compilation test.
953    #
954    cat > $TMPC <<EOF
955    /* this test should fail if the compiler generates 64-bit machine code */
956    int test_array[1-2*(sizeof(void*) != 4)];
957EOF
958    log_n "Checking whether the compiler generates 32-bit binaries..."
959    log $CC $HOST_CFLAGS -c -o $TMPO $TMPC
960    $NDK_CCACHE $CC $HOST_CFLAGS -c -o $TMPO $TMPC >$TMPL 2>&1
961    if [ $? != 0 ] ; then
962        log "no"
963        if [ "$TRY64" != "yes" ]; then
964            # NOTE: We need to modify the definitions of CC and CXX directly
965            #        here. Just changing the value of CFLAGS / HOST_CFLAGS
966            #        will not work well with the GCC toolchain scripts.
967            CC="$CC -m32"
968            CXX="$CXX -m32"
969        fi
970    else
971        log "yes"
972        if [ "$TRY64" = "yes" ]; then
973            CC="$CC -m64"
974            CXX="$CXX -m64"
975        fi
976    fi
977
978    if [ "$TRY64" = "yes" ]; then
979        HOST_BITS=64
980    else
981        force_32bit_binaries  # to modify HOST_TAG and others
982        HOST_BITS=32
983    fi
984}
985
986prepare_host_build ()
987{
988    prepare_common_build
989
990    # Now deal with mingw or darwin
991    if [ "$MINGW" = "yes" -o "$DARWIN" = "yes" ]; then
992        handle_canadian_build
993        CC=$ABI_CONFIGURE_HOST-gcc
994        CXX=$ABI_CONFIGURE_HOST-g++
995        CPP=$ABI_CONFIGURE_HOST-cpp
996        LD=$ABI_CONFIGURE_HOST-ld
997        AR=$ABI_CONFIGURE_HOST-ar
998        AS=$ABI_CONFIGURE_HOST-as
999        RANLIB=$ABI_CONFIGURE_HOST-ranlib
1000        STRIP=$ABI_CONFIGURE_HOST-strip
1001        export CC CXX CPP LD AR AS RANLIB STRIP
1002    fi
1003
1004    setup_ccache
1005}
1006
1007prepare_abi_configure_build ()
1008{
1009    # detect build tag
1010    case $HOST_TAG in
1011        linux-x86)
1012            ABI_CONFIGURE_BUILD=i386-linux-gnu
1013            ;;
1014        linux-x86_64)
1015            ABI_CONFIGURE_BUILD=x86_64-linux-gnu
1016            ;;
1017        darwin-x86)
1018            ABI_CONFIGURE_BUILD=i686-apple-darwin
1019            ;;
1020        darwin-x86_64)
1021            ABI_CONFIGURE_BUILD=x86_64-apple-darwin
1022            ;;
1023        windows)
1024            ABI_CONFIGURE_BUILD=i686-pc-cygwin
1025            ;;
1026        *)
1027            echo "ERROR: Unsupported HOST_TAG: $HOST_TAG"
1028            echo "Please update 'prepare_host_flags' in build/tools/prebuilt-common.sh"
1029            ;;
1030    esac
1031}
1032
1033prepare_target_build ()
1034{
1035    prepare_abi_configure_build
1036
1037    # By default, assume host == build
1038    ABI_CONFIGURE_HOST="$ABI_CONFIGURE_BUILD"
1039
1040    prepare_common_build
1041    HOST_GMP_ABI=$HOST_BITS
1042
1043    # Now handle the --mingw/--darwin flag
1044    if [ "$MINGW" = "yes" -o "$DARWIN" = "yes" ] ; then
1045        handle_canadian_build
1046        STRIP=$ABI_CONFIGURE_HOST-strip
1047        if [ "$MINGW" = "yes" ] ; then
1048            # It turns out that we need to undefine this to be able to
1049            # perform a canadian-cross build with mingw. Otherwise, the
1050            # GMP configure scripts will not be called with the right options
1051            HOST_GMP_ABI=
1052        fi
1053    fi
1054
1055    setup_ccache
1056}
1057
1058# $1: Toolchain name
1059#
1060parse_toolchain_name ()
1061{
1062    TOOLCHAIN=$1
1063    if [ -z "$TOOLCHAIN" ] ; then
1064        echo "ERROR: Missing toolchain name!"
1065        exit 1
1066    fi
1067
1068    ABI_CFLAGS_FOR_TARGET=
1069    ABI_CXXFLAGS_FOR_TARGET=
1070
1071    # Determine ABI based on toolchain name
1072    #
1073    case "$TOOLCHAIN" in
1074    arm-linux-androideabi-*)
1075        ARCH="arm"
1076        ABI="armeabi"
1077        ABI_CONFIGURE_TARGET="arm-linux-androideabi"
1078        ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=armv5te"
1079        ;;
1080    arm-eabi-*)
1081        ARCH="arm"
1082        ABI="armeabi"
1083        ABI_CONFIGURE_TARGET="arm-eabi"
1084        ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=armv5te --disable-gold --disable-libgomp"
1085        ;;
1086    aarch64-linux-android-*)
1087        ARCH="arm64"
1088        ABI="arm64-v8a"
1089        ABI_CONFIGURE_TARGET="aarch64-linux-android"
1090        ;;
1091    x86-*)
1092        ARCH="x86"
1093        ABI=$ARCH
1094        ABI_INSTALL_NAME="x86"
1095        ABI_CONFIGURE_TARGET="i686-linux-android"
1096        # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time
1097        # You can't really build these separately at the moment.
1098        ABI_CFLAGS_FOR_TARGET="-fPIC"
1099        ;;
1100    x86_64-*)
1101        ARCH="x86_64"
1102        ABI=$ARCH
1103        ABI_INSTALL_NAME="x86_64"
1104        ABI_CONFIGURE_TARGET="x86_64-linux-android"
1105        # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time
1106        # You can't really build these separately at the moment.
1107        ABI_CFLAGS_FOR_TARGET="-fPIC"
1108        ;;
1109    mipsel*)
1110        ARCH="mips"
1111        ABI=$ARCH
1112        ABI_INSTALL_NAME="mips"
1113        ABI_CONFIGURE_TARGET="mipsel-linux-android"
1114        # Set default to mips32
1115        ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=mips32"
1116        # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time
1117        # You can't really build these separately at the moment.
1118        # Add -fpic, because MIPS NDK will need to link .a into .so.
1119        ABI_CFLAGS_FOR_TARGET="-fexceptions -fpic"
1120        ABI_CXXFLAGS_FOR_TARGET="-frtti -fpic"
1121        # Add --disable-fixed-point to disable fixed-point support
1122        ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --disable-fixed-point"
1123        ;;
1124    mips64el*)
1125        ARCH="mips64"
1126        ABI=$ARCH
1127        ABI_INSTALL_NAME="mips64"
1128        ABI_CONFIGURE_TARGET="mips64el-linux-android"
1129        # Set default to mips64r6
1130        ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=mips64r6"
1131        # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time
1132        # You can't really build these separately at the moment.
1133        # Add -fpic, because MIPS NDK will need to link .a into .so.
1134        ABI_CFLAGS_FOR_TARGET="-fexceptions -fpic"
1135        ABI_CXXFLAGS_FOR_TARGET="-frtti -fpic"
1136        # Add --disable-fixed-point to disable fixed-point support
1137        ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --disable-fixed-point"
1138        ;;
1139    * )
1140        echo "Invalid toolchain specified. Expected (arm-linux-androideabi-*|arm-eabi-*|x86-*|mipsel*|mips64el*)"
1141        echo ""
1142        print_help
1143        exit 1
1144        ;;
1145    esac
1146
1147    log "Targetting CPU: $ARCH"
1148
1149    GCC_VERSION=`expr -- "$TOOLCHAIN" : '.*-\([0-9x\.]*\)'`
1150    log "Using GCC version: $GCC_VERSION"
1151
1152    # Determine --host value when building gdbserver
1153
1154    case "$TOOLCHAIN" in
1155    arm-*)
1156        GDBSERVER_HOST=arm-eabi-linux
1157        GDBSERVER_CFLAGS="-fno-short-enums"
1158        GDBSERVER_LDFLAGS=
1159        ;;
1160    aarch64-*)
1161        GDBSERVER_HOST=aarch64-eabi-linux
1162        GDBSERVER_CFLAGS="-fno-short-enums -DUAPI_HEADERS"
1163        GDBSERVER_LDFLAGS=
1164        ;;
1165    x86-*)
1166        GDBSERVER_HOST=i686-linux-android
1167        GDBSERVER_CFLAGS=
1168        GDBSERVER_LDFLAGS=
1169        ;;
1170    x86_64-*)
1171        GDBSERVER_HOST=x86_64-linux-android
1172        GDBSERVER_CFLAGS=-DUAPI_HEADERS
1173        GDBSERVER_LDFLAGS=
1174        ;;
1175    mipsel-*)
1176        GDBSERVER_HOST=mipsel-linux-android
1177        GDBSERVER_CFLAGS=
1178        GDBSERVER_LDFLAGS=
1179        ;;
1180    mips64el-*)
1181        GDBSERVER_HOST=mips64el-linux-android
1182        GDBSERVER_CFLAGS=-DUAPI_HEADERS
1183        GDBSERVER_LDFLAGS=
1184        ;;
1185    *)
1186        echo "Unknown TOOLCHAIN=$TOOLCHAIN"
1187        exit
1188    esac
1189}
1190
1191# Return the host "tag" used to identify prebuilt host binaries.
1192# NOTE: Handles the case where '$MINGW = true' or '$DARWIN = true'
1193# For now, valid values are: linux-x86, darwin-x86 and windows
1194get_prebuilt_host_tag ()
1195{
1196    local RET=$HOST_TAG
1197    if [ "$MINGW" = "yes" ]; then
1198        if [ "$TRY64" = "no" ]; then
1199            RET=windows
1200        else
1201            RET=windows-x86_64
1202        fi
1203    fi
1204    if [ "$DARWIN" = "yes" ]; then
1205        RET=darwin-x86_64  # let the following handles 32-bit case
1206    fi
1207    case $RET in
1208        linux-*)
1209            RET=linux-x86_64
1210            ;;
1211        darwin-*)
1212            RET=darwin-x86_64
1213            ;;
1214    esac
1215    echo $RET
1216}
1217
1218# Return the executable suffix corresponding to host executables
1219get_prebuilt_host_exe_ext ()
1220{
1221    if [ "$MINGW" = "yes" ]; then
1222        echo ".exe"
1223    else
1224        echo ""
1225    fi
1226}
1227
1228# Get library suffix for given ABI
1229# $1: ABI
1230# Return: .so or .bc
1231get_lib_suffix_for_abi ()
1232{
1233    local ABI=$1
1234    echo ".so"
1235}
1236
1237# Convert an ABI name into an Architecture name
1238# $1: ABI name
1239# Result: Arch name
1240convert_abi_to_arch ()
1241{
1242    local RET
1243    local ABI=$1
1244    case $ABI in
1245        armeabi|armeabi-v7a|armeabi-v7a-hard)
1246            RET=arm
1247            ;;
1248        x86|mips|x86_64|mips64)
1249            RET=$ABI
1250            ;;
1251        mips32r6)
1252            RET=mips
1253            ;;
1254        arm64-v8a)
1255            RET=arm64
1256            ;;
1257        *)
1258            >&2 echo "ERROR: Unsupported ABI name: $ABI, use one of: armeabi, armeabi-v7a, x86, mips, armeabi-v7a-hard, arm64-v8a, x86_64 or mips64"
1259            exit 1
1260            ;;
1261    esac
1262    echo "$RET"
1263}
1264
1265# Take architecture name as input, and output the list of corresponding ABIs
1266# Inverse for convert_abi_to_arch
1267# $1: ARCH name
1268# Out: ABI names list (comma-separated)
1269convert_arch_to_abi ()
1270{
1271    local RET
1272    local ARCH=$1
1273    case $ARCH in
1274        arm)
1275            RET=armeabi,armeabi-v7a,armeabi-v7a-hard
1276            ;;
1277        x86|x86_64|mips|mips64)
1278            RET=$ARCH
1279            ;;
1280        arm64)
1281            RET=arm64-v8a
1282            ;;
1283        *)
1284            >&2 echo "ERROR: Unsupported ARCH name: $ARCH, use one of: arm, x86, mips"
1285            exit 1
1286            ;;
1287    esac
1288    echo "$RET"
1289}
1290
1291# Take a list of architecture names as input, and output the list of corresponding ABIs
1292# $1: ARCH names list (separated by spaces or commas)
1293# Out: ABI names list (comma-separated)
1294convert_archs_to_abis ()
1295{
1296    local RET
1297    for ARCH in $(commas_to_spaces $@); do
1298       ABI=$(convert_arch_to_abi $ARCH)
1299       if [ -n "$ABI" ]; then
1300          if [ -n "$RET" ]; then
1301             RET=$RET",$ABI"
1302          else
1303             RET=$ABI
1304          fi
1305       else   # Error message is printed by convert_arch_to_abi
1306          exit 1
1307       fi
1308    done
1309    echo "$RET"
1310}
1311
1312# Return the default toolchain binary path prefix for given architecture and gcc version
1313# For example: arm 4.8 -> toolchains/<system>/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-
1314# $1: Architecture name
1315# $2: GCC version
1316# $3: optional, system name, defaults to $HOST_TAG
1317get_toolchain_binprefix_for_arch ()
1318{
1319    local NAME PREFIX DIR BINPREFIX
1320    local SYSTEM=${3:-$(get_prebuilt_host_tag)}
1321    NAME=$(get_toolchain_name_for_arch $1 $2)
1322    PREFIX=$(get_default_toolchain_prefix_for_arch $1)
1323    DIR=$(get_toolchain_install . $NAME $SYSTEM)
1324    BINPREFIX=${DIR#./}/bin/$PREFIX-
1325    echo "$BINPREFIX"
1326}
1327
1328# Return llvm toolchain binary path prefix for given llvm version
1329# $1: llvm version
1330# $2: optional, system name, defaults to $HOST_TAG
1331get_llvm_toolchain_binprefix ()
1332{
1333    local NAME DIR BINPREFIX
1334    local SYSTEM=${2:-$(get_prebuilt_host_tag)}
1335    SYSTEM=${SYSTEM%_64} # Trim _64 suffix. We only have one LLVM.
1336    BINPREFIX=$ANDROID_BUILD_TOP/prebuilts/clang/$SYSTEM/host/$1/bin
1337    echo "$BINPREFIX"
1338}
1339
1340# Return default API level for a given arch
1341# This is the level used to build the toolchains.
1342#
1343# $1: Architecture name
1344get_default_api_level_for_arch ()
1345{
1346    # For now, always build the toolchain against API level 9 for 32-bit arch
1347    # and API level $FIRST_API64_LEVEL for 64-bit arch
1348    case $1 in
1349        *64) echo $FIRST_API64_LEVEL ;;
1350        *) echo 9 ;;
1351    esac
1352}
1353
1354# Return the default platform sysroot corresponding to a given architecture
1355# This is the sysroot used to build the toolchain and other binaries like
1356# the STLport libraries.
1357# $1: Architecture name
1358get_default_platform_sysroot_for_arch ()
1359{
1360    local ARCH=$1
1361    local LEVEL=$(get_default_api_level_for_arch $ARCH)
1362
1363    if [ "$ARCH" != "${ARCH%%64*}" ] ; then
1364        LEVEL=$FIRST_API64_LEVEL
1365    fi
1366    echo "platforms/android-$LEVEL/arch-$ARCH"
1367}
1368
1369# Return the default platform sysroot corresponding to a given abi
1370# $1: ABI
1371get_default_platform_sysroot_for_abi ()
1372{
1373    local ARCH=$(convert_abi_to_arch $1)
1374    $(get_default_platform_sysroot_for_arch $ARCH)
1375}
1376
1377# Return the default libs dir corresponding to a given architecture
1378# $1: Architecture name
1379get_default_libdir_for_arch ()
1380{
1381    case $1 in
1382      x86_64|mips64) echo "lib64" ;;
1383      arm64) echo "lib" ;; # return "lib" until aarch64 is built to look for sysroot/usr/lib64
1384      *) echo "lib" ;;
1385    esac
1386}
1387
1388# Return the default libs dir corresponding to a given abi
1389# $1: ABI
1390get_default_libdir_for_abi ()
1391{
1392    local ARCH
1393
1394    case $1 in
1395      mips32r6) echo "libr6" ;;
1396      *)
1397        local ARCH=$(convert_abi_to_arch $1)
1398        echo "$(get_default_libdir_for_arch $ARCH)"
1399        ;;
1400    esac
1401}
1402
1403# Return the host/build specific path for prebuilt toolchain binaries
1404# relative to $1.
1405#
1406# $1: target root NDK directory
1407# $2: toolchain name
1408# $3: optional, host system name
1409#
1410get_toolchain_install ()
1411{
1412    local NDK="$1"
1413    shift
1414    echo "$NDK/$(get_toolchain_install_subdir "$@")"
1415}
1416
1417# $1: toolchain name
1418# $2: optional, host system name
1419get_toolchain_install_subdir ()
1420{
1421    local SYSTEM=${2:-$(get_prebuilt_host_tag)}
1422    echo "toolchains/$SYSTEM/$1"
1423}
1424
1425# Return the relative install prefix for prebuilt host
1426# executables (relative to the NDK top directory).
1427#
1428# Out: relative path to prebuilt install prefix
1429get_prebuilt_install_prefix ()
1430{
1431    echo "host-tools"
1432}
1433
1434# Return the relative path of an installed prebuilt host
1435# executable.
1436#
1437# $1: executable name
1438# Out: path to prebuilt host executable, relative
1439get_prebuilt_host_exec ()
1440{
1441    local PREFIX EXE
1442    PREFIX=$(get_prebuilt_install_prefix)
1443    EXE=$(get_prebuilt_host_exe_ext)
1444    echo "$PREFIX/bin/$1$EXE"
1445}
1446
1447# Return the name of a given host executable
1448# $1: executable base name
1449# Out: executable name, with optional suffix (e.g. .exe for windows)
1450get_host_exec_name ()
1451{
1452    local EXE=$(get_prebuilt_host_exe_ext)
1453    echo "$1$EXE"
1454}
1455
1456# Return the directory where host-specific binaries are installed.
1457# $1: target root NDK directory
1458get_host_install ()
1459{
1460    echo "$1/$(get_prebuilt_install_prefix)"
1461}
1462
1463# Set the toolchain target NDK location.
1464# this sets TOOLCHAIN_PATH and TOOLCHAIN_PREFIX
1465# $1: target NDK path
1466# $2: toolchain name
1467set_toolchain_ndk ()
1468{
1469    TOOLCHAIN_PATH=`get_toolchain_install "$1" $2`
1470    log "Using toolchain path: $TOOLCHAIN_PATH"
1471
1472    TOOLCHAIN_PREFIX=$TOOLCHAIN_PATH/bin/$ABI_CONFIGURE_TARGET
1473    log "Using toolchain prefix: $TOOLCHAIN_PREFIX"
1474}
1475
1476# Check that a toolchain is properly installed at a target NDK location
1477#
1478# $1: target root NDK directory
1479# $2: toolchain name
1480#
1481check_toolchain_install ()
1482{
1483    TOOLCHAIN_PATH=`get_toolchain_install "$1" $2`
1484    if [ ! -d "$TOOLCHAIN_PATH" ] ; then
1485        echo "ERROR: Cannot find directory '$TOOLCHAIN_PATH'!"
1486        echo "       Toolchain '$2' not installed in '$NDK_DIR'!"
1487        echo "       Ensure that the toolchain has been installed there before."
1488        exit 1
1489    fi
1490
1491    set_toolchain_ndk $1 $2
1492}
1493
1494# $1: toolchain source directory
1495check_toolchain_src_dir ()
1496{
1497    local SRC_DIR="$1"
1498    if [ -z "$SRC_DIR" ]; then
1499        echo "ERROR: Please provide the path to the toolchain source tree. See --help"
1500        exit 1
1501    fi
1502
1503    if [ ! -d "$SRC_DIR" ]; then
1504        echo "ERROR: Not a directory: '$SRC_DIR'"
1505        exit 1
1506    fi
1507
1508    if [ ! -f "$SRC_DIR/build/configure" -o ! -d "$SRC_DIR/gcc" ]; then
1509        echo "ERROR: Either the file $SRC_DIR/build/configure or"
1510        echo "       the directory $SRC_DIR/gcc does not exist."
1511        echo "This is not the top of a toolchain tree: $SRC_DIR"
1512        exit 1
1513    fi
1514}
1515
1516make_repo_prop () {
1517    local OUT_PATH="$1/repo.prop"
1518
1519    # The build server generates a repo.prop file that contains the current SHAs
1520    # of each project.
1521    if [ -f $DIST_DIR/repo.prop ]; then
1522        cp $DIST_DIR/repo.prop $OUT_PATH
1523    else
1524        # Generate our own if we're building locally.
1525        pushd $ANDROID_NDK_ROOT
1526        repo forall \
1527            -c 'echo $REPO_PROJECT $(git rev-parse HEAD)' > $OUT_PATH
1528        popd
1529    fi
1530}
1531
1532#
1533# The NDK_TMPDIR variable is used to specify a root temporary directory
1534# when invoking toolchain build scripts. If it is not defined, we will
1535# create one here, and export the value to ensure that any scripts we
1536# call after that use the same one.
1537#
1538if [ -z "$NDK_TMPDIR" ]; then
1539    NDK_TMPDIR=$TMPDIR/tmp/build-$$
1540    mkdir -p $NDK_TMPDIR
1541    if [ $? != 0 ]; then
1542        echo "ERROR: Could not create NDK_TMPDIR: $NDK_TMPDIR"
1543        exit 1
1544    fi
1545    export NDK_TMPDIR
1546fi
1547
1548# Define HOST_TAG32, as the 32-bit version of HOST_TAG
1549# We do this by replacing an -x86_64 suffix by -x86
1550HOST_TAG32=$HOST_TAG
1551case $HOST_TAG32 in
1552    *-x86_64)
1553        HOST_TAG32=${HOST_TAG%%_64}
1554        ;;
1555esac
1556