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