Home | History | Annotate | Download | only in tools
      1 # Copyright (C) 2012 The Android Open Source Project
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #      http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 #
     15 
     16 # A set of function shared by the 'build-host-xxxx.sh' scripts.
     17 # They are mostly related to building host libraries.
     18 #
     19 # NOTE: This script uses various prefixes:
     20 #
     21 #    BH_       Used for public macros
     22 #    bh_       Use for public functions
     23 #
     24 #    _BH_      Used for private macros
     25 #    _bh_      Used for private functions
     26 #
     27 # Callers should only rely on the public macros and functions defined here.
     28 #
     29 
     30 # List of macros defined by the functions here:
     31 #
     32 #   defined by 'bh_set_build_tag'
     33 #
     34 #   BH_BUILD_CONFIG     Generic GNU config triplet for build system
     35 #   BH_BUILD_OS         NDK system name
     36 #   BH_BUILD_ARCH       NDK arch name
     37 #   BH_BUILD_TAG        NDK system tag ($OS-$ARCH)
     38 #   BH_BUILD_BITS       build system bitness (32 or 64)
     39 #
     40 #   defined by 'bh_set_host_tag'
     41 #                          7
     42 #   BH_HOST_CONFIG
     43 #   BH_HOST_OS
     44 #   BH_HOST_ARCH
     45 #   BH_HOST_TAG
     46 #   BH_HOST_BITS
     47 #
     48 #   defined by 'bh_set_target_tag'
     49 #
     50 #   BH_TARGET_CONFIG
     51 #   BH_TARGET_OS
     52 #   BH_TARGET_ARCH
     53 #   BH_TARGET_TAG
     54 #   BH_TARGET_BITS
     55 #
     56 #
     57 
     58 
     59 # The values of HOST_OS/ARCH/TAG will be redefined during the build to
     60 # match those of the system the generated compiler binaries will run on.
     61 #
     62 # Save the original ones into BUILD_XXX variants, corresponding to the
     63 # machine where the build happens.
     64 #
     65 BH_BUILD_OS=$HOST_OS
     66 BH_BUILD_ARCH=$HOST_ARCH
     67 BH_BUILD_TAG=$HOST_TAG
     68 
     69 # Map an NDK system tag to an OS name
     70 # $1: system tag (e.g. linux-x86)
     71 # Out: system name (e.g. linux)
     72 bh_tag_to_os ()
     73 {
     74     local RET
     75     case $1 in
     76         android-*) RET="android";;
     77         linux-*) RET="linux";;
     78         darwin-*) RET="darwin";;
     79         windows|windows-*) RET="windows";;
     80     esac
     81     echo $RET
     82 }
     83 
     84 # Map an NDK system tag to an architecture name
     85 # $1: system tag (e.g. linux-x86)
     86 # Out: arch name (e.g. x86)
     87 bh_tag_to_arch ()
     88 {
     89     local RET
     90     case $1 in
     91         *-arm) RET=arm;;
     92         *-mips) RET=mips;;
     93         windows|*-x86) RET=x86;;
     94         *-x86_64) RET=x86_64;;
     95     esac
     96     echo $RET
     97 }
     98 
     99 # Map an NDK system tag to a bit number
    100 # $1: system tag (e.g. linux-x86)
    101 # Out: bit number (32 or 64)
    102 bh_tag_to_bits ()
    103 {
    104     local RET
    105     case $1 in
    106         windows|*-x86|*-arm|*-mips) RET=32;;
    107         *-x86_64) RET=64;;
    108     esac
    109     echo $RET
    110 }
    111 
    112 # Map an NDK system tag to the corresponding GNU configuration triplet.
    113 # $1: NDK system tag
    114 # Out: GNU configuration triplet
    115 bh_tag_to_config_triplet ()
    116 {
    117     local RET
    118     case $1 in
    119         linux-x86) RET=i686-linux-gnu;;
    120         linux-x86_64) RET=x86_64-linux-gnu;;
    121         darwin-x86) RET=i686-apple-darwin;;
    122         darwin-x86_64) RET=x86_64-apple-darwin;;
    123         windows|windows-x86) RET=i586-pc-mingw32msvc;;
    124         windows-x86_64) RET=x86_64-w64-mingw32;;
    125         android-arm) RET=arm-linux-androideabi;;
    126         android-x86) RET=i686-linux-android;;
    127         android-mips) RET=mipsel-linux-android;;
    128     esac
    129     echo "$RET"
    130 }
    131 
    132 
    133 bh_set_build_tag ()
    134 {
    135   BH_BUILD_OS=$(bh_tag_to_os $1)
    136   BH_BUILD_ARCH=$(bh_tag_to_arch $1)
    137   BH_BUILD_BITS=$(bh_tag_to_bits $1)
    138   BH_BUILD_TAG=$BH_BUILD_OS-$BH_BUILD_ARCH
    139   BH_BUILD_CONFIG=$(bh_tag_to_config_triplet $1)
    140 }
    141 
    142 # Set default BH_BUILD macros.
    143 bh_set_build_tag $HOST_TAG
    144 
    145 bh_set_host_tag ()
    146 {
    147   BH_HOST_OS=$(bh_tag_to_os $1)
    148   BH_HOST_ARCH=$(bh_tag_to_arch $1)
    149   BH_HOST_BITS=$(bh_tag_to_bits $1)
    150   BH_HOST_TAG=$BH_HOST_OS-$BH_HOST_ARCH
    151   BH_HOST_CONFIG=$(bh_tag_to_config_triplet $1)
    152 }
    153 
    154 bh_set_target_tag ()
    155 {
    156   BH_TARGET_OS=$(bh_tag_to_os $1)
    157   BH_TARGET_ARCH=$(bh_tag_to_arch $1)
    158   BH_TARGET_BITS=$(bh_tag_to_bits $1)
    159   BH_TARGET_TAG=$BH_TARGET_OS-$BH_TARGET_ARCH
    160   BH_TARGET_CONFIG=$(bh_tag_to_config_triplet $1)
    161 }
    162 
    163 bh_sort_systems_build_first ()
    164 {
    165   local IN_SYSTEMS="$1"
    166   local OUT_SYSTEMS
    167   # Pull out the host if there
    168   for IN_SYSTEM in $IN_SYSTEMS; do
    169     if [ "$IN_SYSTEM" = "$BH_BUILD_TAG" ]; then
    170         OUT_SYSTEMS=$IN_SYSTEM
    171     fi
    172   done
    173   # Append the rest
    174   for IN_SYSTEM in $IN_SYSTEMS; do
    175     if [ ! "$IN_SYSTEM" = "$BH_BUILD_TAG" ]; then
    176         OUT_SYSTEMS=$OUT_SYSTEMS" $IN_SYSTEM"
    177     fi
    178   done
    179   echo $OUT_SYSTEMS
    180 }
    181 
    182 # $1 is the string to search for
    183 # $2... is the list to search in
    184 # Returns first, yes or no.
    185 bh_list_contains ()
    186 {
    187   local SEARCH="$1"
    188   shift
    189   # For dash, this has to be split over 2 lines.
    190   # Seems to be a bug with dash itself:
    191   # https://bugs.launchpad.net/ubuntu/+source/dash/+bug/141481
    192   local LIST
    193   LIST=$@
    194   local RESULT=first
    195   # Pull out the host if there
    196   for ELEMENT in $LIST; do
    197     if [ "$ELEMENT" = "$SEARCH" ]; then
    198       echo $RESULT
    199       return 0
    200     fi
    201     RESULT=yes
    202   done
    203   echo no
    204   return 1
    205 }
    206 
    207 
    208 # Use this function to enable/disable colored output
    209 # $1: 'true' or 'false'
    210 bh_set_color_mode ()
    211 {
    212   local DO_COLOR=
    213   case $1 in
    214     on|enable|true) DO_COLOR=true
    215     ;;
    216   esac
    217   if [ "$DO_COLOR" ]; then
    218     _BH_COLOR_GREEN="\033[32m"
    219     _BH_COLOR_PURPLE="\033[35m"
    220     _BH_COLOR_CYAN="\033[36m"
    221     _BH_COLOR_END="\033[0m"
    222   else
    223     _BH_COLOR_GREEN=
    224     _BH_COLOR_PURPLE=
    225     _BH_COLOR_CYAN=
    226     _BH_COLOR_END=
    227   fi
    228 }
    229 
    230 # By default, enable color mode
    231 bh_set_color_mode true
    232 
    233 # Pretty printing with colors!
    234 bh_host_text ()
    235 {
    236     printf "[${_BH_COLOR_GREEN}${BH_HOST_TAG}${_BH_COLOR_END}]"
    237 }
    238 
    239 bh_toolchain_text ()
    240 {
    241     printf "[${_BH_COLOR_PURPLE}${BH_TOOLCHAIN}${_BH_COLOR_END}]"
    242 }
    243 
    244 bh_target_text ()
    245 {
    246     printf "[${_BH_COLOR_CYAN}${BH_TARGET_TAG}${_BH_COLOR_END}]"
    247 }
    248 
    249 bh_arch_text ()
    250 {
    251     # Print arch name in cyan
    252     printf "[${_BH_COLOR_CYAN}${BH_TARGET_ARCH}${_BH_COLOR_END}]"
    253 }
    254 
    255 _bh_extract_version ()
    256 {
    257     echo $1 | tr '-' '\n' | tail -1
    258 }
    259 
    260 # Given an input string of the form <foo>-<bar>-<version>, where
    261 # <version> can be <major>.<minor>, extract <major>
    262 #
    263 # $1: versioned name (e.g. arm-linux-androideabi-4.4.3)
    264 # Out: major version (e.g. 4)
    265 #
    266 # Examples:  arm-linux-androideabi-4.4.3 -> 4
    267 #            gmp-0.81 -> 0
    268 #
    269 bh_extract_major_version ()
    270 {
    271     local RET=$(_bh_extract_version $1 | cut -d . -f 1)
    272     RET=${RET:-0}
    273     echo $RET
    274 }
    275 
    276 # Same as extract_major_version, but for the minor version number
    277 # $1: versioned named
    278 # Out: minor version
    279 #
    280 bh_extract_minor_version ()
    281 {
    282     local RET=$(_bh_extract_version $1 | cut -d . -f 2)
    283     RET=${RET:-0}
    284     echo $RET
    285 }
    286 
    287 # Compare two version numbers and only succeeds if the first one is
    288 # greather or equal than the second one.
    289 #
    290 # $1: first version (e.g. 4.4.3)
    291 # $2: second version (e.g. 4.6)
    292 #
    293 # Example: version_is_greater_than 4.6 4.4.3 --> success
    294 #
    295 bh_version_is_greater_than ()
    296 {
    297     local A_MAJOR A_MINOR B_MAJOR B_MINOR
    298     A_MAJOR=$(bh_extract_major_version $1)
    299     B_MAJOR=$(bh_extract_major_version $2)
    300 
    301     if [ $A_MAJOR -lt $B_MAJOR ]; then
    302         return 1
    303     elif [ $A_MAJOR -gt $B_MAJOR ]; then
    304         return 0
    305     fi
    306 
    307     # We have A_MAJOR == B_MAJOR here
    308 
    309     A_MINOR=$(bh_extract_minor_version $1)
    310     B_MINOR=$(bh_extract_minor_version $2)
    311 
    312     if [ $A_MINOR -lt $B_MINOR ]; then
    313         return 1
    314     else
    315         return 0
    316     fi
    317 }
    318 
    319 # Check that a given compiler generates code correctly
    320 #
    321 # This is to detect bad/broken toolchains, e.g. amd64-mingw32msvc
    322 # is totally broken on Ubuntu 10.10 and 11.04
    323 #
    324 # $1: compiler
    325 # $2: optional extra flags
    326 #
    327 bh_check_compiler ()
    328 {
    329     local CC="$1"
    330     local TMPC=/tmp/build-host-$USER-$$.c
    331     local TMPE=${TMPC%%.c}
    332     local TMPL=$TMPC.log
    333     local RET
    334     shift
    335     cat > $TMPC <<EOF
    336 int main(void) { return 0; }
    337 EOF
    338     log_n "Checking compiler code generation ($CC)... "
    339     $CC -o $TMPE $TMPC "$@" >$TMPL 2>&1
    340     RET=$?
    341     rm -f $TMPC $TMPE $TMPL
    342     if [ "$RET" = 0 ]; then
    343         log "yes"
    344     else
    345         log "no"
    346     fi
    347     return $RET
    348 }
    349 
    350 
    351 # $1: toolchain install dir
    352 # $2: toolchain prefix, no trailing dash (e.g. arm-linux-androideabi)
    353 # $3: optional -m32 or -m64.
    354 _bh_try_host_fullprefix ()
    355 {
    356     local PREFIX="$1/bin/$2"
    357     shift; shift;
    358     if [ -z "$HOST_FULLPREFIX" ]; then
    359         local GCC="$PREFIX-gcc"
    360         if [ -f "$GCC" ]; then
    361             if bh_check_compiler "$GCC" "$@"; then
    362                 HOST_FULLPREFIX="${GCC%%gcc}"
    363                 dump "$(bh_host_text) Using host gcc: $GCC $@"
    364             else
    365                 dump "$(bh_host_text) Ignoring broken host gcc: $GCC $@"
    366             fi
    367         fi
    368     fi
    369 }
    370 
    371 # $1: host prefix, no trailing slash (e.g. i686-linux-android)
    372 # $2: optional compiler args (should be empty, -m32 or -m64)
    373 _bh_try_host_prefix ()
    374 {
    375     local PREFIX="$1"
    376     shift
    377     if [ -z "$HOST_FULLPREFIX" ]; then
    378         local GCC="$(which $PREFIX-gcc 2>/dev/null)"
    379         if [ "$GCC" -a -e "$GCC" ]; then
    380             if bh_check_compiler "$GCC" "$@"; then
    381                 HOST_FULLPREFIX=${GCC%%gcc}
    382                 dump "$(bh_host_text) Using host gcc: ${HOST_FULLPREFIX}gcc $@"
    383             else
    384                 dump "$(bh_host_text) Ignoring broken host gcc: $GCC $@"
    385             fi
    386         fi
    387     fi
    388 }
    389 
    390 # Used to determine the minimum possible Darwin version that a Darwin SDK
    391 # can target. This actually depends from the host architecture.
    392 # $1: Host architecture name
    393 # out: SDK version number (e.g. 10.4 or 10.5)
    394 _bh_darwin_arch_to_min_version ()
    395 {
    396   if [ "$1" = "x86" ]; then
    397     echo "10.4"
    398   else
    399     echo "10.5"
    400   fi
    401 }
    402 
    403 # Use the check for the availability of a compatibility SDK in Darwin
    404 # this can be used to generate binaries compatible with either Tiger or
    405 # Leopard.
    406 #
    407 # $1: SDK root path
    408 # $2: Darwin compatibility minimum version
    409 _bh_check_darwin_sdk ()
    410 {
    411     if [ -d "$1" -a -z "$HOST_CFLAGS" ] ; then
    412         HOST_CFLAGS="-isysroot $1 -mmacosx-version-min=$2 -DMAXOSX_DEPLOYEMENT_TARGET=$2"
    413         HOST_CXXFLAGS=$HOST_CFLAGS
    414         HOST_LDFLAGS="-syslibroot $1 -mmacosx-version-min=$2"
    415         dump "Generating $2-compatible binaries."
    416         return 0  # success
    417     fi
    418     return 1
    419 }
    420 
    421 # Check that a given compiler generates 32 or 64 bit code.
    422 # $1: compiler full path (.e.g  /path/to/fullprefix-gcc)
    423 # $2: 32 or 64
    424 # $3: extract compiler flags
    425 # Return: success iff the compiler generates $2-bits code
    426 _bh_check_compiler_bitness ()
    427 {
    428     local CC="$1"
    429     local BITS="$2"
    430     local TMPC=/tmp/build-host-gcc-bits-$USER-$$.c
    431     local TMPL=$TMPC.log
    432     local RET
    433     shift; shift;
    434     cat > $TMPC <<EOF
    435 /* this program will fail to compile if the compiler doesn't generate BITS-bits code */
    436 int tab[1-2*(sizeof(void*)*8 != BITS)];
    437 EOF
    438     dump_n "$(bh_host_text) Checking that the compiler generates $BITS-bits code ($@)... "
    439     $CC -c -DBITS=$BITS -o /dev/null $TMPC $HOST_CFLAGS "$@" > $TMPL 2>&1
    440     RET=$?
    441     rm -f $TMPC $TMPL
    442     if [ "$RET" = 0 ]; then
    443         dump "yes"
    444     else
    445         dump "no"
    446     fi
    447     return $RET
    448 }
    449 
    450 # This function probes the system to find the best toolchain or cross-toolchain
    451 # to build binaries that run on a given host system. After that, it generates
    452 # a wrapper toolchain under $2 with a prefix of ${BH_HOST_CONFIG}-
    453 # where $BH_HOST_CONFIG is a GNU configuration name.
    454 #
    455 # Important: this script might redefine $BH_HOST_CONFIG to a different value!
    456 #
    457 # $1: NDK system tag (e.g. linux-x86)
    458 #
    459 # The following can be defined, otherwise they'll be auto-detected and set.
    460 #
    461 #  DARWIN_MIN_VERSION   -> Darwmin minimum compatibility version
    462 #  DARWIN_SDK_VERSION   -> Darwin SDK version
    463 #
    464 # The following can be defined for extra features:
    465 #
    466 #  DARWIN_TOOLCHAIN     -> Path to Darwin cross-toolchain (cross-compile only).
    467 #  DARWIN_SYSROOT       -> Path to Darwin SDK sysroot (cross-compile only).
    468 #  NDK_CCACHE           -> Ccache binary to use to speed up rebuilds.
    469 #  ANDROID_NDK_ROOT     -> Top-level NDK directory, for automatic probing
    470 #                          of prebuilt platform toolchains.
    471 #
    472 _bh_select_toolchain_for_host ()
    473 {
    474     local HOST_CFLAGS HOST_CXXFLAGS HOST_LDFLAGS HOST_FULLPREFIX DARWIN_ARCH
    475     local DARWIN_ARCH DARWIN_SDK_SUBDIR
    476 
    477     # We do all the complex auto-detection magic in the setup phase,
    478     # then save the result in host-specific global variables.
    479     #
    480     # In the build phase, we will simply restore the values into the
    481     # global HOST_FULLPREFIX / HOST_BUILD_DIR
    482     # variables.
    483     #
    484 
    485     # Try to find the best toolchain to do that job, assuming we are in
    486     # a full Android platform source checkout, we can look at the prebuilts/
    487     # directory.
    488     case $1 in
    489         linux-x86)
    490             # If possible, automatically use our custom toolchain to generate
    491             # 32-bit executables that work on Ubuntu 8.04 and higher.
    492             _bh_try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" i686-linux
    493             _bh_try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.4.3" i686-linux
    494             _bh_try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilt/linux-x86/toolchain/i686-linux-glibc2.7-4.4.3" i686-linux
    495             _bh_try_host_prefix i686-linux-gnu
    496             _bh_try_host_prefix i686-linux
    497             _bh_try_host_prefix x86_64-linux-gnu -m32
    498             _bh_try_host_prefix x86_64-linux -m32
    499             ;;
    500 
    501         linux-x86_64)
    502             # If possible, automaticaly use our custom toolchain to generate
    503             # 64-bit executables that work on Ubuntu 8.04 and higher.
    504             _bh_try_host_fullprefix "$(dirname $ANDROID_NDK_ROOT)/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" x86_64-linux
    505             _bh_try_host_prefix x86_64-linux-gnu
    506             _bh_try_host_prefix x84_64-linux
    507             _bh_try_host_prefix i686-linux-gnu -m64
    508             _bh_try_host_prefix i686-linux -m64
    509             ;;
    510 
    511         darwin-*)
    512             DARWIN_ARCH=$(bh_tag_to_arch $1)
    513             if [ -z "$DARWIN_MIN_VERSION" ]; then
    514                 DARWIN_MIN_VERSION=$(_bh_darwin_arch_to_min_version $DARWIN_ARCH)
    515             fi
    516             case $BH_BUILD_OS in
    517                 darwin)
    518                     if [ "$DARWIN_SDK_VERSION" ]; then
    519                         # Compute SDK subdirectory name
    520                         case $DARWIN_SDK_VERSION in
    521                             10.4) DARWIN_SDK_SUBDIR=$DARWIN_SDK.sdku;;
    522                             *) DARWIN_SDK_SUBDIR=$DARWIN_SDK.sdk;;
    523                         esac
    524                         # Since xCode moved to the App Store the SDKs have been 'sandboxed' into the Xcode.app folder.
    525                         _bh_check_darwin_sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$DARWIN_SDK_SUBDIR $DARWIN_MIN_VERSION
    526                         _bh_check_darwin_sdk /Developer/SDKs/MacOSX$DARWIN_SDK_SUBDIR $DARWIN_MIN_VERSION
    527                     else
    528                         # Since xCode moved to the App Store the SDKs have been 'sandboxed' into the Xcode.app folder.
    529                         _bh_check_darwin_sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk $DARWIN_MIN_VERSION
    530                         _bh_check_darwin_sdk /Developer/SDKs/MacOSX10.7.sdk  $DARWIN_MIN_VERSION
    531                         _bh_check_darwin_sdk /Developer/SDKs/MacOSX10.6.sdk  $DARWIN_MIN_VERSION
    532                         # NOTE: The 10.5.sdk on Lion is buggy and cannot build basic C++ programs
    533                         #_bh_check_darwin_sdk /Developer/SDKs/MacOSX10.5.sdk  $DARWIN_ARCH
    534                         # NOTE: The 10.4.sdku is not available anymore and could not be tested.
    535                         #_bh_check_darwin_sdk /Developer/SDKs/MacOSX10.4.sdku $DARWIN_ARCH
    536                     fi
    537                     if [ -z "$HOST_CFLAGS" ]; then
    538                         local version="$(sw_vers -productVersion)"
    539                         log "Generating $version-compatible binaries!"
    540                     fi
    541                     ;;
    542                 *)
    543                     if [ -z "$DARWIN_TOOLCHAIN" -o -z "$DARWIN_SYSROOT" ]; then
    544                         dump "If you want to build Darwin binaries on a non-Darwin machine,"
    545                         dump "Please define DARWIN_TOOLCHAIN to name it, and DARWIN_SYSROOT to point"
    546                         dump "to the SDK. For example:"
    547                         dump ""
    548                         dump "   DARWIN_TOOLCHAIN=\"i686-apple-darwin11\""
    549                         dump "   DARWIN_SYSROOT=\"~/darwin-cross/MacOSX10.7.sdk\""
    550                         dump "   export DARWIN_TOOLCHAIN DARWIN_SYSROOT"
    551                         dump ""
    552                         exit 1
    553                     fi
    554                     _bh_check_darwin_sdk $DARWIN_SYSROOT $DARWIN_MIN_VERSION
    555                     _bh_try_host_prefix "$DARWIN_TOOLCHAIN" -m$(bh_tag_to_bits $1) --sysroot "$DARWIN_SYSROOT"
    556                     if [ -z "$HOST_FULLPREFIX" ]; then
    557                         dump "It looks like $DARWIN_TOOLCHAIN-gcc is not in your path, or does not work correctly!"
    558                         exit 1
    559                     fi
    560                     dump "Using darwin cross-toolchain: ${HOST_FULLPREFIX}gcc"
    561                     ;;
    562             esac
    563             ;;
    564 
    565         windows|windows-x86)
    566             case $BH_BUILD_OS in
    567                 linux)
    568                     # We favor these because they are more recent, and because
    569                     # we have a script to rebuild them from scratch. See
    570                     # build-mingw64-toolchain.sh.
    571                     _bh_try_host_prefix x86_64-w64-mingw32 -m32
    572                     _bh_try_host_prefix i686-w64-mingw32
    573                     # Typically provided by the 'mingw32' package on Debian
    574                     # and Ubuntu systems.
    575                     _bh_try_host_prefix i586-mingw32msvc
    576                     # Special note for Fedora: this distribution used
    577                     # to have a mingw32-gcc package that provided a 32-bit
    578                     # only cross-toolchain named i686-pc-mingw32.
    579                     # Later versions of the distro now provide a new package
    580                     # named mingw-gcc which provides i686-w64-mingw32 and
    581                     # x86_64-w64-mingw32 instead.
    582                     _bh_try_host_prefix i686-pc-mingw32
    583                     if [ -z "$HOST_FULLPREFIX" ]; then
    584                         dump "There is no Windows cross-compiler. Ensure that you"
    585                         dump "have one of these installed and in your path:"
    586                         dump "   x86_64-w64-mingw32-gcc  (see build-mingw64-toolchain.sh)"
    587                         dump "   i686-w64-mingw32-gcc    (see build-mingw64-toolchain.sh)"
    588                         dump "   i586-mingw32msvc-gcc    ('mingw32' Debian/Ubuntu package)"
    589                         dump "   i686-pc-mingw32         (on Fedora)"
    590                         dump ""
    591                         exit 1
    592                     fi
    593                     # Adjust $HOST to match the toolchain to ensure proper builds.
    594                     # I.e. chose configuration triplets that are known to work
    595                     # with the gmp/mpfr/mpc/binutils/gcc configure scripts.
    596                     case $HOST_FULLPREFIX in
    597                         *-mingw32msvc-*|i686-pc-mingw32)
    598                             BH_HOST_CONFIG=i586-pc-mingw32msvc
    599                             ;;
    600                         *)
    601                             BH_HOST_CONFIG=i686-w64-mingw32msvc
    602                             ;;
    603                     esac
    604                     ;;
    605                 *) panic "Sorry, this script only supports building windows binaries on Linux."
    606                 ;;
    607             esac
    608             HOST_CFLAGS=$HOST_CFLAGS" -D__USE_MINGW_ANSI_STDIO=1"
    609             HOST_CXXFLAGS=$HOST_CXXFLAGS" -D__USE_MINGW_ANSI_STDIO=1"
    610             ;;
    611 
    612         windows-x86_64)
    613             case $BH_BUILD_OS in
    614                 linux)
    615                     # See comments above for windows-x86
    616                     _bh_try_host_prefix x86_64-w64-mingw32
    617                     _bh_try_host_prefix i686-w64-mingw32 -m64
    618                     # Beware that this package is completely broken on many
    619                     # versions of no vinegar Ubuntu (i.e. it fails at building trivial
    620                     # programs).
    621                     _bh_try_host_prefix amd64-mingw32msvc
    622                     # There is no x86_64-pc-mingw32 toolchain on Fedora.
    623                     if [ -z "$HOST_FULLPREFIX" ]; then
    624                         dump "There is no Windows cross-compiler in your path. Ensure you"
    625                         dump "have one of these installed and in your path:"
    626                         dump "   x86_64-w64-mingw32-gcc  (see build-mingw64-toolchain.sh)"
    627                         dump "   i686-w64-mingw32-gcc    (see build-mingw64-toolchain.sh)"
    628                         dump "   amd64-mingw32msvc-gcc   (Debian/Ubuntu - broken until Ubuntu 11.10)"
    629                         dump ""
    630                         exit 1
    631                     fi
    632                     # See comment above for windows-x86
    633                     case $HOST_FULLPREFIX in
    634                         *-mingw32msvc*)
    635                             # Actually, this has never been tested.
    636                             BH_HOST=amd64-pc-mingw32msvc
    637                             ;;
    638                         *)
    639                             BH_HOST=x86_64-w64-mingw32
    640                             ;;
    641                     esac
    642                     ;;
    643 
    644                 *) panic "Sorry, this script only supports building windows binaries on Linux."
    645                 ;;
    646             esac
    647             HOST_CFLAGS=$HOST_CFLAGS" -D__USE_MINGW_ANSI_STDIO=1"
    648             HOST_CXXFLAGS=$HOST_CXXFLAGS" -D__USE_MINGW_ANSI_STDIO=1"
    649             ;;
    650     esac
    651 
    652     # Determine the default bitness of our compiler. It it doesn't match
    653     # HOST_BITS, tries to see if it supports -m32 or -m64 to change it.
    654     if ! _bh_check_compiler_bitness ${HOST_FULLPREFIX}gcc $BH_HOST_BITS; then
    655         local TRY_CFLAGS
    656         case $BH_HOST_BITS in
    657             32) TRY_CFLAGS=-m32;;
    658             64) TRY_CFLAGS=-m64;;
    659         esac
    660         if ! _bh_check_compiler_bitness ${HOST_FULLPREFIX}gcc $BH_HOST_BITS $TRY_CFLAGS; then
    661             panic "Can't find a way to generate $BH_HOST_BITS binaries with this compiler: ${HOST_FULLPREFIX}gcc"
    662         fi
    663         HOST_CFLAGS=$HOST_CFLAGS" "$TRY_CFLAGS
    664         HOST_CXXFLAGS=$HOST_CXXFLAGS" "$TRY_CFLAGS
    665     fi
    666 
    667     # Support for ccache, to speed up rebuilds.
    668     DST_PREFIX=$HOST_FULLPREFIX
    669     local CCACHE=
    670     if [ "$NDK_CCACHE" ]; then
    671         CCACHE="--ccache=$NDK_CCACHE"
    672     fi
    673 
    674     # We're going to generate a wrapper toolchain with the $HOST prefix
    675     # i.e. if $HOST is 'i686-linux-gnu', then we're going to generate a
    676     # wrapper toolchain named 'i686-linux-gnu-gcc' that will redirect
    677     # to whatever HOST_FULLPREFIX points to, with appropriate modifier
    678     # compiler/linker flags.
    679     #
    680     # This helps tremendously getting stuff to compile with the GCC
    681     # configure scripts.
    682     #
    683     run mkdir -p "$BH_WRAPPERS_DIR" &&
    684     run $NDK_BUILDTOOLS_PATH/gen-toolchain-wrapper.sh "$BH_WRAPPERS_DIR" \
    685         --src-prefix="$BH_HOST_CONFIG-" \
    686         --dst-prefix="$DST_PREFIX" \
    687         --cflags="$HOST_CFLAGS" \
    688         --cxxflags="$HOST_CXXFLAGS" \
    689         --ldflags="$HOST_LDFLAGS" \
    690         $CCACHE
    691 }
    692 
    693 
    694 # Setup the build directory, i.e. a directory where all intermediate
    695 # files will be placed.
    696 #
    697 # $1: Build directory. If empty, a random one will be selected.
    698 #
    699 # $2: Either 'preserve' or 'remove'. Indicates what to do of
    700 #     existing files in the build directory, if any.
    701 #
    702 # $3: Either 'release' or 'debug'. Compilation mode.
    703 #
    704 bh_setup_build_dir ()
    705 {
    706     BH_BUILD_DIR="$1"
    707     if [ -z "$BH_BUILD_DIR" ]; then
    708         BH_BUILD_DIR=/tmp/ndk-$USER/buildhost
    709     fi
    710     mkdir -p "$BH_BUILD_DIR"
    711     fail_panic "Could not create build directory: $BH_BUILD_DIR"
    712 
    713     setup_default_log_file $BH_BUILD_DIR/build.log
    714 
    715     if [ "$_BH_OPTION_FORCE" ]; then
    716         rm -rf "$BH_BUILD_DIR"/*
    717     fi
    718 
    719     if [ "$_BH_OPTION_NO_STRIP" ]; then
    720         BH_BUILD_MODE=debug
    721     else
    722         BH_BUILD_MODE=release
    723     fi
    724 
    725     # The directory that will contain our toolchain wrappers
    726     BH_WRAPPERS_DIR=$BH_BUILD_DIR/toolchain-wrappers
    727     rm -rf "$BH_WRAPPERS_DIR" && mkdir "$BH_WRAPPERS_DIR"
    728     fail_panic "Could not create wrappers dir: $BH_WRAPPERS_DIR"
    729 
    730     # The directory that will contain our timestamps
    731     BH_STAMPS_DIR=$BH_BUILD_DIR/timestamps
    732     mkdir -p "$BH_STAMPS_DIR"
    733     fail_panic "Could not create timestamps dir"
    734 }
    735 
    736 # Call this before anything else to setup a few important variables that are
    737 # used consistently to build any host-specific binaries.
    738 #
    739 # $1: Host system name (e.g. linux-x86), this is the name of the host system
    740 #     where the generated GCC binaries will run, not the current machine's
    741 #     type (this one is in $ORIGINAL_HOST_TAG instead).
    742 #
    743 bh_setup_build_for_host ()
    744 {
    745     local HOST_VARNAME=$(dashes_to_underscores $1)
    746     local HOST_VAR=_BH_HOST_${HOST_VARNAME}
    747 
    748     # Determine the host configuration triplet in $HOST
    749     bh_set_host_tag $1
    750 
    751     # Note: since _bh_select_toolchain_for_host can change the value of
    752     # $BH_HOST_CONFIG, we need to save it in a variable to later get the
    753     # correct one when this function is called again.
    754     if [ -z "$(var_value ${HOST_VAR}_SETUP)" ]; then
    755         _bh_select_toolchain_for_host $1
    756         var_assign ${HOST_VAR}_CONFIG $BH_HOST_CONFIG
    757         var_assign ${HOST_VAR}_SETUP true
    758     else
    759         BH_HOST_CONFIG=$(var_value ${HOST_VAR}_CONFIG)
    760     fi
    761 }
    762 
    763 # This function is used to setup the build environment whenever we
    764 # generate host-specific binaries. You should call it before invoking
    765 # a configure script or make.
    766 #
    767 # It assume sthat bh_setup_build_for_host was called with the right
    768 # host system tag and wrappers directory.
    769 #
    770 bh_setup_host_env ()
    771 {
    772     CC=$BH_HOST_CONFIG-gcc
    773     CXX=$BH_HOST_CONFIG-g++
    774     LD=$BH_HOST_CONFIG-ld
    775     AR=$BH_HOST_CONFIG-ar
    776     AS=$BH_HOST_CONFIG-as
    777     RANLIB=$BH_HOST_CONFIG-ranlib
    778     NM=$BH_HOST_CONFIG-nm
    779     STRIP=$BH_HOST_CONFIG-strip
    780     STRINGS=$BH_HOST_CONFIG-strings
    781     export CC CXX LD AR AS RANLIB NM STRIP STRINGS
    782 
    783     CFLAGS=
    784     CXXFLAGS=
    785     LDFLAGS=
    786     case $BH_BUILD_MODE in
    787         release)
    788             CFLAGS="-O2 -Os -fomit-frame-pointer -s"
    789             CXXFLAGS=$CFLAGS
    790             ;;
    791         debug)
    792             CFLAGS="-O0 -g"
    793             CXXFLAGS=$CFLAGS
    794             ;;
    795     esac
    796     export CFLAGS CXXFLAGS LDFLAGS
    797 
    798     PATH=$BH_WRAPPERS_DIR:$PATH
    799 }
    800 
    801 _bh_option_no_color ()
    802 {
    803     bh_set_color_mode off
    804 }
    805 
    806 # This function is used to register a few command-line options that
    807 # impact the build of host binaries. Call it before invoking
    808 # extract_parameters to add them automatically.
    809 #
    810 bh_register_options ()
    811 {
    812     BH_HOST_SYSTEMS="$BH_BUILD_TAG"
    813     register_var_option "--systems=<list>" BH_HOST_SYSTEMS "Build binaries that run on these systems."
    814 
    815     _BH_OPTION_FORCE=
    816     register_var_option "--force" _BH_OPTION_FORCE "Force rebuild."
    817 
    818     _BH_OPTION_NO_STRIP=
    819     register_var_option "--no-strip" _BH_OPTION_NO_STRIP "Don't strip generated binaries."
    820 
    821     register_option "--no-color" _bh_option_no_color "Don't output colored text."
    822 
    823     if [ "$HOST_OS" = darwin ]; then
    824         DARWIN_SDK_VERSION=
    825         register_var_option "--darwin-sdk-version=<version>" DARWIN_SDK "Select Darwin SDK version."
    826 
    827         DARWIN_MIN_VERSION=
    828         register_var_option "--darwin-min-version=<version>" DARWIN_MIN_VERSION "Select minimum OS X version of generated host toolchains."
    829     fi
    830 }
    831 
    832 # Execute a given command if the corresponding timestamp hasn't been touched
    833 #
    834 # NOTE: The command is run in its own sub-shell to avoid environment
    835 #        contamination.
    836 #
    837 # $1: timestamps name
    838 # $2+: command
    839 bh_stamps_do ()
    840 {
    841     local STAMP_NAME=$1
    842     shift
    843     if [ ! -f "$BH_STAMPS_DIR/$STAMP_NAME" ]; then
    844         ("$@")
    845         fail_panic
    846         mkdir -p "$BH_STAMPS_DIR" && touch "$BH_STAMPS_DIR/$STAMP_NAME"
    847     fi
    848 }
    849