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