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 . `dirname $0`/../core/ndk-common.sh
      6 
      7 #====================================================
      8 #
      9 #  UTILITY FUNCTIONS
     10 #
     11 #====================================================
     12 
     13 # Return the maximum length of a series of strings
     14 #
     15 # Usage:  len=`max_length <string1> <string2> ...`
     16 #
     17 max_length ()
     18 {
     19     echo "$@" | tr ' ' '\n' | awk 'BEGIN {max=0} {len=length($1); if (len > max) max=len} END {print max}'
     20 }
     21 
     22 # Translate dashes to underscores
     23 # Usage:  str=`dashes_to_underscores <values>`
     24 dashes_to_underscores ()
     25 {
     26     echo $@ | tr '-' '_'
     27 }
     28 
     29 # Translate underscores to dashes
     30 # Usage: str=`underscores_to_dashes <values>`
     31 underscores_to_dashes ()
     32 {
     33     echo $@ | tr '_' '-'
     34 }
     35 
     36 #====================================================
     37 #
     38 #  OPTION PROCESSING
     39 #
     40 #====================================================
     41 
     42 # We recognize the following option formats:
     43 #
     44 #  -f
     45 #  --flag
     46 #
     47 #  -s<value>
     48 #  --setting=<value>
     49 #
     50 
     51 # NOTE: We translate '-' into '_' when storing the options in global variables
     52 #
     53 
     54 OPTIONS=""
     55 OPTION_FLAGS=""
     56 OPTION_SETTINGS=""
     57 
     58 # Set a given option attribute
     59 # $1: option name
     60 # $2: option attribute
     61 # $3: attribute value
     62 #
     63 option_set_attr ()
     64 {
     65     eval OPTIONS_$1_$2=\"$3\"
     66 }
     67 
     68 # Get a given option attribute
     69 # $1: option name
     70 # $2: option attribute
     71 #
     72 option_get_attr ()
     73 {
     74     echo `var_value OPTIONS_$1_$2`
     75 }
     76 
     77 # Register a new option
     78 # $1: option
     79 # $2: small abstract for the option
     80 # $3: optional. default value
     81 #
     82 register_option_internal ()
     83 {
     84     optlabel=
     85     optname=
     86     optvalue=
     87     opttype=
     88     while [ -n "1" ] ; do
     89         # Check for something like --setting=<value>
     90         echo "$1" | grep -q -E -e '^--[^=]+=<.+>$'
     91         if [ $? = 0 ] ; then
     92             optlabel=`expr -- "$1" : '\(--[^=]*\)=.*'`
     93             optvalue=`expr -- "$1" : '--[^=]*=\(<.*>\)'`
     94             opttype="long_setting"
     95             break
     96         fi
     97 
     98         # Check for something like --flag
     99         echo "$1" | grep -q -E -e '^--[^=]+$'
    100         if [ $? = 0 ] ; then
    101             optlabel="$1"
    102             opttype="long_flag"
    103             break
    104         fi
    105 
    106         # Check for something like -f<value>
    107         echo "$1" | grep -q -E -e '^-[A-Za-z0-9]<.+>$'
    108         if [ $? = 0 ] ; then
    109             optlabel=`expr -- "$1" : '\(-.\).*'`
    110             optvalue=`expr -- "$1" : '-.\(<.+>\)'`
    111             opttype="short_setting"
    112             break
    113         fi
    114 
    115         # Check for something like -f
    116         echo "$1" | grep -q -E -e '^-.$'
    117         if [ $? = 0 ] ; then
    118             optlabel="$1"
    119             opttype="short_flag"
    120             break
    121         fi
    122 
    123         echo "ERROR: Invalid option format: $1"
    124         echo "       Check register_option call"
    125         exit 1
    126     done
    127 
    128     log "new option: type='$opttype' name='$optlabel' value='$optvalue'"
    129 
    130     optname=`dashes_to_underscores $optlabel`
    131     OPTIONS="$OPTIONS $optname"
    132     OPTIONS_TEXT="$OPTIONS_TEXT $1"
    133     option_set_attr $optname label "$optlabel"
    134     option_set_attr $optname otype "$opttype"
    135     option_set_attr $optname value "$optvalue"
    136     option_set_attr $optname text "$1"
    137     option_set_attr $optname abstract "$2"
    138     option_set_attr $optname default "$3"
    139 }
    140 
    141 # Register a new option with a function callback.
    142 #
    143 # $1: option
    144 # $2: name of function that will be called when the option is parsed
    145 # $3: small abstract for the option
    146 # $4: optional. default value
    147 #
    148 register_option ()
    149 {
    150     local optname optvalue opttype optlabel
    151     register_option_internal "$1" "$3" "$4"
    152     option_set_attr $optname funcname "$2"
    153 }
    154 
    155 # Register a new option with a variable store
    156 #
    157 # $1: option
    158 # $2: name of variable that will be set by this option
    159 # $3: small abstract for the option
    160 #
    161 # NOTE: The current value of $2 is used as the default
    162 #
    163 register_var_option ()
    164 {
    165     local optname optvalue opttype optlabel
    166     register_option_internal "$1" "$3" "`var_value $2`"
    167     option_set_attr $optname varname "$2"
    168 }
    169 
    170 
    171 MINGW=no
    172 do_mingw_option () { MINGW=yes; }
    173 
    174 register_mingw_option ()
    175 {
    176     if [ "$HOST_OS" = "linux" ] ; then
    177         register_option "--mingw" do_mingw_option "Generate windows binaries on Linux."
    178     fi
    179 }
    180 
    181 # Print the help, including a list of registered options for this program
    182 # Note: Assumes PROGRAM_PARAMETERS and PROGRAM_DESCRIPTION exist and
    183 #       correspond to the parameters list and the program description
    184 #
    185 print_help ()
    186 {
    187     local opt text abstract default
    188 
    189     echo "Usage: $PROGNAME [options] $PROGRAM_PARAMETERS"
    190     echo ""
    191     if [ -n "$PROGRAM_DESCRIPTION" ] ; then
    192         echo "$PROGRAM_DESCRIPTION"
    193         echo ""
    194     fi
    195     echo "Valid options (defaults are in brackets):"
    196     echo ""
    197 
    198     maxw=`max_length "$OPTIONS_TEXT"`
    199     AWK_SCRIPT=`echo "{ printf \"%-${maxw}s\", \\$1 }"`
    200     for opt in $OPTIONS; do
    201         text=`option_get_attr $opt text | awk "$AWK_SCRIPT"`
    202         abstract=`option_get_attr $opt abstract`
    203         default=`option_get_attr $opt default`
    204         if [ -n "$default" ] ; then
    205             echo "  $text     $abstract [$default]"
    206         else
    207             echo "  $text     $abstract"
    208         fi
    209     done
    210     echo ""
    211 }
    212 
    213 option_panic_no_args ()
    214 {
    215     echo "ERROR: Option '$1' does not take arguments. See --help for usage."
    216     exit 1
    217 }
    218 
    219 option_panic_missing_arg ()
    220 {
    221     echo "ERROR: Option '$1' requires an argument. See --help for usage."
    222     exit 1
    223 }
    224 
    225 extract_parameters ()
    226 {
    227     local opt optname otype value name fin funcname
    228     PARAMETERS=""
    229     while [ -n "$1" ] ; do
    230         # If the parameter does not begin with a dash
    231         # it is not an option.
    232         param=`expr -- "$1" : '^\([^\-].*\)$'`
    233         if [ -n "$param" ] ; then
    234             if [ -z "$PARAMETERS" ] ; then
    235                 PARAMETERS="$1"
    236             else
    237                 PARAMETERS="$PARAMETERS $1"
    238             fi
    239             shift
    240             continue
    241         fi
    242 
    243         while [ -n "1" ] ; do
    244             # Try to match a long setting, i.e. --option=value
    245             opt=`expr -- "$1" : '^\(--[^=]*\)=.*$'`
    246             if [ -n "$opt" ] ; then
    247                 otype="long_setting"
    248                 value=`expr -- "$1" : '^--[^=]*=\(.*\)$'`
    249                 break
    250             fi
    251 
    252             # Try to match a long flag, i.e. --option
    253             opt=`expr -- "$1" : '^\(--.*\)$'`
    254             if [ -n "$opt" ] ; then
    255                 otype="long_flag"
    256                 value="yes"
    257                 break
    258             fi
    259 
    260             # Try to match a short setting, i.e. -o<value>
    261             opt=`expr -- "$1" : '^\(-[A-Za-z0-9]\)..*$'`
    262             if [ -n "$opt" ] ; then
    263                 otype="short_setting"
    264                 value=`expr -- "$1" : '^-.\(.*\)$'`
    265                 break
    266             fi
    267 
    268             # Try to match a short flag, i.e. -o
    269             opt=`expr -- "$1" : '^\(-.\)$'`
    270             if [ -n "$opt" ] ; then
    271                 otype="short_flag"
    272                 value="yes"
    273                 break
    274             fi
    275 
    276             echo "ERROR: Unknown option '$1'. Use --help for list of valid values."
    277             exit 1
    278         done
    279 
    280         #echo "Found opt='$opt' otype='$otype' value='$value'"
    281 
    282         name=`dashes_to_underscores $opt`
    283         found=0
    284         for xopt in $OPTIONS; do
    285             if [ "$name" != "$xopt" ] ; then
    286                 continue
    287             fi
    288             # Check that the type is correct here
    289             #
    290             # This also allows us to handle -o <value> as -o<value>
    291             #
    292             xotype=`option_get_attr $name otype`
    293             if [ "$otype" != "$xotype" ] ; then
    294                 case "$xotype" in
    295                 "short_flag")
    296                     option_panic_no_args $opt
    297                     ;;
    298                 "short_setting")
    299                     if [ -z "$2" ] ; then
    300                         option_panic_missing_arg $opt
    301                     fi
    302                     value="$2"
    303                     shift
    304                     ;;
    305                 "long_flag")
    306                     option_panic_no_args $opt
    307                     ;;
    308                 "long_setting")
    309                     option_panic_missing_arg $opt
    310                     ;;
    311                 esac
    312             fi
    313             found=1
    314             break
    315             break
    316         done
    317         if [ "$found" = "0" ] ; then
    318             echo "ERROR: Unknown option '$opt'. See --help for usage."
    319             exit 1
    320         fi
    321         # Set variable or launch option-specific function.
    322         varname=`option_get_attr $name varname`
    323         if [ -n "$varname" ] ; then
    324             eval ${varname}=\"$value\"
    325         else
    326             eval `option_get_attr $name funcname` \"$value\"
    327         fi
    328         shift
    329     done
    330 }
    331 
    332 do_option_help ()
    333 {
    334     print_help
    335     exit 0
    336 }
    337 
    338 VERBOSE=no
    339 VERBOSE2=no
    340 do_option_verbose ()
    341 {
    342     if [ $VERBOSE = "yes" ] ; then
    343         VERBOSE2=yes
    344     else
    345         VERBOSE=yes
    346     fi
    347 }
    348 
    349 register_option "--help"          do_option_help     "Print this help."
    350 register_option "--verbose"       do_option_verbose  "Enable verbose mode."
    351 
    352 #====================================================
    353 #
    354 #  TOOLCHAIN AND ABI PROCESSING
    355 #
    356 #====================================================
    357 
    358 # Determine optional variable value
    359 # $1: final variable name
    360 # $2: option variable name
    361 # $3: small description for the option
    362 fix_option ()
    363 {
    364     if [ -n "$2" ] ; then
    365         eval $1="$2"
    366         log "Using specific $3: $2"
    367     else
    368         log "Using default $3: `var_value $1`"
    369     fi
    370 }
    371 
    372 
    373 # If SYSROOT is empty, check that $1/$2 contains a sysroot
    374 # and set the variable to it.
    375 #
    376 # $1: sysroot path
    377 # $2: platform/arch suffix
    378 check_sysroot ()
    379 {
    380     if [ -z "$SYSROOT" ] ; then
    381         log "Probing directory for sysroot: $1/$2"
    382         if [ -d $1/$2 ] ; then
    383             SYSROOT=$1/$2
    384         fi
    385     fi
    386 }
    387 
    388 # Determine sysroot
    389 # $1: Option value (or empty)
    390 #
    391 fix_sysroot ()
    392 {
    393     if [ -n "$1" ] ; then
    394         eval SYSROOT="$1"
    395         log "Using specified sysroot: $1"
    396     else
    397         SYSROOT_SUFFIX=$PLATFORM/arch-$ARCH
    398         SYSROOT=
    399         check_sysroot $NDK_DIR/platforms $SYSROOT_SUFFIX
    400         check_sysroot $ANDROID_NDK_ROOT/platforms $SYSROOT_SUFFIX
    401         check_sysroot `dirname $ANDROID_NDK_ROOT`/development/ndk/platforms $SYSROOT_SUFFIX
    402 
    403         if [ -z "$SYSROOT" ] ; then
    404             echo "ERROR: Could not find NDK sysroot path for $SYSROOT_SUFFIX."
    405             echo "       Use --sysroot=<path> to specify one."
    406             exit 1
    407         fi
    408     fi
    409 
    410     if [ ! -f $SYSROOT/usr/include/stdlib.h ] ; then
    411         echo "ERROR: Invalid sysroot path: $SYSROOT"
    412         echo "       Use --sysroot=<path> to indicate a valid one."
    413         exit 1
    414     fi
    415 }
    416 
    417 prepare_host_flags ()
    418 {
    419     # detect build tag
    420     case $HOST_TAG in
    421         linux-x86)
    422             ABI_CONFIGURE_BUILD=i386-linux-gnu
    423             ;;
    424         linux-x86_64)
    425             ABI_CONFIGURE_BUILD=x86_64-linux-gnu
    426             ;;
    427         darwin-x86)
    428             ABI_CONFIGURE_BUILD=i686-apple-darwin
    429             ;;
    430         darwin-x86_64)
    431             ABI_CONFIGURE_BUILD=x86_64-apple-darwin
    432             ;;
    433         windows)
    434             ABI_CONFIGURE_BUILD=i686-pc-cygwin
    435             ;;
    436         *)
    437             echo "ERROR: Unsupported HOST_TAG: $HOST_TAG"
    438             echo "Please update 'prepare_host_flags' in build/tools/prebuilt-common.sh"
    439             ;;
    440     esac
    441 
    442     # By default, assume host == build
    443     ABI_CONFIGURE_HOST="$ABI_CONFIGURE_BUILD"
    444 
    445     # Force generation of 32-bit binaries on 64-bit systems
    446     CC=${CC:-gcc}
    447     CXX=${CXX:-g++}
    448     case $HOST_TAG in
    449         *-x86_64)
    450             CC="$CC -m32"
    451             CXX="$CXX -m32"
    452             HOST_GMP_ABI="32"
    453             force_32bit_binaries  # to modify HOST_TAG and others
    454             ;;
    455     esac
    456 
    457     # Now handle the --mingw flag
    458     if [ "$MINGW" = "yes" ] ; then
    459         case $HOST_TAG in
    460             linux-*)
    461                 ;;
    462             *)
    463                 echo "ERROR: Can only enable mingw on Linux platforms !"
    464                 exit 1
    465                 ;;
    466         esac
    467         ABI_CONFIGURE_HOST=i586-mingw32msvc
    468         HOST_OS=windows
    469         HOST_TAG=windows
    470         HOST_GMP_ABI=
    471     fi
    472 }
    473 
    474 parse_toolchain_name ()
    475 {
    476     if [ -z "$TOOLCHAIN" ] ; then
    477         echo "ERROR: Missing toolchain name!"
    478         exit 1
    479     fi
    480 
    481     # Determine ABI based on toolchain name
    482     #
    483     case "$TOOLCHAIN" in
    484     arm-eabi-*)
    485         ARCH="arm"
    486         ABI_CONFIGURE_TARGET="arm-eabi"
    487         ;;
    488     arm-linux-androideabi-*)
    489         ARCH="arm"
    490         ABI_CONFIGURE_TARGET="arm-linux-androideabi"
    491         ABI_CONFIGURE_EXTRA_FLAGS="--with-gmp-version=4.2.4 --with-mpfr-version=2.4.1
    492 --with-arch=armv5te"
    493         # Disabled until Gold is fixed for Cortex-A8 CPU bug
    494         #ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --enable-gold=both/gold"
    495         GDB_VERSION=7.1.x
    496         ;;
    497     x86-*)
    498         ARCH="x86"
    499         ABI_INSTALL_NAME="x86"
    500         ABI_CONFIGURE_TARGET="i686-android-linux-gnu"
    501         PLATFORM=android-5
    502         ;;
    503     * )
    504         echo "Invalid toolchain specified. Expected (arm-eabi-*|x86-*)"
    505         echo ""
    506         print_help
    507         exit 1
    508         ;;
    509     esac
    510 
    511     log "Targetting CPU: $ARCH"
    512 
    513     GCC_VERSION=`expr -- "$TOOLCHAIN" : '.*-\([0-9\.]*\)'`
    514     log "Using GCC version: $GCC_VERSION"
    515 
    516     # Determine --host value when building gdbserver
    517     case "$TOOLCHAIN" in
    518     arm-*)
    519         GDBSERVER_HOST=arm-eabi-linux
    520         GDBSERVER_CFLAGS="-fno-short-enums"
    521         ;;
    522     x86-*)
    523         GDBSERVER_HOST=i686-android-linux-gnu
    524         GDBSERVER_CFLAGS=
    525         ;;
    526     esac
    527 
    528 }
    529 
    530 # Return the host/build specific path for prebuilt toolchain binaries
    531 # relative to $1.
    532 #
    533 # $1: target root NDK directory
    534 #
    535 get_toolchain_install ()
    536 {
    537     echo "$1/toolchains/$TOOLCHAIN/prebuilt/$HOST_TAG"
    538 }
    539 
    540 
    541 # Set the toolchain target NDK location.
    542 # this sets TOOLCHAIN_PATH and TOOLCHAIN_PREFIX
    543 # $1: target NDK path
    544 set_toolchain_ndk ()
    545 {
    546     TOOLCHAIN_PATH=`get_toolchain_install $1`
    547     log "Using toolchain path: $TOOLCHAIN_PATH"
    548 
    549     TOOLCHAIN_PREFIX=$TOOLCHAIN_PATH/bin/$ABI_CONFIGURE_TARGET
    550     log "Using toolchain prefix: $TOOLCHAIN_PREFIX"
    551 }
    552 
    553 # Check that a toolchain is properly installed at a target NDK location
    554 #
    555 # $1: target root NDK directory
    556 #
    557 check_toolchain_install ()
    558 {
    559     TOOLCHAIN_PATH=`get_toolchain_install $1`
    560     if [ ! -d "$TOOLCHAIN_PATH" ] ; then
    561         echo "ERROR: Toolchain '$TOOLCHAIN' not installed in '$NDK_DIR'!"
    562         echo "       Ensure that the toolchain has been installed there before."
    563         exit 1
    564     fi
    565 
    566     set_toolchain_ndk $1
    567 }
    568 
    569 
    570 random_temp_directory ()
    571 {
    572     mkdir -p /tmp/ndk-toolchain
    573     mktemp -d /tmp/ndk-toolchain/build-XXXXXX
    574 }
    575