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