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