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#
65BH_BUILD_OS=$HOST_OS
66BH_BUILD_ARCH=$HOST_ARCH
67BH_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)
72bh_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)
88bh_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)
106bh_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
120bh_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
142bh_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.
155bh_set_build_tag $HOST_TAG
156
157bh_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
169bh_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
181bh_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.
203bh_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'
228bh_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
249bh_set_color_mode true
250
251# Pretty printing with colors!
252bh_host_text ()
253{
254    printf "[${_BH_COLOR_GREEN}${BH_HOST_TAG}${_BH_COLOR_END}]"
255}
256
257bh_toolchain_text ()
258{
259    printf "[${_BH_COLOR_PURPLE}${BH_TOOLCHAIN}${_BH_COLOR_END}]"
260}
261
262bh_target_text ()
263{
264    printf "[${_BH_COLOR_CYAN}${BH_TARGET_TAG}${_BH_COLOR_END}]"
265}
266
267bh_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#
281bh_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
290int main(void) { return 0; }
291EOF
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 */
390int tab[1-2*(sizeof(void*)*8 != BITS)];
391EOF
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#
658bh_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#
697bh_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#
724bh_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#
764bh_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
792bh_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.
806python_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
815python_ndk_install_dir ()
816{
817    echo "host-tools"
818}
819