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