prebuilt-common.sh revision 721e3f4f6b6d6ee2f03c37c687a6ab987d7e03f7
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# 17max_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>` 24dashes_to_underscores () 25{ 26 echo $@ | tr '-' '_' 27} 28 29# Translate underscores to dashes 30# Usage: str=`underscores_to_dashes <values>` 31underscores_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 54OPTIONS="" 55OPTION_FLAGS="" 56OPTION_SETTINGS="" 57 58# Set a given option attribute 59# $1: option name 60# $2: option attribute 61# $3: attribute value 62# 63option_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# 72option_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# 82register_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# 148register_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# 163register_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 171MINGW=no 172do_mingw_option () { MINGW=yes; } 173 174register_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 181TRY64=no 182do_try64_option () { TRY64=yes; } 183 184register_try64_option () 185{ 186 register_option "--try-64" do_try64_option "Generate 64-bit binaries." 187} 188 189# Print the help, including a list of registered options for this program 190# Note: Assumes PROGRAM_PARAMETERS and PROGRAM_DESCRIPTION exist and 191# correspond to the parameters list and the program description 192# 193print_help () 194{ 195 local opt text abstract default 196 197 echo "Usage: $PROGNAME [options] $PROGRAM_PARAMETERS" 198 echo "" 199 if [ -n "$PROGRAM_DESCRIPTION" ] ; then 200 echo "$PROGRAM_DESCRIPTION" 201 echo "" 202 fi 203 echo "Valid options (defaults are in brackets):" 204 echo "" 205 206 maxw=`max_length "$OPTIONS_TEXT"` 207 AWK_SCRIPT=`echo "{ printf \"%-${maxw}s\", \\$1 }"` 208 for opt in $OPTIONS; do 209 text=`option_get_attr $opt text | awk "$AWK_SCRIPT"` 210 abstract=`option_get_attr $opt abstract` 211 default=`option_get_attr $opt default` 212 if [ -n "$default" ] ; then 213 echo " $text $abstract [$default]" 214 else 215 echo " $text $abstract" 216 fi 217 done 218 echo "" 219} 220 221option_panic_no_args () 222{ 223 echo "ERROR: Option '$1' does not take arguments. See --help for usage." 224 exit 1 225} 226 227option_panic_missing_arg () 228{ 229 echo "ERROR: Option '$1' requires an argument. See --help for usage." 230 exit 1 231} 232 233extract_parameters () 234{ 235 local opt optname otype value name fin funcname 236 PARAMETERS="" 237 while [ -n "$1" ] ; do 238 # If the parameter does not begin with a dash 239 # it is not an option. 240 param=`expr -- "$1" : '^\([^\-].*\)$'` 241 if [ -n "$param" ] ; then 242 if [ -z "$PARAMETERS" ] ; then 243 PARAMETERS="$1" 244 else 245 PARAMETERS="$PARAMETERS $1" 246 fi 247 shift 248 continue 249 fi 250 251 while [ -n "1" ] ; do 252 # Try to match a long setting, i.e. --option=value 253 opt=`expr -- "$1" : '^\(--[^=]*\)=.*$'` 254 if [ -n "$opt" ] ; then 255 otype="long_setting" 256 value=`expr -- "$1" : '^--[^=]*=\(.*\)$'` 257 break 258 fi 259 260 # Try to match a long flag, i.e. --option 261 opt=`expr -- "$1" : '^\(--.*\)$'` 262 if [ -n "$opt" ] ; then 263 otype="long_flag" 264 value="yes" 265 break 266 fi 267 268 # Try to match a short setting, i.e. -o<value> 269 opt=`expr -- "$1" : '^\(-[A-Za-z0-9]\)..*$'` 270 if [ -n "$opt" ] ; then 271 otype="short_setting" 272 value=`expr -- "$1" : '^-.\(.*\)$'` 273 break 274 fi 275 276 # Try to match a short flag, i.e. -o 277 opt=`expr -- "$1" : '^\(-.\)$'` 278 if [ -n "$opt" ] ; then 279 otype="short_flag" 280 value="yes" 281 break 282 fi 283 284 echo "ERROR: Unknown option '$1'. Use --help for list of valid values." 285 exit 1 286 done 287 288 #echo "Found opt='$opt' otype='$otype' value='$value'" 289 290 name=`dashes_to_underscores $opt` 291 found=0 292 for xopt in $OPTIONS; do 293 if [ "$name" != "$xopt" ] ; then 294 continue 295 fi 296 # Check that the type is correct here 297 # 298 # This also allows us to handle -o <value> as -o<value> 299 # 300 xotype=`option_get_attr $name otype` 301 if [ "$otype" != "$xotype" ] ; then 302 case "$xotype" in 303 "short_flag") 304 option_panic_no_args $opt 305 ;; 306 "short_setting") 307 if [ -z "$2" ] ; then 308 option_panic_missing_arg $opt 309 fi 310 value="$2" 311 shift 312 ;; 313 "long_flag") 314 option_panic_no_args $opt 315 ;; 316 "long_setting") 317 option_panic_missing_arg $opt 318 ;; 319 esac 320 fi 321 found=1 322 break 323 break 324 done 325 if [ "$found" = "0" ] ; then 326 echo "ERROR: Unknown option '$opt'. See --help for usage." 327 exit 1 328 fi 329 # Set variable or launch option-specific function. 330 varname=`option_get_attr $name varname` 331 if [ -n "$varname" ] ; then 332 eval ${varname}=\"$value\" 333 else 334 eval `option_get_attr $name funcname` \"$value\" 335 fi 336 shift 337 done 338} 339 340do_option_help () 341{ 342 print_help 343 exit 0 344} 345 346VERBOSE=no 347VERBOSE2=no 348do_option_verbose () 349{ 350 if [ $VERBOSE = "yes" ] ; then 351 VERBOSE2=yes 352 else 353 VERBOSE=yes 354 fi 355} 356 357register_option "--help" do_option_help "Print this help." 358register_option "--verbose" do_option_verbose "Enable verbose mode." 359 360#==================================================== 361# 362# TOOLCHAIN AND ABI PROCESSING 363# 364#==================================================== 365 366# Determine optional variable value 367# $1: final variable name 368# $2: option variable name 369# $3: small description for the option 370fix_option () 371{ 372 if [ -n "$2" ] ; then 373 eval $1="$2" 374 log "Using specific $3: $2" 375 else 376 log "Using default $3: `var_value $1`" 377 fi 378} 379 380 381# If SYSROOT is empty, check that $1/$2 contains a sysroot 382# and set the variable to it. 383# 384# $1: sysroot path 385# $2: platform/arch suffix 386check_sysroot () 387{ 388 if [ -z "$SYSROOT" ] ; then 389 log "Probing directory for sysroot: $1/$2" 390 if [ -d $1/$2 ] ; then 391 SYSROOT=$1/$2 392 fi 393 fi 394} 395 396# Determine sysroot 397# $1: Option value (or empty) 398# 399fix_sysroot () 400{ 401 if [ -n "$1" ] ; then 402 eval SYSROOT="$1" 403 log "Using specified sysroot: $1" 404 else 405 SYSROOT_SUFFIX=$PLATFORM/arch-$ARCH 406 SYSROOT= 407 check_sysroot $NDK_DIR/platforms $SYSROOT_SUFFIX 408 check_sysroot $ANDROID_NDK_ROOT/platforms $SYSROOT_SUFFIX 409 check_sysroot `dirname $ANDROID_NDK_ROOT`/development/ndk/platforms $SYSROOT_SUFFIX 410 411 if [ -z "$SYSROOT" ] ; then 412 echo "ERROR: Could not find NDK sysroot path for $SYSROOT_SUFFIX." 413 echo " Use --sysroot=<path> to specify one." 414 exit 1 415 fi 416 fi 417 418 if [ ! -f $SYSROOT/usr/include/stdlib.h ] ; then 419 echo "ERROR: Invalid sysroot path: $SYSROOT" 420 echo " Use --sysroot=<path> to indicate a valid one." 421 exit 1 422 fi 423} 424 425# Use the check for the availability of a compatibility SDK in Darwin 426# this can be used to generate binaries compatible with either Tiger or 427# Leopard. 428# 429# $1: SDK root path 430# $2: MacOS X minimum version (e.g. 10.4) 431check_darwin_sdk () 432{ 433 if [ -d "$1" ] ; then 434 HOST_CFLAGS="-isysroot $1 -mmacosx-version-min=$2 -DMAXOSX_DEPLOYEMENT_TARGET=$2" 435 HOST_LDFLAGS="-Wl,-syslibroot,$sdk -mmacosx-version-min=$2" 436 return 0 # success 437 fi 438 return 1 439} 440 441 442prepare_host_flags () 443{ 444 # detect build tag 445 case $HOST_TAG in 446 linux-x86) 447 ABI_CONFIGURE_BUILD=i386-linux-gnu 448 ;; 449 linux-x86_64) 450 ABI_CONFIGURE_BUILD=x86_64-linux-gnu 451 ;; 452 darwin-x86) 453 ABI_CONFIGURE_BUILD=i686-apple-darwin 454 ;; 455 darwin-x86_64) 456 ABI_CONFIGURE_BUILD=x86_64-apple-darwin 457 ;; 458 windows) 459 ABI_CONFIGURE_BUILD=i686-pc-cygwin 460 ;; 461 *) 462 echo "ERROR: Unsupported HOST_TAG: $HOST_TAG" 463 echo "Please update 'prepare_host_flags' in build/tools/prebuilt-common.sh" 464 ;; 465 esac 466 467 # By default, assume host == build 468 ABI_CONFIGURE_HOST="$ABI_CONFIGURE_BUILD" 469 470 # On Linux, detect our legacy-compatible toolchain when in the Android 471 # source tree, and use it to force the generation of glibc-2.7 compatible 472 # binaries. 473 # 474 # We only do this if the CC variable is not defined to a given value 475 # and the --mingw or --try-64 options are not used. 476 # 477 if [ "$HOST_OS" = "linux" -a -z "$CC" -a "$MINGW" != "yes" -a "$TRY64" != "yes" ]; then 478 LEGACY_TOOLCHAIN_DIR="$ANDROID_NDK_ROOT/../prebuilt/linux-x86/toolchain/i686-linux-glibc2.7-4.4.3" 479 if [ -d "$LEGACY_TOOLCHAIN_DIR" ] ; then 480 dump "Forcing generation of Linux binaries with legacy toolchain" 481 CC="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-gcc" 482 CXX="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-g++" 483 fi 484 fi 485 486 # Force generation of 32-bit binaries on 64-bit systems 487 CC=${CC:-gcc} 488 CXX=${CXX:-g++} 489 case $HOST_TAG in 490 darwin-*) 491 # Try to build with Tiger SDK if available 492 if check_darwin_sdk /Developer/SDKs/MacOSX10.4.sdku 10.4; then 493 log "Generating Tiger-compatible binaries!" 494 # Otherwise with Leopard SDK 495 elif check_darwin_sdk /Developer/SDKs/MacOSX10.5.sdk 10.5; then 496 log "Generating Leopard-compatible binaries!" 497 else 498 local version=`sw_vers -productVersion` 499 log "Generating $version-compatible binaries!" 500 fi 501 ;; 502 esac 503 504 # Force generation of 32-bit binaries on 64-bit systems. 505 # We used to test the value of $HOST_TAG for *-x86_64, but this is 506 # not sufficient on certain systems. 507 # 508 # For example, Snow Leopard can be booted with a 32-bit kernel, running 509 # a 64-bit userland, with a compiler that generates 64-bit binaries by 510 # default *even* though "gcc -v" will report --target=i686-apple-darwin10! 511 # 512 # So know, simply probe for the size of void* by performing a small runtime 513 # compilation test. 514 # 515 cat > $TMPC <<EOF 516 /* this test should fail if the compiler generates 64-bit machine code */ 517 int test_array[1-2*(sizeof(void*) != 4)]; 518EOF 519 echo -n "Checking whether the compiler generates 32-bit binaries..." 520 HOST_GMP_ABI=32 521 log $CC $HOST_CFLAGS -c -o $TMPO $TMPC 522 $CC $HOST_CFLAGS -c -o $TMPO $TMPC >$TMPL 2>&1 523 if [ $? != 0 ] ; then 524 echo "no" 525 if [ "$TRY64" != "yes" ]; then 526 # NOTE: We need to modify the definitions of CC and CXX directly 527 # here. Just changing the value of CFLAGS / HOST_CFLAGS 528 # will not work well with the GCC toolchain scripts. 529 CC="$CC -m32" 530 CXX="$CXX -m32" 531 else 532 HOST_GMP_ABI=64 533 fi 534 else 535 echo "yes" 536 fi 537 538 # For now, we only support building 32-bit binaries anyway 539 if [ "$TRY64" != "yes" ]; then 540 force_32bit_binaries # to modify HOST_TAG and others 541 HOST_GMP_ABI="32" 542 fi 543 544 # Now handle the --mingw flag 545 if [ "$MINGW" = "yes" ] ; then 546 case $HOST_TAG in 547 linux-*) 548 ;; 549 *) 550 echo "ERROR: Can only enable mingw on Linux platforms !" 551 exit 1 552 ;; 553 esac 554 if [ "$TRY64" = "yes" ]; then 555 ABI_CONFIGURE_HOST=amd64-mingw32msvc 556 else 557 ABI_CONFIGURE_HOST=i586-mingw32msvc 558 fi 559 HOST_OS=windows 560 HOST_TAG=windows 561 HOST_EXE=.exe 562 # It turns out that we need to undefine this to be able to 563 # perform a canadian-cross build with mingw. Otherwise, the 564 # GMP configure scripts will not be called with the right options 565 HOST_GMP_ABI= 566 fi 567} 568 569parse_toolchain_name () 570{ 571 if [ -z "$TOOLCHAIN" ] ; then 572 echo "ERROR: Missing toolchain name!" 573 exit 1 574 fi 575 576 ABI_CFLAGS_FOR_TARGET= 577 ABI_CXXFLAGS_FOR_TARGET= 578 579 # Determine ABI based on toolchain name 580 # 581 case "$TOOLCHAIN" in 582 arm-eabi-*) 583 ARCH="arm" 584 ABI_CONFIGURE_TARGET="arm-eabi" 585 ;; 586 arm-linux-androideabi-*) 587 ARCH="arm" 588 ABI_CONFIGURE_TARGET="arm-linux-androideabi" 589 ABI_CONFIGURE_EXTRA_FLAGS="--with-gmp-version=4.2.4 --with-mpfr-version=2.4.1 590--with-arch=armv5te" 591 # Disable ARM Gold linker for now, it doesn't build on Windows, it 592 # crashes with SIGBUS on Darwin, and produces weird executables on 593 # linux that strip complains about... Sigh. 594 #ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --enable-gold=both/gold" 595 596 # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time 597 # You can't really build these separately at the moment. 598 ABI_CFLAGS_FOR_TARGET="-fexceptions" 599 ABI_CXXFLAGS_FOR_TARGET="-frtti" 600 ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --enable-libstdc__-v3" 601 # Stick to 6.6 for now. 7.1.x doesn't seem to work right now. 602 #GDB_VERSION=7.1.x 603 ;; 604 x86-*) 605 ARCH="x86" 606 ABI_INSTALL_NAME="x86" 607 ABI_CONFIGURE_TARGET="i686-android-linux" 608 ABI_CONFIGURE_EXTRA_FLAGS="--with-gmp-version=4.2.4 --with-mpfr-version=2.4.1" 609 # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time 610 # You can't really build these separately at the moment. 611 ABI_CFLAGS_FOR_TARGET="-fexceptions" 612 ABI_CXXFLAGS_FOR_TARGET="-frtti" 613 ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --enable-libstdc__-v3" 614 ;; 615 * ) 616 echo "Invalid toolchain specified. Expected (arm-eabi-*|x86-*)" 617 echo "" 618 print_help 619 exit 1 620 ;; 621 esac 622 623 log "Targetting CPU: $ARCH" 624 625 GCC_VERSION=`expr -- "$TOOLCHAIN" : '.*-\([0-9x\.]*\)'` 626 log "Using GCC version: $GCC_VERSION" 627 628 # Determine --host value when building gdbserver 629 case "$TOOLCHAIN" in 630 arm-*) 631 GDBSERVER_HOST=arm-eabi-linux 632 GDBSERVER_CFLAGS="-fno-short-enums" 633 ;; 634 x86-*) 635 GDBSERVER_HOST=i686-android-linux-gnu 636 GDBSERVER_CFLAGS= 637 ;; 638 esac 639 640} 641 642# Return the host/build specific path for prebuilt toolchain binaries 643# relative to $1. 644# 645# $1: target root NDK directory 646# 647get_toolchain_install () 648{ 649 echo "$1/toolchains/$TOOLCHAIN/prebuilt/$HOST_TAG" 650} 651 652 653# Set the toolchain target NDK location. 654# this sets TOOLCHAIN_PATH and TOOLCHAIN_PREFIX 655# $1: target NDK path 656set_toolchain_ndk () 657{ 658 TOOLCHAIN_PATH=`get_toolchain_install $1` 659 log "Using toolchain path: $TOOLCHAIN_PATH" 660 661 TOOLCHAIN_PREFIX=$TOOLCHAIN_PATH/bin/$ABI_CONFIGURE_TARGET 662 log "Using toolchain prefix: $TOOLCHAIN_PREFIX" 663} 664 665# Check that a toolchain is properly installed at a target NDK location 666# 667# $1: target root NDK directory 668# 669check_toolchain_install () 670{ 671 TOOLCHAIN_PATH=`get_toolchain_install $1` 672 if [ ! -d "$TOOLCHAIN_PATH" ] ; then 673 echo "ERROR: Toolchain '$TOOLCHAIN' not installed in '$NDK_DIR'!" 674 echo " Ensure that the toolchain has been installed there before." 675 exit 1 676 fi 677 678 set_toolchain_ndk $1 679} 680 681 682random_temp_directory () 683{ 684 mkdir -p /tmp/ndk-toolchain 685 mktemp -d /tmp/ndk-toolchain/build-XXXXXX 686} 687 688# 689# Common definitions 690# 691 692# Current list of platform levels we support 693# 694# Note: levels 6 and 7 are omitted since they have the same native 695# APIs as level 5. 696# 697API_LEVELS="3 4 5 8 9" 698 699# Location of the STLport sources, relative to the NDK root directory 700STLPORT_SUBDIR=sources/cxx-stl/stlport 701 702# Default ABIs for the prebuilt STLport binaries 703STLPORT_ABIS="armeabi armeabi-v7a" 704 705# Location of the GNU libstdc++ headers and libraries, relative to the NDK 706# root directory. 707GNUSTL_SUBDIR=sources/cxx-stl/gnu-libstdc++ 708 709# The date to use when downloading toolchain sources from android.git.kernel.org 710# Leave it empty for tip of tree. 711TOOLCHAIN_GIT_DATE=2011-02-23 712