envsetup.sh revision f9631fd9db447a32135f4060a0d5b51bb799f2d4
1# These unsets should stay to clear the old functions from any long running
2# shells.
3# TODO(danalbert): Remove this in a day or so.
4unset -f gdbwrapper
5unset -f get_symbols_directory
6unset -f adb_get_product_device
7unset -f adb_get_traced_by
8unset -f gdbclient
9unset -f gdbclient_old
10
11function hmm() {
12cat <<EOF
13Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
14- lunch:   lunch <product_name>-<build_variant>
15- tapas:   tapas [<App1> <App2> ...] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
16- croot:   Changes directory to the top of the tree.
17- m:       Makes from the top of the tree.
18- mm:      Builds all of the modules in the current directory, but not their dependencies.
19- mmm:     Builds all of the modules in the supplied directories, but not their dependencies.
20           To limit the modules being built use the syntax: mmm dir/:target1,target2.
21- mma:     Builds all of the modules in the current directory, and their dependencies.
22- mmma:    Builds all of the modules in the supplied directories, and their dependencies.
23- cgrep:   Greps on all local C/C++ files.
24- ggrep:   Greps on all local Gradle files.
25- jgrep:   Greps on all local Java files.
26- resgrep: Greps on all local res/*.xml files.
27- mangrep: Greps on all local AndroidManifest.xml files.
28- sepgrep: Greps on all local sepolicy files.
29- sgrep:   Greps on all local source files.
30- godir:   Go to the directory containing a file.
31
32Environemnt options:
33- SANITIZE_HOST: Set to 'true' to use ASAN for all host modules. Note that
34                 ASAN_OPTIONS=detect_leaks=0 will be set by default until the
35                 build is leak-check clean.
36
37Look at the source to view more functions. The complete list is:
38EOF
39    T=$(gettop)
40    local A
41    A=""
42    for i in `cat $T/build/envsetup.sh | sed -n "/^[ \t]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
43      A="$A $i"
44    done
45    echo $A
46}
47
48# Get the value of a build variable as an absolute path.
49function get_abs_build_var()
50{
51    T=$(gettop)
52    if [ ! "$T" ]; then
53        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
54        return
55    fi
56    (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
57      command make --no-print-directory -f build/core/config.mk dumpvar-abs-$1)
58}
59
60# Get the exact value of a build variable.
61function get_build_var()
62{
63    T=$(gettop)
64    if [ ! "$T" ]; then
65        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
66        return
67    fi
68    (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
69      command make --no-print-directory -f build/core/config.mk dumpvar-$1)
70}
71
72# check to see if the supplied product is one we can build
73function check_product()
74{
75    T=$(gettop)
76    if [ ! "$T" ]; then
77        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
78        return
79    fi
80        TARGET_PRODUCT=$1 \
81        TARGET_BUILD_VARIANT= \
82        TARGET_BUILD_TYPE= \
83        TARGET_BUILD_APPS= \
84        get_build_var TARGET_DEVICE > /dev/null
85    # hide successful answers, but allow the errors to show
86}
87
88VARIANT_CHOICES=(user userdebug eng)
89
90# check to see if the supplied variant is valid
91function check_variant()
92{
93    for v in ${VARIANT_CHOICES[@]}
94    do
95        if [ "$v" = "$1" ]
96        then
97            return 0
98        fi
99    done
100    return 1
101}
102
103function setpaths()
104{
105    T=$(gettop)
106    if [ ! "$T" ]; then
107        echo "Couldn't locate the top of the tree.  Try setting TOP."
108        return
109    fi
110
111    ##################################################################
112    #                                                                #
113    #              Read me before you modify this code               #
114    #                                                                #
115    #   This function sets ANDROID_BUILD_PATHS to what it is adding  #
116    #   to PATH, and the next time it is run, it removes that from   #
117    #   PATH.  This is required so lunch can be run more than once   #
118    #   and still have working paths.                                #
119    #                                                                #
120    ##################################################################
121
122    # Note: on windows/cygwin, ANDROID_BUILD_PATHS will contain spaces
123    # due to "C:\Program Files" being in the path.
124
125    # out with the old
126    if [ -n "$ANDROID_BUILD_PATHS" ] ; then
127        export PATH=${PATH/$ANDROID_BUILD_PATHS/}
128    fi
129    if [ -n "$ANDROID_PRE_BUILD_PATHS" ] ; then
130        export PATH=${PATH/$ANDROID_PRE_BUILD_PATHS/}
131        # strip leading ':', if any
132        export PATH=${PATH/:%/}
133    fi
134
135    # and in with the new
136    prebuiltdir=$(getprebuilt)
137    gccprebuiltdir=$(get_abs_build_var ANDROID_GCC_PREBUILTS)
138
139    # defined in core/config.mk
140    targetgccversion=$(get_build_var TARGET_GCC_VERSION)
141    targetgccversion2=$(get_build_var 2ND_TARGET_GCC_VERSION)
142    export TARGET_GCC_VERSION=$targetgccversion
143
144    # The gcc toolchain does not exists for windows/cygwin. In this case, do not reference it.
145    export ANDROID_TOOLCHAIN=
146    export ANDROID_TOOLCHAIN_2ND_ARCH=
147    local ARCH=$(get_build_var TARGET_ARCH)
148    case $ARCH in
149        x86) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
150            ;;
151        x86_64) toolchaindir=x86/x86_64-linux-android-$targetgccversion/bin
152            ;;
153        arm) toolchaindir=arm/arm-linux-androideabi-$targetgccversion/bin
154            ;;
155        arm64) toolchaindir=aarch64/aarch64-linux-android-$targetgccversion/bin;
156               toolchaindir2=arm/arm-linux-androideabi-$targetgccversion2/bin
157            ;;
158        mips|mips64) toolchaindir=mips/mips64el-linux-android-$targetgccversion/bin
159            ;;
160        *)
161            echo "Can't find toolchain for unknown architecture: $ARCH"
162            toolchaindir=xxxxxxxxx
163            ;;
164    esac
165    if [ -d "$gccprebuiltdir/$toolchaindir" ]; then
166        export ANDROID_TOOLCHAIN=$gccprebuiltdir/$toolchaindir
167    fi
168
169    if [ -d "$gccprebuiltdir/$toolchaindir2" ]; then
170        export ANDROID_TOOLCHAIN_2ND_ARCH=$gccprebuiltdir/$toolchaindir2
171    fi
172
173    unset ANDROID_KERNEL_TOOLCHAIN_PATH
174    case $ARCH in
175        arm)
176            # Legacy toolchain configuration used for ARM kernel compilation
177            toolchaindir=arm/arm-eabi-$targetgccversion/bin
178            if [ -d "$gccprebuiltdir/$toolchaindir" ]; then
179                 export ARM_EABI_TOOLCHAIN="$gccprebuiltdir/$toolchaindir"
180                 ANDROID_KERNEL_TOOLCHAIN_PATH="$ARM_EABI_TOOLCHAIN":
181            fi
182            ;;
183        *)
184            # No need to set ARM_EABI_TOOLCHAIN for other ARCHs
185            ;;
186    esac
187
188    export ANDROID_DEV_SCRIPTS=$T/development/scripts:$T/prebuilts/devtools/tools
189    export ANDROID_BUILD_PATHS=$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_TOOLCHAIN:$ANDROID_TOOLCHAIN_2ND_ARCH:$ANDROID_KERNEL_TOOLCHAIN_PATH$ANDROID_DEV_SCRIPTS:
190
191    # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH
192    # to ensure that the corresponding 'emulator' binaries are used.
193    case $(uname -s) in
194        Darwin)
195            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/darwin-x86_64
196            ;;
197        Linux)
198            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/linux-x86_64
199            ;;
200        *)
201            ANDROID_EMULATOR_PREBUILTS=
202            ;;
203    esac
204    if [ -n "$ANDROID_EMULATOR_PREBUILTS" -a -d "$ANDROID_EMULATOR_PREBUILTS" ]; then
205        ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS$ANDROID_EMULATOR_PREBUILTS:
206        export ANDROID_EMULATOR_PREBUILTS
207    fi
208
209    export PATH=$ANDROID_BUILD_PATHS$PATH
210
211    unset ANDROID_JAVA_TOOLCHAIN
212    unset ANDROID_PRE_BUILD_PATHS
213    if [ -n "$JAVA_HOME" ]; then
214        export ANDROID_JAVA_TOOLCHAIN=$JAVA_HOME/bin
215        export ANDROID_PRE_BUILD_PATHS=$ANDROID_JAVA_TOOLCHAIN:
216        export PATH=$ANDROID_PRE_BUILD_PATHS$PATH
217    fi
218
219    unset ANDROID_PRODUCT_OUT
220    export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)
221    export OUT=$ANDROID_PRODUCT_OUT
222
223    unset ANDROID_HOST_OUT
224    export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
225
226    # needed for building linux on MacOS
227    # TODO: fix the path
228    #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include
229}
230
231function printconfig()
232{
233    T=$(gettop)
234    if [ ! "$T" ]; then
235        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
236        return
237    fi
238    get_build_var report_config
239}
240
241function set_stuff_for_environment()
242{
243    settitle
244    set_java_home
245    setpaths
246    set_sequence_number
247
248    export ANDROID_BUILD_TOP=$(gettop)
249    # With this environment variable new GCC can apply colors to warnings/errors
250    export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
251    export ASAN_OPTIONS=detect_leaks=0
252}
253
254function set_sequence_number()
255{
256    export BUILD_ENV_SEQUENCE_NUMBER=10
257}
258
259function settitle()
260{
261    if [ "$STAY_OFF_MY_LAWN" = "" ]; then
262        local arch=$(gettargetarch)
263        local product=$TARGET_PRODUCT
264        local variant=$TARGET_BUILD_VARIANT
265        local apps=$TARGET_BUILD_APPS
266        if [ -z "$apps" ]; then
267            export PROMPT_COMMAND="echo -ne \"\033]0;[${arch}-${product}-${variant}] ${USER}@${HOSTNAME}: ${PWD}\007\""
268        else
269            export PROMPT_COMMAND="echo -ne \"\033]0;[$arch $apps $variant] ${USER}@${HOSTNAME}: ${PWD}\007\""
270        fi
271    fi
272}
273
274function addcompletions()
275{
276    local T dir f
277
278    # Keep us from trying to run in something that isn't bash.
279    if [ -z "${BASH_VERSION}" ]; then
280        return
281    fi
282
283    # Keep us from trying to run in bash that's too old.
284    if [ ${BASH_VERSINFO[0]} -lt 3 ]; then
285        return
286    fi
287
288    dir="sdk/bash_completion"
289    if [ -d ${dir} ]; then
290        for f in `/bin/ls ${dir}/[a-z]*.bash 2> /dev/null`; do
291            echo "including $f"
292            . $f
293        done
294    fi
295}
296
297function choosetype()
298{
299    echo "Build type choices are:"
300    echo "     1. release"
301    echo "     2. debug"
302    echo
303
304    local DEFAULT_NUM DEFAULT_VALUE
305    DEFAULT_NUM=1
306    DEFAULT_VALUE=release
307
308    export TARGET_BUILD_TYPE=
309    local ANSWER
310    while [ -z $TARGET_BUILD_TYPE ]
311    do
312        echo -n "Which would you like? ["$DEFAULT_NUM"] "
313        if [ -z "$1" ] ; then
314            read ANSWER
315        else
316            echo $1
317            ANSWER=$1
318        fi
319        case $ANSWER in
320        "")
321            export TARGET_BUILD_TYPE=$DEFAULT_VALUE
322            ;;
323        1)
324            export TARGET_BUILD_TYPE=release
325            ;;
326        release)
327            export TARGET_BUILD_TYPE=release
328            ;;
329        2)
330            export TARGET_BUILD_TYPE=debug
331            ;;
332        debug)
333            export TARGET_BUILD_TYPE=debug
334            ;;
335        *)
336            echo
337            echo "I didn't understand your response.  Please try again."
338            echo
339            ;;
340        esac
341        if [ -n "$1" ] ; then
342            break
343        fi
344    done
345
346    set_stuff_for_environment
347}
348
349#
350# This function isn't really right:  It chooses a TARGET_PRODUCT
351# based on the list of boards.  Usually, that gets you something
352# that kinda works with a generic product, but really, you should
353# pick a product by name.
354#
355function chooseproduct()
356{
357    if [ "x$TARGET_PRODUCT" != x ] ; then
358        default_value=$TARGET_PRODUCT
359    else
360        default_value=full
361    fi
362
363    export TARGET_PRODUCT=
364    local ANSWER
365    while [ -z "$TARGET_PRODUCT" ]
366    do
367        echo -n "Which product would you like? [$default_value] "
368        if [ -z "$1" ] ; then
369            read ANSWER
370        else
371            echo $1
372            ANSWER=$1
373        fi
374
375        if [ -z "$ANSWER" ] ; then
376            export TARGET_PRODUCT=$default_value
377        else
378            if check_product $ANSWER
379            then
380                export TARGET_PRODUCT=$ANSWER
381            else
382                echo "** Not a valid product: $ANSWER"
383            fi
384        fi
385        if [ -n "$1" ] ; then
386            break
387        fi
388    done
389
390    set_stuff_for_environment
391}
392
393function choosevariant()
394{
395    echo "Variant choices are:"
396    local index=1
397    local v
398    for v in ${VARIANT_CHOICES[@]}
399    do
400        # The product name is the name of the directory containing
401        # the makefile we found, above.
402        echo "     $index. $v"
403        index=$(($index+1))
404    done
405
406    local default_value=eng
407    local ANSWER
408
409    export TARGET_BUILD_VARIANT=
410    while [ -z "$TARGET_BUILD_VARIANT" ]
411    do
412        echo -n "Which would you like? [$default_value] "
413        if [ -z "$1" ] ; then
414            read ANSWER
415        else
416            echo $1
417            ANSWER=$1
418        fi
419
420        if [ -z "$ANSWER" ] ; then
421            export TARGET_BUILD_VARIANT=$default_value
422        elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$") ; then
423            if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ] ; then
424                export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[$(($ANSWER-1))]}
425            fi
426        else
427            if check_variant $ANSWER
428            then
429                export TARGET_BUILD_VARIANT=$ANSWER
430            else
431                echo "** Not a valid variant: $ANSWER"
432            fi
433        fi
434        if [ -n "$1" ] ; then
435            break
436        fi
437    done
438}
439
440function choosecombo()
441{
442    choosetype $1
443
444    echo
445    echo
446    chooseproduct $2
447
448    echo
449    echo
450    choosevariant $3
451
452    echo
453    set_stuff_for_environment
454    printconfig
455}
456
457# Clear this variable.  It will be built up again when the vendorsetup.sh
458# files are included at the end of this file.
459unset LUNCH_MENU_CHOICES
460function add_lunch_combo()
461{
462    local new_combo=$1
463    local c
464    for c in ${LUNCH_MENU_CHOICES[@]} ; do
465        if [ "$new_combo" = "$c" ] ; then
466            return
467        fi
468    done
469    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
470}
471
472# add the default one here
473add_lunch_combo aosp_arm-eng
474add_lunch_combo aosp_arm64-eng
475add_lunch_combo aosp_mips-eng
476add_lunch_combo aosp_mips64-eng
477add_lunch_combo aosp_x86-eng
478add_lunch_combo aosp_x86_64-eng
479
480function print_lunch_menu()
481{
482    local uname=$(uname)
483    echo
484    echo "You're building on" $uname
485    echo
486    echo "Lunch menu... pick a combo:"
487
488    local i=1
489    local choice
490    for choice in ${LUNCH_MENU_CHOICES[@]}
491    do
492        echo "     $i. $choice"
493        i=$(($i+1))
494    done
495
496    echo
497}
498
499function lunch()
500{
501    local answer
502
503    if [ "$1" ] ; then
504        answer=$1
505    else
506        print_lunch_menu
507        echo -n "Which would you like? [aosp_arm-eng] "
508        read answer
509    fi
510
511    local selection=
512
513    if [ -z "$answer" ]
514    then
515        selection=aosp_arm-eng
516    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
517    then
518        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
519        then
520            selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
521        fi
522    elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
523    then
524        selection=$answer
525    fi
526
527    if [ -z "$selection" ]
528    then
529        echo
530        echo "Invalid lunch combo: $answer"
531        return 1
532    fi
533
534    export TARGET_BUILD_APPS=
535
536    local product=$(echo -n $selection | sed -e "s/-.*$//")
537    check_product $product
538    if [ $? -ne 0 ]
539    then
540        echo
541        echo "** Don't have a product spec for: '$product'"
542        echo "** Do you have the right repo manifest?"
543        product=
544    fi
545
546    local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
547    check_variant $variant
548    if [ $? -ne 0 ]
549    then
550        echo
551        echo "** Invalid variant: '$variant'"
552        echo "** Must be one of ${VARIANT_CHOICES[@]}"
553        variant=
554    fi
555
556    if [ -z "$product" -o -z "$variant" ]
557    then
558        echo
559        return 1
560    fi
561
562    export TARGET_PRODUCT=$product
563    export TARGET_BUILD_VARIANT=$variant
564    export TARGET_BUILD_TYPE=release
565
566    echo
567
568    set_stuff_for_environment
569    printconfig
570}
571
572# Tab completion for lunch.
573function _lunch()
574{
575    local cur prev opts
576    COMPREPLY=()
577    cur="${COMP_WORDS[COMP_CWORD]}"
578    prev="${COMP_WORDS[COMP_CWORD-1]}"
579
580    COMPREPLY=( $(compgen -W "${LUNCH_MENU_CHOICES[*]}" -- ${cur}) )
581    return 0
582}
583complete -F _lunch lunch
584
585# Configures the build to build unbundled apps.
586# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
587function tapas()
588{
589    local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5|arm64|x86_64|mips64)$' | xargs)"
590    local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
591    local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|armv5|arm64|x86_64|mips64)$' | xargs)"
592
593    if [ $(echo $arch | wc -w) -gt 1 ]; then
594        echo "tapas: Error: Multiple build archs supplied: $arch"
595        return
596    fi
597    if [ $(echo $variant | wc -w) -gt 1 ]; then
598        echo "tapas: Error: Multiple build variants supplied: $variant"
599        return
600    fi
601
602    local product=full
603    case $arch in
604      x86)    product=full_x86;;
605      mips)   product=full_mips;;
606      armv5)  product=generic_armv5;;
607      arm64)  product=aosp_arm64;;
608      x86_64) product=aosp_x86_64;;
609      mips64)  product=aosp_mips64;;
610    esac
611    if [ -z "$variant" ]; then
612        variant=eng
613    fi
614    if [ -z "$apps" ]; then
615        apps=all
616    fi
617
618    export TARGET_PRODUCT=$product
619    export TARGET_BUILD_VARIANT=$variant
620    export TARGET_BUILD_TYPE=release
621    export TARGET_BUILD_APPS=$apps
622
623    set_stuff_for_environment
624    printconfig
625}
626
627function gettop
628{
629    local TOPFILE=build/core/envsetup.mk
630    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
631        # The following circumlocution ensures we remove symlinks from TOP.
632        (cd $TOP; PWD= /bin/pwd)
633    else
634        if [ -f $TOPFILE ] ; then
635            # The following circumlocution (repeated below as well) ensures
636            # that we record the true directory name and not one that is
637            # faked up with symlink names.
638            PWD= /bin/pwd
639        else
640            local HERE=$PWD
641            T=
642            while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
643                \cd ..
644                T=`PWD= /bin/pwd -P`
645            done
646            \cd $HERE
647            if [ -f "$T/$TOPFILE" ]; then
648                echo $T
649            fi
650        fi
651    fi
652}
653
654# Return driver for "make", if any (eg. static analyzer)
655function getdriver()
656{
657    local T="$1"
658    test "$WITH_STATIC_ANALYZER" = "0" && unset WITH_STATIC_ANALYZER
659    if [ -n "$WITH_STATIC_ANALYZER" ]; then
660        echo "\
661$T/prebuilts/misc/linux-x86/analyzer/tools/scan-build/scan-build \
662--use-analyzer $T/prebuilts/misc/linux-x86/analyzer/bin/analyzer \
663--status-bugs \
664--top=$T"
665    fi
666}
667
668function m()
669{
670    local T=$(gettop)
671    local DRV=$(getdriver $T)
672    if [ "$T" ]; then
673        $DRV make -C $T -f build/core/main.mk $@
674    else
675        echo "Couldn't locate the top of the tree.  Try setting TOP."
676    fi
677}
678
679function findmakefile()
680{
681    TOPFILE=build/core/envsetup.mk
682    local HERE=$PWD
683    T=
684    while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
685        T=`PWD= /bin/pwd`
686        if [ -f "$T/Android.mk" ]; then
687            echo $T/Android.mk
688            \cd $HERE
689            return
690        fi
691        \cd ..
692    done
693    \cd $HERE
694}
695
696function mm()
697{
698    local T=$(gettop)
699    local DRV=$(getdriver $T)
700    # If we're sitting in the root of the build tree, just do a
701    # normal make.
702    if [ -f build/core/envsetup.mk -a -f Makefile ]; then
703        $DRV make $@
704    else
705        # Find the closest Android.mk file.
706        local M=$(findmakefile)
707        local MODULES=
708        local GET_INSTALL_PATH=
709        local ARGS=
710        # Remove the path to top as the makefilepath needs to be relative
711        local M=`echo $M|sed 's:'$T'/::'`
712        if [ ! "$T" ]; then
713            echo "Couldn't locate the top of the tree.  Try setting TOP."
714        elif [ ! "$M" ]; then
715            echo "Couldn't locate a makefile from the current directory."
716        else
717            for ARG in $@; do
718                case $ARG in
719                  GET-INSTALL-PATH) GET_INSTALL_PATH=$ARG;;
720                esac
721            done
722            if [ -n "$GET_INSTALL_PATH" ]; then
723              MODULES=
724              ARGS=GET-INSTALL-PATH
725            else
726              MODULES=all_modules
727              ARGS=$@
728            fi
729            ONE_SHOT_MAKEFILE=$M $DRV make -C $T -f build/core/main.mk $MODULES $ARGS
730        fi
731    fi
732}
733
734function mmm()
735{
736    local T=$(gettop)
737    local DRV=$(getdriver $T)
738    if [ "$T" ]; then
739        local MAKEFILE=
740        local MODULES=
741        local ARGS=
742        local DIR TO_CHOP
743        local GET_INSTALL_PATH=
744        local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
745        local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
746        for DIR in $DIRS ; do
747            MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'`
748            if [ "$MODULES" = "" ]; then
749                MODULES=all_modules
750            fi
751            DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'`
752            if [ -f $DIR/Android.mk ]; then
753                local TO_CHOP=`(\cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
754                local TO_CHOP=`expr $TO_CHOP + 1`
755                local START=`PWD= /bin/pwd`
756                local MFILE=`echo $START | cut -c${TO_CHOP}-`
757                if [ "$MFILE" = "" ] ; then
758                    MFILE=$DIR/Android.mk
759                else
760                    MFILE=$MFILE/$DIR/Android.mk
761                fi
762                MAKEFILE="$MAKEFILE $MFILE"
763            else
764                case $DIR in
765                  showcommands | snod | dist | incrementaljavac) ARGS="$ARGS $DIR";;
766                  GET-INSTALL-PATH) GET_INSTALL_PATH=$DIR;;
767                  *) echo "No Android.mk in $DIR."; return 1;;
768                esac
769            fi
770        done
771        if [ -n "$GET_INSTALL_PATH" ]; then
772          ARGS=$GET_INSTALL_PATH
773          MODULES=
774        fi
775        ONE_SHOT_MAKEFILE="$MAKEFILE" $DRV make -C $T -f build/core/main.mk $DASH_ARGS $MODULES $ARGS
776    else
777        echo "Couldn't locate the top of the tree.  Try setting TOP."
778    fi
779}
780
781function mma()
782{
783  local T=$(gettop)
784  local DRV=$(getdriver $T)
785  if [ -f build/core/envsetup.mk -a -f Makefile ]; then
786    $DRV make $@
787  else
788    if [ ! "$T" ]; then
789      echo "Couldn't locate the top of the tree.  Try setting TOP."
790    fi
791    local MY_PWD=`PWD= /bin/pwd|sed 's:'$T'/::'`
792    $DRV make -C $T -f build/core/main.mk $@ all_modules BUILD_MODULES_IN_PATHS="$MY_PWD"
793  fi
794}
795
796function mmma()
797{
798  local T=$(gettop)
799  local DRV=$(getdriver $T)
800  if [ "$T" ]; then
801    local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
802    local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
803    local MY_PWD=`PWD= /bin/pwd`
804    if [ "$MY_PWD" = "$T" ]; then
805      MY_PWD=
806    else
807      MY_PWD=`echo $MY_PWD|sed 's:'$T'/::'`
808    fi
809    local DIR=
810    local MODULE_PATHS=
811    local ARGS=
812    for DIR in $DIRS ; do
813      if [ -d $DIR ]; then
814        if [ "$MY_PWD" = "" ]; then
815          MODULE_PATHS="$MODULE_PATHS $DIR"
816        else
817          MODULE_PATHS="$MODULE_PATHS $MY_PWD/$DIR"
818        fi
819      else
820        case $DIR in
821          showcommands | snod | dist | incrementaljavac) ARGS="$ARGS $DIR";;
822          *) echo "Couldn't find directory $DIR"; return 1;;
823        esac
824      fi
825    done
826    $DRV make -C $T -f build/core/main.mk $DASH_ARGS $ARGS all_modules BUILD_MODULES_IN_PATHS="$MODULE_PATHS"
827  else
828    echo "Couldn't locate the top of the tree.  Try setting TOP."
829  fi
830}
831
832function croot()
833{
834    T=$(gettop)
835    if [ "$T" ]; then
836        \cd $(gettop)
837    else
838        echo "Couldn't locate the top of the tree.  Try setting TOP."
839    fi
840}
841
842function cproj()
843{
844    TOPFILE=build/core/envsetup.mk
845    local HERE=$PWD
846    T=
847    while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
848        T=$PWD
849        if [ -f "$T/Android.mk" ]; then
850            \cd $T
851            return
852        fi
853        \cd ..
854    done
855    \cd $HERE
856    echo "can't find Android.mk"
857}
858
859# simplified version of ps; output in the form
860# <pid> <procname>
861function qpid() {
862    local prepend=''
863    local append=''
864    if [ "$1" = "--exact" ]; then
865        prepend=' '
866        append='$'
867        shift
868    elif [ "$1" = "--help" -o "$1" = "-h" ]; then
869		echo "usage: qpid [[--exact] <process name|pid>"
870		return 255
871	fi
872
873    local EXE="$1"
874    if [ "$EXE" ] ; then
875		qpid | \grep "$prepend$EXE$append"
876	else
877		adb shell ps \
878			| tr -d '\r' \
879			| sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'
880	fi
881}
882
883function pid()
884{
885    local prepend=''
886    local append=''
887    if [ "$1" = "--exact" ]; then
888        prepend=' '
889        append='$'
890        shift
891    fi
892    local EXE="$1"
893    if [ "$EXE" ] ; then
894        local PID=`adb shell ps \
895            | tr -d '\r' \
896            | \grep "$prepend$EXE$append" \
897            | sed -e 's/^[^ ]* *\([0-9]*\).*$/\1/'`
898        echo "$PID"
899    else
900        echo "usage: pid [--exact] <process name>"
901		return 255
902    fi
903}
904
905# systemstack - dump the current stack trace of all threads in the system process
906# to the usual ANR traces file
907function systemstack()
908{
909    stacks system_server
910}
911
912function stacks()
913{
914    if [[ $1 =~ ^[0-9]+$ ]] ; then
915        local PID="$1"
916    elif [ "$1" ] ; then
917        local PIDLIST="$(pid $1)"
918        if [[ $PIDLIST =~ ^[0-9]+$ ]] ; then
919            local PID="$PIDLIST"
920        elif [ "$PIDLIST" ] ; then
921            echo "more than one process: $1"
922        else
923            echo "no such process: $1"
924        fi
925    else
926        echo "usage: stacks [pid|process name]"
927    fi
928
929    if [ "$PID" ] ; then
930        # Determine whether the process is native
931        if adb shell ls -l /proc/$PID/exe | grep -q /system/bin/app_process ; then
932            # Dump stacks of Dalvik process
933            local TRACES=/data/anr/traces.txt
934            local ORIG=/data/anr/traces.orig
935            local TMP=/data/anr/traces.tmp
936
937            # Keep original traces to avoid clobbering
938            adb shell mv $TRACES $ORIG
939
940            # Make sure we have a usable file
941            adb shell touch $TRACES
942            adb shell chmod 666 $TRACES
943
944            # Dump stacks and wait for dump to finish
945            adb shell kill -3 $PID
946            adb shell notify $TRACES >/dev/null
947
948            # Restore original stacks, and show current output
949            adb shell mv $TRACES $TMP
950            adb shell mv $ORIG $TRACES
951            adb shell cat $TMP
952        else
953            # Dump stacks of native process
954            local USE64BIT="$(is64bit $PID)"
955            adb shell debuggerd$USE64BIT -b $PID
956        fi
957    fi
958}
959
960# Read the ELF header from /proc/$PID/exe to determine if the process is
961# 64-bit.
962function is64bit()
963{
964    local PID="$1"
965    if [ "$PID" ] ; then
966        if [[ "$(adb shell cat /proc/$PID/exe | xxd -l 1 -s 4 -ps)" -eq "02" ]] ; then
967            echo "64"
968        else
969            echo ""
970        fi
971    else
972        echo ""
973    fi
974}
975
976case `uname -s` in
977    Darwin)
978        function sgrep()
979        {
980            find -E . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.(c|h|cc|cpp|S|java|xml|sh|mk|aidl)' -print0 | xargs -0 grep --color -n "$@"
981        }
982
983        ;;
984    *)
985        function sgrep()
986        {
987            find . -name .repo -prune -o -name .git -prune -o  -type f -iregex '.*\.\(c\|h\|cc\|cpp\|S\|java\|xml\|sh\|mk\|aidl\)' -print0 | xargs -0 grep --color -n "$@"
988        }
989        ;;
990esac
991
992function gettargetarch
993{
994    get_build_var TARGET_ARCH
995}
996
997function ggrep()
998{
999    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.gradle" -print0 | xargs -0 grep --color -n "$@"
1000}
1001
1002function jgrep()
1003{
1004    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.java" -print0 | xargs -0 grep --color -n "$@"
1005}
1006
1007function cgrep()
1008{
1009    find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) -print0 | xargs -0 grep --color -n "$@"
1010}
1011
1012function resgrep()
1013{
1014    for dir in `find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -name res -type d`; do find $dir -type f -name '*\.xml' -print0 | xargs -0 grep --color -n "$@"; done;
1015}
1016
1017function mangrep()
1018{
1019    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'AndroidManifest.xml' -print0 | xargs -0 grep --color -n "$@"
1020}
1021
1022function sepgrep()
1023{
1024    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -name sepolicy -type d -print0 | xargs -0 grep --color -n -r --exclude-dir=\.git "$@"
1025}
1026
1027case `uname -s` in
1028    Darwin)
1029        function mgrep()
1030        {
1031            find -E . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -print0 | xargs -0 grep --color -n "$@"
1032        }
1033
1034        function treegrep()
1035        {
1036            find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cpp|S|java|xml)' -print0 | xargs -0 grep --color -n -i "$@"
1037        }
1038
1039        ;;
1040    *)
1041        function mgrep()
1042        {
1043            find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -type f -print0 | xargs -0 grep --color -n "$@"
1044        }
1045
1046        function treegrep()
1047        {
1048            find . -name .repo -prune -o -name .git -prune -o -regextype posix-egrep -iregex '.*\.(c|h|cpp|S|java|xml)' -type f -print0 | xargs -0 grep --color -n -i "$@"
1049        }
1050
1051        ;;
1052esac
1053
1054function getprebuilt
1055{
1056    get_abs_build_var ANDROID_PREBUILTS
1057}
1058
1059function tracedmdump()
1060{
1061    T=$(gettop)
1062    if [ ! "$T" ]; then
1063        echo "Couldn't locate the top of the tree.  Try setting TOP."
1064        return
1065    fi
1066    local prebuiltdir=$(getprebuilt)
1067    local arch=$(gettargetarch)
1068    local KERNEL=$T/prebuilts/qemu-kernel/$arch/vmlinux-qemu
1069
1070    local TRACE=$1
1071    if [ ! "$TRACE" ] ; then
1072        echo "usage:  tracedmdump  tracename"
1073        return
1074    fi
1075
1076    if [ ! -r "$KERNEL" ] ; then
1077        echo "Error: cannot find kernel: '$KERNEL'"
1078        return
1079    fi
1080
1081    local BASETRACE=$(basename $TRACE)
1082    if [ "$BASETRACE" = "$TRACE" ] ; then
1083        TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
1084    fi
1085
1086    echo "post-processing traces..."
1087    rm -f $TRACE/qtrace.dexlist
1088    post_trace $TRACE
1089    if [ $? -ne 0 ]; then
1090        echo "***"
1091        echo "*** Error: malformed trace.  Did you remember to exit the emulator?"
1092        echo "***"
1093        return
1094    fi
1095    echo "generating dexlist output..."
1096    /bin/ls $ANDROID_PRODUCT_OUT/system/framework/*.jar $ANDROID_PRODUCT_OUT/system/app/*.apk $ANDROID_PRODUCT_OUT/data/app/*.apk 2>/dev/null | xargs dexlist > $TRACE/qtrace.dexlist
1097    echo "generating dmtrace data..."
1098    q2dm -r $ANDROID_PRODUCT_OUT/symbols $TRACE $KERNEL $TRACE/dmtrace || return
1099    echo "generating html file..."
1100    dmtracedump -h $TRACE/dmtrace >| $TRACE/dmtrace.html || return
1101    echo "done, see $TRACE/dmtrace.html for details"
1102    echo "or run:"
1103    echo "    traceview $TRACE/dmtrace"
1104}
1105
1106# communicate with a running device or emulator, set up necessary state,
1107# and run the hat command.
1108function runhat()
1109{
1110    # process standard adb options
1111    local adbTarget=""
1112    if [ "$1" = "-d" -o "$1" = "-e" ]; then
1113        adbTarget=$1
1114        shift 1
1115    elif [ "$1" = "-s" ]; then
1116        adbTarget="$1 $2"
1117        shift 2
1118    fi
1119    local adbOptions=${adbTarget}
1120    #echo adbOptions = ${adbOptions}
1121
1122    # runhat options
1123    local targetPid=$1
1124
1125    if [ "$targetPid" = "" ]; then
1126        echo "Usage: runhat [ -d | -e | -s serial ] target-pid"
1127        return
1128    fi
1129
1130    # confirm hat is available
1131    if [ -z $(which hat) ]; then
1132        echo "hat is not available in this configuration."
1133        return
1134    fi
1135
1136    # issue "am" command to cause the hprof dump
1137    local devFile=/data/local/tmp/hprof-$targetPid
1138    echo "Poking $targetPid and waiting for data..."
1139    echo "Storing data at $devFile"
1140    adb ${adbOptions} shell am dumpheap $targetPid $devFile
1141    echo "Press enter when logcat shows \"hprof: heap dump completed\""
1142    echo -n "> "
1143    read
1144
1145    local localFile=/tmp/$$-hprof
1146
1147    echo "Retrieving file $devFile..."
1148    adb ${adbOptions} pull $devFile $localFile
1149
1150    adb ${adbOptions} shell rm $devFile
1151
1152    echo "Running hat on $localFile"
1153    echo "View the output by pointing your browser at http://localhost:7000/"
1154    echo ""
1155    hat -JXmx512m $localFile
1156}
1157
1158function getbugreports()
1159{
1160    local reports=(`adb shell ls /sdcard/bugreports | tr -d '\r'`)
1161
1162    if [ ! "$reports" ]; then
1163        echo "Could not locate any bugreports."
1164        return
1165    fi
1166
1167    local report
1168    for report in ${reports[@]}
1169    do
1170        echo "/sdcard/bugreports/${report}"
1171        adb pull /sdcard/bugreports/${report} ${report}
1172        gunzip ${report}
1173    done
1174}
1175
1176function getsdcardpath()
1177{
1178    adb ${adbOptions} shell echo -n \$\{EXTERNAL_STORAGE\}
1179}
1180
1181function getscreenshotpath()
1182{
1183    echo "$(getsdcardpath)/Pictures/Screenshots"
1184}
1185
1186function getlastscreenshot()
1187{
1188    local screenshot_path=$(getscreenshotpath)
1189    local screenshot=`adb ${adbOptions} ls ${screenshot_path} | grep Screenshot_[0-9-]*.*\.png | sort -rk 3 | cut -d " " -f 4 | head -n 1`
1190    if [ "$screenshot" = "" ]; then
1191        echo "No screenshots found."
1192        return
1193    fi
1194    echo "${screenshot}"
1195    adb ${adbOptions} pull ${screenshot_path}/${screenshot}
1196}
1197
1198function startviewserver()
1199{
1200    local port=4939
1201    if [ $# -gt 0 ]; then
1202            port=$1
1203    fi
1204    adb shell service call window 1 i32 $port
1205}
1206
1207function stopviewserver()
1208{
1209    adb shell service call window 2
1210}
1211
1212function isviewserverstarted()
1213{
1214    adb shell service call window 3
1215}
1216
1217function key_home()
1218{
1219    adb shell input keyevent 3
1220}
1221
1222function key_back()
1223{
1224    adb shell input keyevent 4
1225}
1226
1227function key_menu()
1228{
1229    adb shell input keyevent 82
1230}
1231
1232function smoketest()
1233{
1234    if [ ! "$ANDROID_PRODUCT_OUT" ]; then
1235        echo "Couldn't locate output files.  Try running 'lunch' first." >&2
1236        return
1237    fi
1238    T=$(gettop)
1239    if [ ! "$T" ]; then
1240        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1241        return
1242    fi
1243
1244    (\cd "$T" && mmm tests/SmokeTest) &&
1245      adb uninstall com.android.smoketest > /dev/null &&
1246      adb uninstall com.android.smoketest.tests > /dev/null &&
1247      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk &&
1248      adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTest.apk &&
1249      adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner
1250}
1251
1252# simple shortcut to the runtest command
1253function runtest()
1254{
1255    T=$(gettop)
1256    if [ ! "$T" ]; then
1257        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
1258        return
1259    fi
1260    ("$T"/development/testrunner/runtest.py $@)
1261}
1262
1263function godir () {
1264    if [[ -z "$1" ]]; then
1265        echo "Usage: godir <regex>"
1266        return
1267    fi
1268    T=$(gettop)
1269    if [[ ! -f $T/filelist ]]; then
1270        echo -n "Creating index..."
1271        (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > filelist)
1272        echo " Done"
1273        echo ""
1274    fi
1275    local lines
1276    lines=($(\grep "$1" $T/filelist | sed -e 's/\/[^/]*$//' | sort | uniq))
1277    if [[ ${#lines[@]} = 0 ]]; then
1278        echo "Not found"
1279        return
1280    fi
1281    local pathname
1282    local choice
1283    if [[ ${#lines[@]} > 1 ]]; then
1284        while [[ -z "$pathname" ]]; do
1285            local index=1
1286            local line
1287            for line in ${lines[@]}; do
1288                printf "%6s %s\n" "[$index]" $line
1289                index=$(($index + 1))
1290            done
1291            echo
1292            echo -n "Select one: "
1293            unset choice
1294            read choice
1295            if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then
1296                echo "Invalid choice"
1297                continue
1298            fi
1299            pathname=${lines[$(($choice-1))]}
1300        done
1301    else
1302        pathname=${lines[0]}
1303    fi
1304    \cd $T/$pathname
1305}
1306
1307# Force JAVA_HOME to point to java 1.7 if it isn't already set.
1308#
1309# Note that the MacOS path for java 1.7 includes a minor revision number (sigh).
1310# For some reason, installing the JDK doesn't make it show up in the
1311# JavaVM.framework/Versions/1.7/ folder.
1312function set_java_home() {
1313    # Clear the existing JAVA_HOME value if we set it ourselves, so that
1314    # we can reset it later, depending on the version of java the build
1315    # system needs.
1316    #
1317    # If we don't do this, the JAVA_HOME value set by the first call to
1318    # build/envsetup.sh will persist forever.
1319    if [ -n "$ANDROID_SET_JAVA_HOME" ]; then
1320      export JAVA_HOME=""
1321    fi
1322
1323    if [ ! "$JAVA_HOME" ]; then
1324      case `uname -s` in
1325          Darwin)
1326              export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
1327              ;;
1328          *)
1329              export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
1330              ;;
1331      esac
1332
1333      # Keep track of the fact that we set JAVA_HOME ourselves, so that
1334      # we can change it on the next envsetup.sh, if required.
1335      export ANDROID_SET_JAVA_HOME=true
1336    fi
1337}
1338
1339# Print colored exit condition
1340function pez {
1341    "$@"
1342    local retval=$?
1343    if [ $retval -ne 0 ]
1344    then
1345        echo -e "\e[0;31mFAILURE\e[00m"
1346    else
1347        echo -e "\e[0;32mSUCCESS\e[00m"
1348    fi
1349    return $retval
1350}
1351
1352function get_make_command()
1353{
1354  echo command make
1355}
1356
1357function make()
1358{
1359    local start_time=$(date +"%s")
1360    $(get_make_command) "$@"
1361    local ret=$?
1362    local end_time=$(date +"%s")
1363    local tdiff=$(($end_time-$start_time))
1364    local hours=$(($tdiff / 3600 ))
1365    local mins=$((($tdiff % 3600) / 60))
1366    local secs=$(($tdiff % 60))
1367    echo
1368    if [ $ret -eq 0 ] ; then
1369        if [ $(uname) != "Darwin" ]; then
1370            echo -n -e "\e[0;32m#### make completed successfully "
1371        else
1372            echo -n -e "#### make completed successfully "
1373        fi
1374    else
1375        if [ $(uname) != "Darwin" ]; then
1376            echo -n -e "\e[0;31m#### make failed to build some targets "
1377        else
1378            echo -n -e "#### make failed to build some targets "
1379        fi
1380    fi
1381    if [ $hours -gt 0 ] ; then
1382        printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs
1383    elif [ $mins -gt 0 ] ; then
1384        printf "(%02g:%02g (mm:ss))" $mins $secs
1385    elif [ $secs -gt 0 ] ; then
1386        printf "(%s seconds)" $secs
1387    fi
1388    if [ $(uname) != "Darwin" ]; then
1389        echo -e " ####\e[00m"
1390    fi
1391    echo
1392    return $ret
1393}
1394
1395if [ "x$SHELL" != "x/bin/bash" ]; then
1396    case `ps -o command -p $$` in
1397        *bash*)
1398            ;;
1399        *)
1400            echo "WARNING: Only bash is supported, use of other shell would lead to erroneous results"
1401            ;;
1402    esac
1403fi
1404
1405# Execute the contents of any vendorsetup.sh files we can find.
1406for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null` \
1407         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null`
1408do
1409    echo "including $f"
1410    . $f
1411done
1412unset f
1413
1414addcompletions
1415