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