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 # Warn about /bin/sh ins't bash.
     21 if [ -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."
     23 fi
     24 
     25 NDK_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 #
     45 max_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>`
     52 dashes_to_underscores ()
     53 {
     54     echo "$@" | tr '-' '_'
     55 }
     56 
     57 # Translate underscores to dashes
     58 # Usage: str=`underscores_to_dashes <values>`
     59 underscores_to_dashes ()
     60 {
     61     echo "$@" | tr '_' '-'
     62 }
     63 
     64 # Translate commas to spaces
     65 # Usage: str=`commas_to_spaces <list>`
     66 commas_to_spaces ()
     67 {
     68     echo "$@" | tr ',' ' '
     69 }
     70 
     71 # Translate spaces to commas
     72 # Usage: list=`spaces_to_commas <string>`
     73 spaces_to_commas ()
     74 {
     75     echo "$@" | tr ' ' ','
     76 }
     77 
     78 # Remove trailing path of a path
     79 # $1: path
     80 remove_trailing_slash () {
     81     echo ${1%%/}
     82 }
     83 
     84 # Reverse a file path directory
     85 # foo -> .
     86 # foo/bar -> ..
     87 # foo/bar/zoo -> ../..
     88 reverse_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
    121 sort_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
    131 list_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
    143 filter_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
    157 var_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 
    180 OPTIONS=""
    181 OPTION_FLAGS=""
    182 OPTION_SETTINGS=""
    183 
    184 # Set a given option attribute
    185 # $1: option name
    186 # $2: option attribute
    187 # $3: attribute value
    188 #
    189 option_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 #
    198 option_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 #
    208 register_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 #
    274 register_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 #
    289 register_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 
    297 MINGW=no
    298 DARWIN=no
    299 do_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 }
    307 do_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 
    316 register_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 
    324 TRY64=no
    325 do_try64_option () { TRY64=yes; }
    326 
    327 register_try64_option ()
    328 {
    329     register_option "--try-64" do_try64_option "Generate 64-bit binaries."
    330 }
    331 
    332 
    333 register_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 #
    343 print_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 
    371 option_panic_no_args ()
    372 {
    373     echo "ERROR: Option '$1' does not take arguments. See --help for usage."
    374     exit 1
    375 }
    376 
    377 option_panic_missing_arg ()
    378 {
    379     echo "ERROR: Option '$1' requires an argument. See --help for usage."
    380     exit 1
    381 }
    382 
    383 extract_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 
    490 do_option_help ()
    491 {
    492     print_help
    493     exit 0
    494 }
    495 
    496 VERBOSE=no
    497 VERBOSE2=no
    498 do_option_verbose ()
    499 {
    500     if [ $VERBOSE = "yes" ] ; then
    501         VERBOSE2=yes
    502     else
    503         VERBOSE=yes
    504     fi
    505 }
    506 
    507 register_option "--help"          do_option_help     "Print this help."
    508 register_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
    520 fix_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
    536 check_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 #
    549 fix_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)
    581 DARWIN_MINVER=10.6
    582 check_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 #
    607 probe_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 
    624 handle_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 #
    665 find_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 #
    709 prepare_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
    757 case \$1 in
    758     -productVersion)
    759         echo $DARWIN_MINVER
    760         ;;
    761     *)
    762         echo "ERROR: Unknown switch \$1"
    763         exit 1
    764 esac
    765 EOF
    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 
    812 handle_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 
    821 setup_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 
    844 prepare_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)];
    914 EOF
    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 
    943 prepare_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 
    964 prepare_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 
    990 prepare_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 #
   1017 parse_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
   1153 get_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
   1182 get_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
   1193 find_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
   1234 find_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
   1245 arch_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
   1258 get_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
   1271 convert_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)
   1301 convert_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)
   1330 convert_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
   1353 get_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
   1367 get_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
   1381 get_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
   1391 get_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
   1405 get_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
   1418 get_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?
   1428 get_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 #
   1443 get_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
   1452 get_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
   1464 get_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
   1477 get_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)
   1488 get_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
   1496 get_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
   1505 set_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 #
   1519 check_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
   1533 check_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 #
   1562 if [ -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
   1570 fi
   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
   1574 HOST_TAG32=$HOST_TAG
   1575 case $HOST_TAG32 in
   1576     *-x86_64)
   1577         HOST_TAG32=${HOST_TAG%%_64}
   1578         ;;
   1579 esac
   1580