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