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