1# Common functions for all prebuilt-related scripts 2# This is included/sourced by other scripts 3# 4 5# ensure stable sort order 6export 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# 12if [ -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 18fi 19 20NDK_BUILDTOOLS_ABSPATH=$(cd $NDK_BUILDTOOLS_PATH && pwd) 21 22. $NDK_BUILDTOOLS_PATH/../core/ndk-common.sh 23. $NDK_BUILDTOOLS_PATH/dev-defaults.sh 24 25#==================================================== 26# 27# UTILITY FUNCTIONS 28# 29#==================================================== 30 31# Return the maximum length of a series of strings 32# 33# Usage: len=`max_length <string1> <string2> ...` 34# 35max_length () 36{ 37 echo "$@" | tr ' ' '\n' | awk 'BEGIN {max=0} {len=length($1); if (len > max) max=len} END {print max}' 38} 39 40# Translate dashes to underscores 41# Usage: str=`dashes_to_underscores <values>` 42dashes_to_underscores () 43{ 44 echo "$@" | tr '-' '_' 45} 46 47# Translate underscores to dashes 48# Usage: str=`underscores_to_dashes <values>` 49underscores_to_dashes () 50{ 51 echo "$@" | tr '_' '-' 52} 53 54# Translate commas to spaces 55# Usage: str=`commas_to_spaces <list>` 56commas_to_spaces () 57{ 58 echo "$@" | tr ',' ' ' 59} 60 61# Translate spaces to commas 62# Usage: list=`spaces_to_commas <string>` 63spaces_to_commas () 64{ 65 echo "$@" | tr ' ' ',' 66} 67 68# Remove trailing path of a path 69# $1: path 70remove_trailing_slash () { 71 echo ${1%%/} 72} 73 74# Reverse a file path directory 75# foo -> . 76# foo/bar -> .. 77# foo/bar/zoo -> ../.. 78reverse_path () 79{ 80 local path cur item 81 path=${1%%/} # remove trailing slash 82 cur="." 83 if [ "$path" != "." ] ; then 84 for item in $(echo "$path" | tr '/' ' '); do 85 cur="../$cur" 86 done 87 fi 88 echo ${cur%%/.} 89} 90 91# test_reverse_path () 92# { 93# rr=`reverse_path $1` 94# if [ "$rr" != "$2" ] ; then 95# echo "ERROR: reverse_path '$1' -> '$rr' (expected '$2')" 96# fi 97# } 98# 99# test_reverse_path . . 100# test_reverse_path ./ . 101# test_reverse_path foo .. 102# test_reverse_path foo/ .. 103# test_reverse_path foo/bar ../.. 104# test_reverse_path foo/bar/ ../.. 105# test_reverse_path foo/bar/zoo ../../.. 106# test_reverse_path foo/bar/zoo/ ../../.. 107 108# Sort a space-separated list and remove duplicates 109# $1+: slist 110# Output: new slist 111sort_uniq () 112{ 113 local RET 114 RET=$(echo "$@" | tr ' ' '\n' | sort -u) 115 echo $RET 116} 117 118# Return the list of all regular files under a given directory 119# $1: Directory path 120# Output: list of files, relative to $1 121list_files_under () 122{ 123 if [ -d "$1" ]; then 124 (cd $1 && find . -type f | sed -e "s!./!!" | sort -u) 125 else 126 echo "" 127 fi 128} 129 130# Assign a value to a variable 131# $1: Variable name 132# $2: Value 133var_assign () 134{ 135 eval $1=\"$2\" 136} 137 138#==================================================== 139# 140# OPTION PROCESSING 141# 142#==================================================== 143 144# We recognize the following option formats: 145# 146# -f 147# --flag 148# 149# -s<value> 150# --setting=<value> 151# 152 153# NOTE: We translate '-' into '_' when storing the options in global variables 154# 155 156OPTIONS="" 157OPTION_FLAGS="" 158OPTION_SETTINGS="" 159 160# Set a given option attribute 161# $1: option name 162# $2: option attribute 163# $3: attribute value 164# 165option_set_attr () 166{ 167 eval OPTIONS_$1_$2=\"$3\" 168} 169 170# Get a given option attribute 171# $1: option name 172# $2: option attribute 173# 174option_get_attr () 175{ 176 echo `var_value OPTIONS_$1_$2` 177} 178 179# Register a new option 180# $1: option 181# $2: small abstract for the option 182# $3: optional. default value 183# 184register_option_internal () 185{ 186 optlabel= 187 optname= 188 optvalue= 189 opttype= 190 while [ -n "1" ] ; do 191 # Check for something like --setting=<value> 192 echo "$1" | grep -q -E -e '^--[^=]+=<.+>$' 193 if [ $? = 0 ] ; then 194 optlabel=`expr -- "$1" : '\(--[^=]*\)=.*'` 195 optvalue=`expr -- "$1" : '--[^=]*=\(<.*>\)'` 196 opttype="long_setting" 197 break 198 fi 199 200 # Check for something like --flag 201 echo "$1" | grep -q -E -e '^--[^=]+$' 202 if [ $? = 0 ] ; then 203 optlabel="$1" 204 opttype="long_flag" 205 break 206 fi 207 208 # Check for something like -f<value> 209 echo "$1" | grep -q -E -e '^-[A-Za-z0-9]<.+>$' 210 if [ $? = 0 ] ; then 211 optlabel=`expr -- "$1" : '\(-.\).*'` 212 optvalue=`expr -- "$1" : '-.\(<.+>\)'` 213 opttype="short_setting" 214 break 215 fi 216 217 # Check for something like -f 218 echo "$1" | grep -q -E -e '^-.$' 219 if [ $? = 0 ] ; then 220 optlabel="$1" 221 opttype="short_flag" 222 break 223 fi 224 225 echo "ERROR: Invalid option format: $1" 226 echo " Check register_option call" 227 exit 1 228 done 229 230 log "new option: type='$opttype' name='$optlabel' value='$optvalue'" 231 232 optname=`dashes_to_underscores $optlabel` 233 OPTIONS="$OPTIONS $optname" 234 OPTIONS_TEXT="$OPTIONS_TEXT $1" 235 option_set_attr $optname label "$optlabel" 236 option_set_attr $optname otype "$opttype" 237 option_set_attr $optname value "$optvalue" 238 option_set_attr $optname text "$1" 239 option_set_attr $optname abstract "$2" 240 option_set_attr $optname default "$3" 241} 242 243# Register a new option with a function callback. 244# 245# $1: option 246# $2: name of function that will be called when the option is parsed 247# $3: small abstract for the option 248# $4: optional. default value 249# 250register_option () 251{ 252 local optname optvalue opttype optlabel 253 register_option_internal "$1" "$3" "$4" 254 option_set_attr $optname funcname "$2" 255} 256 257# Register a new option with a variable store 258# 259# $1: option 260# $2: name of variable that will be set by this option 261# $3: small abstract for the option 262# 263# NOTE: The current value of $2 is used as the default 264# 265register_var_option () 266{ 267 local optname optvalue opttype optlabel 268 register_option_internal "$1" "$3" "`var_value $2`" 269 option_set_attr $optname varname "$2" 270} 271 272 273MINGW=no 274do_mingw_option () { MINGW=yes; } 275 276register_mingw_option () 277{ 278 if [ "$HOST_OS" = "linux" ] ; then 279 register_option "--mingw" do_mingw_option "Generate windows binaries on Linux." 280 fi 281} 282 283TRY64=no 284do_try64_option () { TRY64=yes; } 285 286register_try64_option () 287{ 288 register_option "--try-64" do_try64_option "Generate 64-bit binaries." 289} 290 291 292register_jobs_option () 293{ 294 NUM_JOBS=$BUILD_NUM_CPUS 295 register_var_option "-j<number>" NUM_JOBS "Use <number> parallel build jobs" 296} 297 298# Print the help, including a list of registered options for this program 299# Note: Assumes PROGRAM_PARAMETERS and PROGRAM_DESCRIPTION exist and 300# correspond to the parameters list and the program description 301# 302print_help () 303{ 304 local opt text abstract default 305 306 echo "Usage: $PROGNAME [options] $PROGRAM_PARAMETERS" 307 echo "" 308 if [ -n "$PROGRAM_DESCRIPTION" ] ; then 309 echo "$PROGRAM_DESCRIPTION" 310 echo "" 311 fi 312 echo "Valid options (defaults are in brackets):" 313 echo "" 314 315 maxw=`max_length "$OPTIONS_TEXT"` 316 AWK_SCRIPT=`echo "{ printf \"%-${maxw}s\", \\$1 }"` 317 for opt in $OPTIONS; do 318 text=`option_get_attr $opt text | awk "$AWK_SCRIPT"` 319 abstract=`option_get_attr $opt abstract` 320 default=`option_get_attr $opt default` 321 if [ -n "$default" ] ; then 322 echo " $text $abstract [$default]" 323 else 324 echo " $text $abstract" 325 fi 326 done 327 echo "" 328} 329 330option_panic_no_args () 331{ 332 echo "ERROR: Option '$1' does not take arguments. See --help for usage." 333 exit 1 334} 335 336option_panic_missing_arg () 337{ 338 echo "ERROR: Option '$1' requires an argument. See --help for usage." 339 exit 1 340} 341 342extract_parameters () 343{ 344 local opt optname otype value name fin funcname 345 PARAMETERS="" 346 while [ -n "$1" ] ; do 347 # If the parameter does not begin with a dash 348 # it is not an option. 349 param=`expr -- "$1" : '^\([^\-].*\)$'` 350 if [ -n "$param" ] ; then 351 if [ -z "$PARAMETERS" ] ; then 352 PARAMETERS="$1" 353 else 354 PARAMETERS="$PARAMETERS $1" 355 fi 356 shift 357 continue 358 fi 359 360 while [ -n "1" ] ; do 361 # Try to match a long setting, i.e. --option=value 362 opt=`expr -- "$1" : '^\(--[^=]*\)=.*$'` 363 if [ -n "$opt" ] ; then 364 otype="long_setting" 365 value=`expr -- "$1" : '^--[^=]*=\(.*\)$'` 366 break 367 fi 368 369 # Try to match a long flag, i.e. --option 370 opt=`expr -- "$1" : '^\(--.*\)$'` 371 if [ -n "$opt" ] ; then 372 otype="long_flag" 373 value="yes" 374 break 375 fi 376 377 # Try to match a short setting, i.e. -o<value> 378 opt=`expr -- "$1" : '^\(-[A-Za-z0-9]\)..*$'` 379 if [ -n "$opt" ] ; then 380 otype="short_setting" 381 value=`expr -- "$1" : '^-.\(.*\)$'` 382 break 383 fi 384 385 # Try to match a short flag, i.e. -o 386 opt=`expr -- "$1" : '^\(-.\)$'` 387 if [ -n "$opt" ] ; then 388 otype="short_flag" 389 value="yes" 390 break 391 fi 392 393 echo "ERROR: Unknown option '$1'. Use --help for list of valid values." 394 exit 1 395 done 396 397 #echo "Found opt='$opt' otype='$otype' value='$value'" 398 399 name=`dashes_to_underscores $opt` 400 found=0 401 for xopt in $OPTIONS; do 402 if [ "$name" != "$xopt" ] ; then 403 continue 404 fi 405 # Check that the type is correct here 406 # 407 # This also allows us to handle -o <value> as -o<value> 408 # 409 xotype=`option_get_attr $name otype` 410 if [ "$otype" != "$xotype" ] ; then 411 case "$xotype" in 412 "short_flag") 413 option_panic_no_args $opt 414 ;; 415 "short_setting") 416 if [ -z "$2" ] ; then 417 option_panic_missing_arg $opt 418 fi 419 value="$2" 420 shift 421 ;; 422 "long_flag") 423 option_panic_no_args $opt 424 ;; 425 "long_setting") 426 option_panic_missing_arg $opt 427 ;; 428 esac 429 fi 430 found=1 431 break 432 break 433 done 434 if [ "$found" = "0" ] ; then 435 echo "ERROR: Unknown option '$opt'. See --help for usage." 436 exit 1 437 fi 438 # Set variable or launch option-specific function. 439 varname=`option_get_attr $name varname` 440 if [ -n "$varname" ] ; then 441 eval ${varname}=\"$value\" 442 else 443 eval `option_get_attr $name funcname` \"$value\" 444 fi 445 shift 446 done 447} 448 449do_option_help () 450{ 451 print_help 452 exit 0 453} 454 455VERBOSE=no 456VERBOSE2=no 457do_option_verbose () 458{ 459 if [ $VERBOSE = "yes" ] ; then 460 VERBOSE2=yes 461 else 462 VERBOSE=yes 463 fi 464} 465 466register_option "--help" do_option_help "Print this help." 467register_option "--verbose" do_option_verbose "Enable verbose mode." 468 469#==================================================== 470# 471# TOOLCHAIN AND ABI PROCESSING 472# 473#==================================================== 474 475# Determine optional variable value 476# $1: final variable name 477# $2: option variable name 478# $3: small description for the option 479fix_option () 480{ 481 if [ -n "$2" ] ; then 482 eval $1="$2" 483 log "Using specific $3: $2" 484 else 485 log "Using default $3: `var_value $1`" 486 fi 487} 488 489 490# If SYSROOT is empty, check that $1/$2 contains a sysroot 491# and set the variable to it. 492# 493# $1: sysroot path 494# $2: platform/arch suffix 495check_sysroot () 496{ 497 if [ -z "$SYSROOT" ] ; then 498 log "Probing directory for sysroot: $1/$2" 499 if [ -d $1/$2 ] ; then 500 SYSROOT=$1/$2 501 fi 502 fi 503} 504 505# Determine sysroot 506# $1: Option value (or empty) 507# 508fix_sysroot () 509{ 510 if [ -n "$1" ] ; then 511 eval SYSROOT="$1" 512 log "Using specified sysroot: $1" 513 else 514 SYSROOT_SUFFIX=$PLATFORM/arch-$ARCH 515 SYSROOT= 516 check_sysroot $NDK_DIR/platforms $SYSROOT_SUFFIX 517 check_sysroot $ANDROID_NDK_ROOT/platforms $SYSROOT_SUFFIX 518 check_sysroot `dirname $ANDROID_NDK_ROOT`/development/ndk/platforms $SYSROOT_SUFFIX 519 520 if [ -z "$SYSROOT" ] ; then 521 echo "ERROR: Could not find NDK sysroot path for $SYSROOT_SUFFIX." 522 echo " Use --sysroot=<path> to specify one." 523 exit 1 524 fi 525 fi 526 527 if [ ! -f $SYSROOT/usr/include/stdlib.h ] ; then 528 echo "ERROR: Invalid sysroot path: $SYSROOT" 529 echo " Use --sysroot=<path> to indicate a valid one." 530 exit 1 531 fi 532} 533 534# Use the check for the availability of a compatibility SDK in Darwin 535# this can be used to generate binaries compatible with either Tiger or 536# Leopard. 537# 538# $1: SDK root path 539# $2: MacOS X minimum version (e.g. 10.4) 540check_darwin_sdk () 541{ 542 if [ -d "$1" ] ; then 543 HOST_CFLAGS="-isysroot $1 -mmacosx-version-min=$2 -DMAXOSX_DEPLOYEMENT_TARGET=$2" 544 HOST_LDFLAGS="-Wl,-syslibroot,$sdk -mmacosx-version-min=$2" 545 return 0 # success 546 fi 547 return 1 548} 549 550 551handle_mingw () 552{ 553 # Now handle the --mingw flag 554 HOST_EXE= 555 if [ "$MINGW" = "yes" ] ; then 556 case $HOST_TAG in 557 linux-*) 558 ;; 559 *) 560 echo "ERROR: Can only enable mingw on Linux platforms !" 561 exit 1 562 ;; 563 esac 564 if [ "$TRY64" = "yes" ]; then 565 ABI_CONFIGURE_HOST=amd64-mingw32msvc 566 else 567 # NOTE: The canadian-cross build of Binutils 2.19 will fail if you 568 # use i586-pc-mingw32msvc here. Binutils 2.21 will work ok 569 # with both names. 570 # Use i586-pc-mingw32msvc here because wrappers are generated 571 # using this name 572 ABI_CONFIGURE_HOST=i586-pc-mingw32msvc 573 fi 574 HOST_OS=windows 575 HOST_TAG=windows 576 HOST_EXE=.exe 577 fi 578} 579 580# Find mingw toolchain 581# 582# Set MINGW_GCC to the found mingw toolchain 583# 584find_mingw_toolchain () 585{ 586 # IMPORTANT NOTE: binutils 2.21 requires a cross toolchain named 587 # i585-pc-mingw32msvc-gcc, or it will fail its configure step late 588 # in the toolchain build. Note that binutils 2.19 can build properly 589 # with i585-mingw32mvsc-gcc, which is the name used by the 'mingw32' 590 # toolchain install on Debian/Ubuntu. 591 # 592 # To solve this dilemma, we create a wrapper toolchain named 593 # i586-pc-mingw32msvc-gcc that really calls i586-mingw32msvc-gcc, 594 # this works with all versions of binutils. 595 # 596 # We apply the same logic to the 64-bit Windows cross-toolchain 597 # 598 # Fedora note: On Fedora it's x86_64-w64-mingw32- or i686-w64-mingw32- 599 # On older Fedora it's 32-bit only and called i686-pc-mingw32- 600 # so we just add more prefixes to the list to check. 601 if [ "$HOST_ARCH" = "x86_64" -a "$TRY64" = "yes" ]; then 602 BINPREFIX=x86_64-pc-mingw32msvc- 603 BINPREFIXLST="x86_64-pc-mingw32msvc- amd64-mingw32msvc- 604 x86_64-w64-mingw32-" 605 DEBIAN_NAME=mingw64 606 else 607 # we are trying 32 bit anyway, so forcing it to avoid build issues 608 force_32bit_binaries 609 BINPREFIX=i586-pc-mingw32msvc- 610 BINPREFIXLST="i586-pc-mingw32msvc- i686-pc-mingw32- i686-w64-mingw32- 611 i586-mingw32msvc-" 612 DEBIAN_NAME=mingw32 613 fi 614 615 # Scan $BINPREFIXLST list to find installed mingw toolchain. It will be 616 # wrapped later with $BINPREFIX. 617 for i in $BINPREFIXLST; do 618 find_program MINGW_GCC ${i}gcc 619 if [ -n "$MINGW_GCC" ]; then 620 dump "Found mingw toolchain: $MINGW_GCC" 621 break 622 fi 623 done 624} 625 626# If --mingw option is used, check that there is a working 627# mingw32 toolchain installed. 628# 629# If there is, check that it's working 630# 631# $1: install directory for wrapper toolchain 632# 633prepare_mingw_toolchain () 634{ 635 if [ "$MINGW" != "yes" ]; then 636 return 637 fi 638 find_mingw_toolchain 639 if [ -z "$MINGW_GCC" ]; then 640 echo "ERROR: Could not find in your PATH any of:" 641 for i in $BINPREFIXLST; do echo " ${i}gcc"; done 642 echo "Please install the corresponding cross-toolchain and re-run this script" 643 echo "TIP: On Debian or Ubuntu, try: sudo apt-get install $DEBIAN_NAME" 644 exit 1 645 fi 646 # Create a wrapper toolchain, and prepend its dir to our PATH 647 MINGW_WRAP_DIR="$1"/$DEBIAN_NAME-wrapper 648 rm -rf "$MINGW_WRAP_DIR" 649 650 DST_PREFIX=${MINGW_GCC%gcc} 651 if [ "$NDK_CCACHE" ]; then 652 DST_PREFIX="$NDK_CCACHE $DST_PREFIX" 653 fi 654 $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=$BINPREFIX --dst-prefix="$DST_PREFIX" "$MINGW_WRAP_DIR" 655 # generate wrappers for BUILD toolchain 656 # this is required for mingw build to avoid tools canadian cross configuration issues 657 LEGACY_TOOLCHAIN_DIR="$ANDROID_NDK_ROOT/../prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" 658 $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=x86_64-linux-gnu- \ 659 --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/x86_64-linux-" "$MINGW_WRAP_DIR" 660 $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=x86_64-pc-linux-gnu- \ 661 --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/x86_64-linux-" "$MINGW_WRAP_DIR" 662 LEGACY_TOOLCHAIN_DIR="$ANDROID_NDK_ROOT/../prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" 663 $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=i386-linux-gnu- \ 664 --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-" "$MINGW_WRAP_DIR" 665 $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh --src-prefix=i386-pc-linux-gnu- \ 666 --dst-prefix="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-" "$MINGW_WRAP_DIR" 667 fail_panic "Could not create mingw wrapper toolchain in $MINGW_WRAP_DIR" 668 669 export PATH=$MINGW_WRAP_DIR:$PATH 670 dump "Using mingw wrapper: $MINGW_WRAP_DIR/${BINPREFIX}gcc" 671} 672 673handle_host () 674{ 675 # For now, we only support building 32-bit binaries anyway 676 if [ "$TRY64" != "yes" ]; then 677 force_32bit_binaries # to modify HOST_TAG and others 678 HOST_BITS=32 679 fi 680 handle_mingw 681} 682 683setup_ccache () 684{ 685 # Support for ccache compilation 686 # We can't use this here when building Windows binaries on Linux with 687 # binutils 2.21, because defining CC/CXX in the environment makes the 688 # configure script fail later 689 # 690 if [ "$NDK_CCACHE" -a "$MINGW" != "yes" ]; then 691 NDK_CCACHE_CC=$CC 692 NDK_CCACHE_CXX=$CXX 693 # Unfortunately, we can just do CC="$NDK_CCACHE $CC" because some 694 # configure scripts are not capable of dealing with this properly 695 # E.g. the ones used to rebuild the GCC toolchain from scratch. 696 # So instead, use a wrapper script 697 CC=$NDK_BUILDTOOLS_ABSPATH/ndk-ccache-gcc.sh 698 CXX=$NDK_BUILDTOOLS_ABSPATH/ndk-ccache-g++.sh 699 export NDK_CCACHE_CC NDK_CCACHE_CXX 700 log "Using ccache compilation" 701 log "NDK_CCACHE_CC=$NDK_CCACHE_CC" 702 log "NDK_CCACHE_CXX=$NDK_CCACHE_CXX" 703 fi 704} 705 706prepare_common_build () 707{ 708 if [ "$MINGW" = "yes" ]; then 709 if [ "$TRY64" = "yes" ]; then 710 log "Generating 64-bit Windows binaries" 711 HOST_BITS=64 712 else 713 log "Generating 32-bit Windows binaries" 714 HOST_BITS=32 715 fi 716 # Do *not* set CC and CXX when building the Windows binaries 717 # Otherwise, the GCC configure/build script will mess that Canadian cross 718 # build in weird ways. Instead we rely on the toolchain detected or generated 719 # previously in prepare_mingw_toolchain. 720 unset CC CXX STRIP 721 return 722 fi 723 724 # On Linux, detect our legacy-compatible toolchain when in the Android 725 # source tree, and use it to force the generation of glibc-2.7 compatible 726 # binaries. 727 # 728 # We only do this if the CC variable is not defined to a given value 729 # and the --mingw or --try-64 options are not used. 730 # 731 if [ "$HOST_OS" = "linux" -a -z "$CC" -a "$MINGW" != "yes" -a "$TRY64" != "yes" ]; then 732 LEGACY_TOOLCHAIN_DIR="$ANDROID_NDK_ROOT/../prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" 733 if [ -d "$LEGACY_TOOLCHAIN_DIR" ] ; then 734 log "Forcing generation of Linux binaries with legacy toolchain" 735 CC="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-gcc" 736 CXX="$LEGACY_TOOLCHAIN_DIR/bin/i686-linux-g++" 737 fi 738 fi 739 740 # Force generation of 32-bit binaries on 64-bit systems 741 CC=${CC:-gcc} 742 CXX=${CXX:-g++} 743 STRIP=${STRIP:-strip} 744 case $HOST_TAG in 745 darwin-*) 746 # Try to build with Tiger SDK if available 747 if check_darwin_sdk /Developer/SDKs/MacOSX10.4.sdku 10.4; then 748 log "Generating Tiger-compatible binaries!" 749 # Otherwise with Leopard SDK 750 elif check_darwin_sdk /Developer/SDKs/MacOSX10.5.sdk 10.5; then 751 log "Generating Leopard-compatible binaries!" 752 else 753 local version=`sw_vers -productVersion` 754 log "Generating $version-compatible binaries!" 755 fi 756 ;; 757 esac 758 759 # Force generation of 32-bit binaries on 64-bit systems. 760 # We used to test the value of $HOST_TAG for *-x86_64, but this is 761 # not sufficient on certain systems. 762 # 763 # For example, Snow Leopard can be booted with a 32-bit kernel, running 764 # a 64-bit userland, with a compiler that generates 64-bit binaries by 765 # default *even* though "gcc -v" will report --target=i686-apple-darwin10! 766 # 767 # So know, simply probe for the size of void* by performing a small runtime 768 # compilation test. 769 # 770 cat > $TMPC <<EOF 771 /* this test should fail if the compiler generates 64-bit machine code */ 772 int test_array[1-2*(sizeof(void*) != 4)]; 773EOF 774 log_n "Checking whether the compiler generates 32-bit binaries..." 775 HOST_BITS=32 776 log2 $CC $HOST_CFLAGS -c -o $TMPO $TMPC 777 $NDK_CCACHE $CC $HOST_CFLAGS -c -o $TMPO $TMPC >$TMPL 2>&1 778 if [ $? != 0 ] ; then 779 log "no" 780 if [ "$TRY64" != "yes" ]; then 781 # NOTE: We need to modify the definitions of CC and CXX directly 782 # here. Just changing the value of CFLAGS / HOST_CFLAGS 783 # will not work well with the GCC toolchain scripts. 784 CC="$CC -m32" 785 CXX="$CXX -m32" 786 else 787 HOST_BITS=64 788 fi 789 else 790 log "yes" 791 fi 792 793 # For now, we only support building 32-bit binaries anyway 794 if [ "$TRY64" != "yes" ]; then 795 force_32bit_binaries # to modify HOST_TAG and others 796 HOST_BITS=32 797 fi 798} 799 800prepare_host_build () 801{ 802 prepare_common_build 803 804 # Now deal with mingw 805 if [ "$MINGW" = "yes" ]; then 806 handle_mingw 807 CC=$ABI_CONFIGURE_HOST-gcc 808 CXX=$ABI_CONFIGURE_HOST-g++ 809 LD=$ABI_CONFIGURE_HOST-ld 810 AR=$ABI_CONFIGURE_HOST-ar 811 AS=$ABI_CONFIGURE_HOST-as 812 RANLIB=$ABI_CONFIGURE_HOST-ranlib 813 STRIP=$ABI_CONFIGURE_HOST-strip 814 export CC CXX LD AR AS RANLIB STRIP 815 fi 816 817 setup_ccache 818} 819 820 821prepare_target_build () 822{ 823 # detect build tag 824 case $HOST_TAG in 825 linux-x86) 826 ABI_CONFIGURE_BUILD=i386-linux-gnu 827 ;; 828 linux-x86_64) 829 ABI_CONFIGURE_BUILD=x86_64-linux-gnu 830 ;; 831 darwin-x86) 832 ABI_CONFIGURE_BUILD=i686-apple-darwin 833 ;; 834 darwin-x86_64) 835 ABI_CONFIGURE_BUILD=x86_64-apple-darwin 836 ;; 837 windows) 838 ABI_CONFIGURE_BUILD=i686-pc-cygwin 839 ;; 840 *) 841 echo "ERROR: Unsupported HOST_TAG: $HOST_TAG" 842 echo "Please update 'prepare_host_flags' in build/tools/prebuilt-common.sh" 843 ;; 844 esac 845 846 # By default, assume host == build 847 ABI_CONFIGURE_HOST="$ABI_CONFIGURE_BUILD" 848 849 prepare_common_build 850 HOST_GMP_ABI=$HOST_BITS 851 852 # Now handle the --mingw flag 853 if [ "$MINGW" = "yes" ] ; then 854 handle_mingw 855 # It turns out that we need to undefine this to be able to 856 # perform a canadian-cross build with mingw. Otherwise, the 857 # GMP configure scripts will not be called with the right options 858 HOST_GMP_ABI= 859 fi 860 861 setup_ccache 862} 863 864# $1: Toolchain name 865# 866parse_toolchain_name () 867{ 868 TOOLCHAIN=$1 869 if [ -z "$TOOLCHAIN" ] ; then 870 echo "ERROR: Missing toolchain name!" 871 exit 1 872 fi 873 874 ABI_CFLAGS_FOR_TARGET= 875 ABI_CXXFLAGS_FOR_TARGET= 876 877 # Determine ABI based on toolchain name 878 # 879 case "$TOOLCHAIN" in 880 arm-linux-androideabi-*) 881 ARCH="arm" 882 ABI="armeabi" 883 ABI_CONFIGURE_TARGET="arm-linux-androideabi" 884 ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=armv5te" 885 # Disable ARM Gold linker for now, it doesn't build on Windows, it 886 # crashes with SIGBUS on Darwin, and produces weird executables on 887 # linux that strip complains about... Sigh. 888 #ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --enable-gold=both/gold" 889 890 ;; 891 x86-*) 892 ARCH="x86" 893 ABI=$ARCH 894 ABI_INSTALL_NAME="x86" 895 ABI_CONFIGURE_TARGET="i686-linux-android" 896 # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time 897 # You can't really build these separately at the moment. 898 ABI_CFLAGS_FOR_TARGET="-fPIC" 899 ;; 900 mips*) 901 ARCH="mips" 902 ABI=$ARCH 903 ABI_INSTALL_NAME="mips" 904 ABI_CONFIGURE_TARGET="mipsel-linux-android" 905 # Set default to mips32 906 ABI_CONFIGURE_EXTRA_FLAGS="--with-arch=mips32" 907 # Enable C++ exceptions, RTTI and GNU libstdc++ at the same time 908 # You can't really build these separately at the moment. 909 # Add -fpic, because MIPS NDK will need to link .a into .so. 910 ABI_CFLAGS_FOR_TARGET="-fexceptions -fpic" 911 ABI_CXXFLAGS_FOR_TARGET="-frtti -fpic" 912 # Add --disable-fixed-point to disable fixed-point support 913 # Add --disable-threads for eh_frame handling in a single thread 914 ABI_CONFIGURE_EXTRA_FLAGS="$ABI_CONFIGURE_EXTRA_FLAGS --disable-fixed-point --disable-threads" 915 ;; 916 * ) 917 echo "Invalid toolchain specified. Expected (arm-linux-androideabi-*|x86-*|mips*)" 918 echo "" 919 print_help 920 exit 1 921 ;; 922 esac 923 924 log "Targetting CPU: $ARCH" 925 926 GCC_VERSION=`expr -- "$TOOLCHAIN" : '.*-\([0-9x\.]*\)'` 927 log "Using GCC version: $GCC_VERSION" 928 929 # Determine --host value when building gdbserver 930 case "$TOOLCHAIN" in 931 arm-*) 932 GDBSERVER_HOST=arm-eabi-linux 933 GDBSERVER_CFLAGS="-fno-short-enums" 934 GDBSERVER_LDFLAGS= 935 ;; 936 x86-*) 937 GDBSERVER_HOST=i686-linux-android 938 GDBSERVER_CFLAGS= 939 GDBSERVER_LDFLAGS= 940 ;; 941 mips*) 942 GDBSERVER_HOST=mipsel-linux-android 943 GDBSERVER_CFLAGS= 944 GDBSERVER_LDFLAGS= 945 ;; 946 esac 947 948} 949 950# Return the host "tag" used to identify prebuilt host binaries. 951# NOTE: Handles the case where '$MINGW = true' 952# For now, valid values are: linux-x86, darwin-x86 and windows 953get_prebuilt_host_tag () 954{ 955 local RET=$HOST_TAG 956 if [ "$MINGW" = "yes" ]; then 957 RET=windows 958 fi 959 case $RET in 960 linux-x86_64) 961 if [ "$TRY64" = "no" ]; then 962 RET=linux-x86 963 fi 964 ;; 965 darwin-x86_64) 966 if [ "$TRY64" = "no" ]; then 967 RET=darwin-x86 968 fi 969 ;; 970 esac 971 echo $RET 972} 973 974# Return the executable suffix corresponding to host executables 975get_prebuilt_host_exe_ext () 976{ 977 if [ "$MINGW" = "yes" ]; then 978 echo ".exe" 979 else 980 echo "" 981 fi 982} 983 984# Convert an ABI name into an Architecture name 985# $1: ABI name 986# Result: Arch name 987convert_abi_to_arch () 988{ 989 local RET 990 case $1 in 991 armeabi|armeabi-v7a) 992 RET=arm 993 ;; 994 x86) 995 RET=x86 996 ;; 997 mips) 998 RET=mips 999 ;; 1000 *) 1001 2> echo "ERROR: Unsupported ABI name: $1, use one of: armeabi, armeabi-v7a or x86 or mips" 1002 exit 1 1003 ;; 1004 esac 1005 echo "$RET" 1006} 1007 1008# Take architecture name as input, and output the list of corresponding ABIs 1009# Inverse for convert_abi_to_arch 1010# $1: ARCH name 1011# Out: ABI names list (comma-separated) 1012convert_arch_to_abi () 1013{ 1014 local RET 1015 case $1 in 1016 arm) 1017 RET=armeabi,armeabi-v7a 1018 ;; 1019 x86) 1020 RET=x86 1021 ;; 1022 mips) 1023 RET=mips 1024 ;; 1025 *) 1026 >&2 echo "ERROR: Unsupported ARCH name: $1, use one of: arm, x86, mips" 1027 exit 1 1028 ;; 1029 esac 1030 echo "$RET" 1031} 1032 1033# Take a list of architecture names as input, and output the list of corresponding ABIs 1034# $1: ARCH names list (separated by spaces or commas) 1035# Out: ABI names list (comma-separated) 1036convert_archs_to_abis () 1037{ 1038 local RET 1039 for ARCH in $(commas_to_spaces $@); do 1040 ABI=$(convert_arch_to_abi $ARCH) 1041 if [ -n "$ABI" ]; then 1042 if [ -n "$RET" ]; then 1043 RET=$RET",$ABI" 1044 else 1045 RET=$ABI 1046 fi 1047 else # Error message is printed by convert_arch_to_abi 1048 exit 1 1049 fi 1050 done 1051 echo "$RET" 1052} 1053 1054# Return the default toolchain binary path prefix for given architecture and gcc version 1055# For example: arm 4.6 -> toolchains/arm-linux-androideabi-4.6/prebuilt/<system>/bin/arm-linux-androideabi- 1056# $1: Architecture name 1057# $2: GCC version 1058# $3: optional, system name, defaults to $HOST_TAG 1059get_toolchain_binprefix_for_arch () 1060{ 1061 local NAME PREFIX DIR BINPREFIX 1062 local SYSTEM=${3:-$(get_prebuilt_host_tag)} 1063 NAME=$(get_toolchain_name_for_arch $1 $2) 1064 PREFIX=$(get_default_toolchain_prefix_for_arch $1) 1065 DIR=$(get_toolchain_install . $NAME $SYSTEM) 1066 BINPREFIX=${DIR#./}/bin/$PREFIX- 1067 echo "$BINPREFIX" 1068} 1069 1070# Return the default toochain binary path prefix for a given architecture 1071# For example: arm -> toolchains/arm-linux-androideabi-4.6/prebuilt/<system>/bin/arm-linux-androideabi- 1072# $1: Architecture name 1073# $2: optional, system name, defaults to $HOST_TAG 1074get_default_toolchain_binprefix_for_arch () 1075{ 1076 get_toolchain_binprefix_for_arch $1 $DEFAULT_GCC_VERSION $2 1077} 1078 1079# Return default API level for a given arch 1080# This is the level used to build the toolchains. 1081# 1082# $1: Architecture name 1083get_default_api_level_for_arch () 1084{ 1085 # For now, always build the toolchain against API level 9 1086 # (We have local toolchain patches under build/tools/toolchain-patches 1087 # to ensure that the result works on previous platforms properly). 1088 local LEVEL=9 1089 echo $LEVEL 1090} 1091 1092# Return the default platform sysroot corresponding to a given architecture 1093# This is the sysroot used to build the toolchain and other binaries like 1094# the STLport libraries. 1095# $1: Architecture name 1096get_default_platform_sysroot_for_arch () 1097{ 1098 local LEVEL=$(get_default_api_level_for_arch $1) 1099 echo "platforms/android-$LEVEL/arch-$1" 1100} 1101 1102# Guess what? 1103get_default_platform_sysroot_for_abi () 1104{ 1105 local ARCH=$(convert_abi_to_arch $1) 1106 $(get_default_platform_sysroot_for_arch $ARCH) 1107} 1108 1109 1110 1111# Return the host/build specific path for prebuilt toolchain binaries 1112# relative to $1. 1113# 1114# $1: target root NDK directory 1115# $2: toolchain name 1116# $3: optional, host system name 1117# 1118get_toolchain_install () 1119{ 1120 local NDK="$1" 1121 shift 1122 echo "$NDK/$(get_toolchain_install_subdir "$@")" 1123} 1124 1125# $1: toolchain name 1126# $2: optional, host system name 1127get_toolchain_install_subdir () 1128{ 1129 local SYSTEM=${2:-$(get_prebuilt_host_tag)} 1130 echo "toolchains/$1/prebuilt/$SYSTEM" 1131} 1132 1133# Return the relative install prefix for prebuilt host 1134# executables (relative to the NDK top directory). 1135# NOTE: This deals with MINGW==yes appropriately 1136# 1137# $1: optional, system name 1138# Out: relative path to prebuilt install prefix 1139get_prebuilt_install_prefix () 1140{ 1141 local TAG=${1:-$(get_prebuilt_host_tag)} 1142 echo "prebuilt/$TAG" 1143} 1144 1145# Return the relative path of an installed prebuilt host 1146# executable 1147# NOTE: This deals with MINGW==yes appropriately. 1148# 1149# $1: executable name 1150# $2: optional, host system name 1151# Out: path to prebuilt host executable, relative 1152get_prebuilt_host_exec () 1153{ 1154 local PREFIX EXE 1155 PREFIX=$(get_prebuilt_install_prefix $2) 1156 EXE=$(get_prebuilt_host_exe_ext) 1157 echo "$PREFIX/bin/$1$EXE" 1158} 1159 1160# Return the name of a given host executable 1161# $1: executable base name 1162# Out: executable name, with optional suffix (e.g. .exe for windows) 1163get_host_exec_name () 1164{ 1165 local EXE=$(get_prebuilt_host_exe_ext) 1166 echo "$1$EXE" 1167} 1168 1169# Return the directory where host-specific binaries are installed. 1170# $1: target root NDK directory 1171get_host_install () 1172{ 1173 echo "$1/$(get_prebuilt_install_prefix)" 1174} 1175 1176# Set the toolchain target NDK location. 1177# this sets TOOLCHAIN_PATH and TOOLCHAIN_PREFIX 1178# $1: target NDK path 1179# $2: toolchain name 1180set_toolchain_ndk () 1181{ 1182 TOOLCHAIN_PATH=`get_toolchain_install "$1" $2` 1183 log "Using toolchain path: $TOOLCHAIN_PATH" 1184 1185 TOOLCHAIN_PREFIX=$TOOLCHAIN_PATH/bin/$ABI_CONFIGURE_TARGET 1186 log "Using toolchain prefix: $TOOLCHAIN_PREFIX" 1187} 1188 1189# Check that a toolchain is properly installed at a target NDK location 1190# 1191# $1: target root NDK directory 1192# $2: toolchain name 1193# 1194check_toolchain_install () 1195{ 1196 TOOLCHAIN_PATH=`get_toolchain_install "$1" $2` 1197 if [ ! -d "$TOOLCHAIN_PATH" ] ; then 1198 echo "ERROR: Cannot find directory '$TOOLCHAIN_PATH'!" 1199 echo " Toolchain '$2' not installed in '$NDK_DIR'!" 1200 echo " Ensure that the toolchain has been installed there before." 1201 exit 1 1202 fi 1203 1204 set_toolchain_ndk $1 $2 1205} 1206 1207# $1: toolchain source directory 1208check_toolchain_src_dir () 1209{ 1210 local SRC_DIR="$1" 1211 if [ -z "$SRC_DIR" ]; then 1212 echo "ERROR: Please provide the path to the toolchain source tree. See --help" 1213 exit 1 1214 fi 1215 1216 if [ ! -d "$SRC_DIR" ]; then 1217 echo "ERROR: Not a directory: '$SRC_DIR'" 1218 exit 1 1219 fi 1220 1221 if [ ! -f "$SRC_DIR/build/configure" -o ! -d "$SRC_DIR/gcc" ]; then 1222 echo "ERROR: Either the file $SRC_DIR/build/configure or" 1223 echo " the directory $SRC_DIR/gcc does not exist." 1224 echo "This is not the top of a toolchain tree: $SRC_DIR" 1225 echo "You must give the path to a copy of the toolchain source directories" 1226 echo "created by 'download-toolchain-sources.sh." 1227 exit 1 1228 fi 1229} 1230 1231# 1232# The NDK_TMPDIR variable is used to specify a root temporary directory 1233# when invoking toolchain build scripts. If it is not defined, we will 1234# create one here, and export the value to ensure that any scripts we 1235# call after that use the same one. 1236# 1237if [ -z "$NDK_TMPDIR" ]; then 1238 NDK_TMPDIR=/tmp/ndk-$USER/tmp/build-$$ 1239 mkdir -p $NDK_TMPDIR 1240 if [ $? != 0 ]; then 1241 echo "ERROR: Could not create NDK_TMPDIR: $NDK_TMPDIR" 1242 exit 1 1243 fi 1244 export NDK_TMPDIR 1245fi 1246 1247# Define HOST_TAG32, as the 32-bit version of HOST_TAG 1248# We do this by replacing an -x86_64 suffix by -x86 1249HOST_TAG32=$HOST_TAG 1250case $HOST_TAG32 in 1251 *-x86_64) 1252 HOST_TAG32=${HOST_TAG%%_64} 1253 ;; 1254esac 1255