• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2022 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# gettop is duplicated here and in shell_utils.mk, because it's difficult
16# to find shell_utils.make without it for all the novel ways this file can be
17# sourced.  Other common functions should only be in one place or the other.
18function _gettop_once
19{
20    local TOPFILE=build/make/core/envsetup.mk
21    if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
22        # The following circumlocution ensures we remove symlinks from TOP.
23        (cd "$TOP"; PWD= /bin/pwd)
24    else
25        if [ -f $TOPFILE ] ; then
26            # The following circumlocution (repeated below as well) ensures
27            # that we record the true directory name and not one that is
28            # faked up with symlink names.
29            PWD= /bin/pwd
30        else
31            local HERE=$PWD
32            local T=
33            while [ \( ! \( -f $TOPFILE \) \) -a \( "$PWD" != "/" \) ]; do
34                \cd ..
35                T=`PWD= /bin/pwd -P`
36            done
37            \cd "$HERE"
38            if [ -f "$T/$TOPFILE" ]; then
39                echo "$T"
40            fi
41        fi
42    fi
43}
44T=$(_gettop_once)
45if [ ! "$T" ]; then
46    echo "Couldn't locate the top of the tree. Always source build/envsetup.sh from the root of the tree." >&2
47    return 1
48fi
49IMPORTING_ENVSETUP=true source $T/build/make/shell_utils.sh
50
51# Get all the build variables needed by this script in a single call to the build system.
52function build_build_var_cache()
53{
54    local T=$(gettop)
55    # Grep out the variable names from the script.
56    cached_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/_get_build_var_cached/) print $(i+1)}' | sort -u | tr '\n' ' '`)
57    cached_abs_vars=(`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/_get_abs_build_var_cached/) print $(i+1)}' | sort -u | tr '\n' ' '`)
58    # Call the build system to dump the "<val>=<value>" pairs as a shell script.
59    build_dicts_script=`\builtin cd $T; build/soong/soong_ui.bash --dumpvars-mode \
60                        --vars="${cached_vars[*]}" \
61                        --abs-vars="${cached_abs_vars[*]}" \
62                        --var-prefix=var_cache_ \
63                        --abs-var-prefix=abs_var_cache_`
64    local ret=$?
65    if [ $ret -ne 0 ]
66    then
67        unset build_dicts_script
68        return $ret
69    fi
70    # Execute the script to store the "<val>=<value>" pairs as shell variables.
71    eval "$build_dicts_script"
72    ret=$?
73    unset build_dicts_script
74    if [ $ret -ne 0 ]
75    then
76        return $ret
77    fi
78    BUILD_VAR_CACHE_READY="true"
79}
80
81# Delete the build var cache, so that we can still call into the build system
82# to get build variables not listed in this script.
83function destroy_build_var_cache()
84{
85    unset BUILD_VAR_CACHE_READY
86    local v
87    for v in $cached_vars; do
88      unset var_cache_$v
89    done
90    unset cached_vars
91    for v in $cached_abs_vars; do
92      unset abs_var_cache_$v
93    done
94    unset cached_abs_vars
95}
96
97# Get the value of a build variable as an absolute path.
98function _get_abs_build_var_cached()
99{
100    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
101    then
102        eval "echo \"\${abs_var_cache_$1}\""
103        return
104    fi
105
106    local T=$(gettop)
107    if [ ! "$T" ]; then
108        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
109        return
110    fi
111    (\cd $T; build/soong/soong_ui.bash --dumpvar-mode --abs $1)
112}
113
114# Get the exact value of a build variable.
115function _get_build_var_cached()
116{
117    if [ "$BUILD_VAR_CACHE_READY" = "true" ]
118    then
119        eval "echo \"\${var_cache_$1}\""
120        return 0
121    fi
122
123    local T=$(gettop)
124    if [ ! "$T" ]; then
125        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
126        return 1
127    fi
128    (\cd $T; build/soong/soong_ui.bash --dumpvar-mode $1)
129}
130
131# This logic matches envsetup.mk
132function get_host_prebuilt_prefix
133{
134  local un=$(uname)
135  if [[ $un == "Linux" ]] ; then
136    echo linux-x86
137  elif [[ $un == "Darwin" ]] ; then
138    echo darwin-x86
139  else
140    echo "Error: Invalid host operating system: $un" 1>&2
141  fi
142}
143
144# Add directories to PATH that are dependent on the lunch target.
145# For directories that are not lunch-specific, add them in set_global_paths
146function set_lunch_paths()
147{
148    local T=$(gettop)
149    if [ ! "$T" ]; then
150        echo "Couldn't locate the top of the tree.  Try setting TOP."
151        return
152    fi
153
154    ##################################################################
155    #                                                                #
156    #              Read me before you modify this code               #
157    #                                                                #
158    #   This function sets ANDROID_LUNCH_BUILD_PATHS to what it is   #
159    #   adding to PATH, and the next time it is run, it removes that #
160    #   from PATH.  This is required so lunch can be run more than   #
161    #   once and still have working paths.                           #
162    #                                                                #
163    ##################################################################
164
165    # Note: on windows/cygwin, ANDROID_LUNCH_BUILD_PATHS will contain spaces
166    # due to "C:\Program Files" being in the path.
167
168    # Handle compat with the old ANDROID_BUILD_PATHS variable.
169    # TODO: Remove this after we think everyone has lunched again.
170    if [ -z "$ANDROID_LUNCH_BUILD_PATHS" -a -n "$ANDROID_BUILD_PATHS" ] ; then
171      ANDROID_LUNCH_BUILD_PATHS="$ANDROID_BUILD_PATHS"
172      ANDROID_BUILD_PATHS=
173    fi
174    if [ -n "$ANDROID_PRE_BUILD_PATHS" ] ; then
175        export PATH=${PATH/$ANDROID_PRE_BUILD_PATHS/}
176        # strip leading ':', if any
177        export PATH=${PATH/:%/}
178        ANDROID_PRE_BUILD_PATHS=
179    fi
180
181    # Out with the old...
182    if [ -n "$ANDROID_LUNCH_BUILD_PATHS" ] ; then
183        export PATH=${PATH/$ANDROID_LUNCH_BUILD_PATHS/}
184    fi
185
186    # And in with the new...
187    ANDROID_LUNCH_BUILD_PATHS=$(_get_abs_build_var_cached SOONG_HOST_OUT_EXECUTABLES)
188    ANDROID_LUNCH_BUILD_PATHS+=:$(_get_abs_build_var_cached HOST_OUT_EXECUTABLES)
189
190    # Append llvm binutils prebuilts path to ANDROID_LUNCH_BUILD_PATHS.
191    local ANDROID_LLVM_BINUTILS=$(_get_abs_build_var_cached ANDROID_CLANG_PREBUILTS)/llvm-binutils-stable
192    ANDROID_LUNCH_BUILD_PATHS+=:$ANDROID_LLVM_BINUTILS
193
194    # Set up ASAN_SYMBOLIZER_PATH for SANITIZE_HOST=address builds.
195    export ASAN_SYMBOLIZER_PATH=$ANDROID_LLVM_BINUTILS/llvm-symbolizer
196
197    # Append asuite prebuilts path to ANDROID_LUNCH_BUILD_PATHS.
198    local os_arch=$(_get_build_var_cached HOST_PREBUILT_TAG)
199    ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/acloud/$os_arch
200    ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/aidegen/$os_arch
201    ANDROID_LUNCH_BUILD_PATHS+=:$T/prebuilts/asuite/atest/$os_arch
202
203    export ANDROID_JAVA_HOME=$(_get_abs_build_var_cached ANDROID_JAVA_HOME)
204    export JAVA_HOME=$ANDROID_JAVA_HOME
205    export ANDROID_JAVA_TOOLCHAIN=$(_get_abs_build_var_cached ANDROID_JAVA_TOOLCHAIN)
206    ANDROID_LUNCH_BUILD_PATHS+=:$ANDROID_JAVA_TOOLCHAIN
207
208    # Fix up PYTHONPATH
209    if [ -n $ANDROID_PYTHONPATH ]; then
210        export PYTHONPATH=${PYTHONPATH//$ANDROID_PYTHONPATH/}
211    fi
212    # //development/python-packages contains both a pseudo-PYTHONPATH which
213    # mimics an already assembled venv, but also contains real Python packages
214    # that are not in that layout until they are installed. We can fake it for
215    # the latter type by adding the package source directories to the PYTHONPATH
216    # directly. For the former group, we only need to add the python-packages
217    # directory itself.
218    #
219    # This could be cleaned up by converting the remaining packages that are in
220    # the first category into a typical python source layout (that is, another
221    # layer of directory nesting) and automatically adding all subdirectories of
222    # python-packages to the PYTHONPATH instead of manually curating this. We
223    # can't convert the packages like adb to the other style because doing so
224    # would prevent exporting type info from those packages.
225    #
226    # http://b/266688086
227    export ANDROID_PYTHONPATH=$T/development/python-packages/adb:$T/development/python-packages/gdbrunner:$T/development/python-packages:
228    if [ -n $VENDOR_PYTHONPATH ]; then
229        ANDROID_PYTHONPATH=$ANDROID_PYTHONPATH$VENDOR_PYTHONPATH
230    fi
231    export PYTHONPATH=$ANDROID_PYTHONPATH$PYTHONPATH
232
233    unset ANDROID_PRODUCT_OUT
234    export ANDROID_PRODUCT_OUT=$(_get_abs_build_var_cached PRODUCT_OUT)
235    export OUT=$ANDROID_PRODUCT_OUT
236
237    unset ANDROID_HOST_OUT
238    export ANDROID_HOST_OUT=$(_get_abs_build_var_cached HOST_OUT)
239
240    unset ANDROID_SOONG_HOST_OUT
241    export ANDROID_SOONG_HOST_OUT=$(_get_abs_build_var_cached SOONG_HOST_OUT)
242
243    unset ANDROID_HOST_OUT_TESTCASES
244    export ANDROID_HOST_OUT_TESTCASES=$(_get_abs_build_var_cached HOST_OUT_TESTCASES)
245
246    unset ANDROID_TARGET_OUT_TESTCASES
247    export ANDROID_TARGET_OUT_TESTCASES=$(_get_abs_build_var_cached TARGET_OUT_TESTCASES)
248
249    # Finally, set PATH
250    export PATH=$ANDROID_LUNCH_BUILD_PATHS:$PATH
251}
252
253# Add directories to PATH that are NOT dependent on the lunch target.
254# For directories that are lunch-specific, add them in set_lunch_paths
255function set_global_paths()
256{
257    local T=$(gettop)
258    if [ ! "$T" ]; then
259        echo "Couldn't locate the top of the tree.  Try setting TOP."
260        return
261    fi
262
263    ##################################################################
264    #                                                                #
265    #              Read me before you modify this code               #
266    #                                                                #
267    #   This function sets ANDROID_GLOBAL_BUILD_PATHS to what it is  #
268    #   adding to PATH, and the next time it is run, it removes that #
269    #   from PATH.  This is required so envsetup.sh can be sourced   #
270    #   more than once and still have working paths.                 #
271    #                                                                #
272    ##################################################################
273
274    # Out with the old...
275    if [ -n "$ANDROID_GLOBAL_BUILD_PATHS" ] ; then
276        export PATH=${PATH/$ANDROID_GLOBAL_BUILD_PATHS/}
277    fi
278
279    # And in with the new...
280    ANDROID_GLOBAL_BUILD_PATHS=$T/build/soong/bin
281    ANDROID_GLOBAL_BUILD_PATHS+=:$T/build/bazel/bin
282    ANDROID_GLOBAL_BUILD_PATHS+=:$T/development/scripts
283    ANDROID_GLOBAL_BUILD_PATHS+=:$T/prebuilts/devtools/tools
284
285    # add kernel specific binaries
286    if [ $(uname -s) = Linux ] ; then
287        ANDROID_GLOBAL_BUILD_PATHS+=:$T/prebuilts/misc/linux-x86/dtc
288        ANDROID_GLOBAL_BUILD_PATHS+=:$T/prebuilts/misc/linux-x86/libufdt
289    fi
290
291    # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH
292    # to ensure that the corresponding 'emulator' binaries are used.
293    case $(uname -s) in
294        Darwin)
295            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/darwin-x86_64
296            ;;
297        Linux)
298            ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/linux-x86_64
299            ;;
300        *)
301            ANDROID_EMULATOR_PREBUILTS=
302            ;;
303    esac
304    if [ -n "$ANDROID_EMULATOR_PREBUILTS" -a -d "$ANDROID_EMULATOR_PREBUILTS" ]; then
305        ANDROID_GLOBAL_BUILD_PATHS+=:$ANDROID_EMULATOR_PREBUILTS
306        export ANDROID_EMULATOR_PREBUILTS
307    fi
308
309    # Finally, set PATH
310    export PATH=$ANDROID_GLOBAL_BUILD_PATHS:$PATH
311}
312
313function printconfig()
314{
315    local T=$(gettop)
316    if [ ! "$T" ]; then
317        echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
318        return
319    fi
320    _get_build_var_cached report_config
321}
322
323function set_stuff_for_environment()
324{
325    set_lunch_paths
326    set_sequence_number
327
328    export ANDROID_BUILD_TOP=$(gettop)
329}
330
331function set_sequence_number()
332{
333    export BUILD_ENV_SEQUENCE_NUMBER=13
334}
335
336# Takes a command name, and check if it's in ENVSETUP_NO_COMPLETION or not.
337function should_add_completion() {
338    local cmd="$(basename $1| sed 's/_completion//' |sed 's/\.\(.*\)*sh$//')"
339    case :"$ENVSETUP_NO_COMPLETION": in
340        *:"$cmd":*)
341            return 1
342            ;;
343    esac
344    return 0
345}
346
347function addcompletions()
348{
349    local f=
350
351    # Keep us from trying to run in something that's neither bash nor zsh.
352    if [ -z "$BASH_VERSION" -a -z "$ZSH_VERSION" ]; then
353        return
354    fi
355
356    # Keep us from trying to run in bash that's too old.
357    if [ -n "$BASH_VERSION" -a ${BASH_VERSINFO[0]} -lt 3 ]; then
358        return
359    fi
360
361    local completion_files=(
362      packages/modules/adb/adb.bash
363      system/core/fastboot/fastboot.bash
364      tools/asuite/asuite.sh
365    )
366    # Completion can be disabled selectively to allow users to use non-standard completion.
367    # e.g.
368    # ENVSETUP_NO_COMPLETION=adb # -> disable adb completion
369    # ENVSETUP_NO_COMPLETION=adb:bit # -> disable adb and bit completion
370    local T=$(gettop)
371    for f in ${completion_files[*]}; do
372        f="$T/$f"
373        if [ ! -f "$f" ]; then
374          echo "Warning: completion file $f not found"
375        elif should_add_completion "$f"; then
376            . $f
377        fi
378    done
379
380    if [ -z "$ZSH_VERSION" ]; then
381        # Doesn't work in zsh.
382        complete -o nospace -F _croot croot
383        # TODO(b/244559459): Support b autocompletion for zsh
384        complete -F _bazel__complete -o nospace b
385    fi
386    complete -F _lunch lunch
387    complete -F _lunch_completion lunch2
388
389    complete -F _complete_android_module_names pathmod
390    complete -F _complete_android_module_names gomod
391    complete -F _complete_android_module_names outmod
392    complete -F _complete_android_module_names installmod
393    complete -F _complete_android_module_names m
394}
395
396function add_lunch_combo()
397{
398    if [ -n "$ZSH_VERSION" ]; then
399        echo -n "${funcfiletrace[1]}: "
400    else
401        echo -n "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: "
402    fi
403    echo "add_lunch_combo is obsolete. Use COMMON_LUNCH_CHOICES in your AndroidProducts.mk instead."
404}
405
406function print_lunch_menu()
407{
408    local uname=$(uname)
409    local choices
410    choices=$(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_RELEASE= TARGET_BUILD_VARIANT= _get_build_var_cached COMMON_LUNCH_CHOICES 2>/dev/null)
411    local ret=$?
412
413    echo
414    echo "You're building on" $uname
415    echo
416
417    if [ $ret -ne 0 ]
418    then
419        echo "Warning: Cannot display lunch menu."
420        echo
421        echo "Note: You can invoke lunch with an explicit target:"
422        echo
423        echo "  usage: lunch [target]" >&2
424        echo
425        return
426    fi
427
428    echo "Lunch menu .. Here are the common combinations:"
429
430    local i=1
431    local choice
432    for choice in $(echo $choices)
433    do
434        echo "     $i. $choice"
435        i=$(($i+1))
436    done
437
438    echo
439}
440
441function _lunch_meat()
442{
443    local product=$1
444    local release=$2
445    local variant=$3
446
447    TARGET_PRODUCT=$product \
448    TARGET_RELEASE=$release \
449    TARGET_BUILD_VARIANT=$variant \
450    build_build_var_cache
451    if [ $? -ne 0 ]
452    then
453        if [[ "$product" =~ .*_(eng|user|userdebug) ]]
454        then
455            echo "Did you mean -${product/*_/}? (dash instead of underscore)"
456        fi
457        return 1
458    fi
459    export TARGET_PRODUCT=$(_get_build_var_cached TARGET_PRODUCT)
460    export TARGET_BUILD_VARIANT=$(_get_build_var_cached TARGET_BUILD_VARIANT)
461    export TARGET_RELEASE=$release
462    # Note this is the string "release", not the value of the variable.
463    export TARGET_BUILD_TYPE=release
464
465    [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || echo
466
467    set_stuff_for_environment
468    [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || printconfig
469
470    if [[ -z "${ANDROID_QUIET_BUILD}" ]]; then
471        local spam_for_lunch=$(gettop)/build/make/tools/envsetup/spam_for_lunch
472        if [[ -x $spam_for_lunch ]]; then
473            $spam_for_lunch
474        fi
475    fi
476
477    destroy_build_var_cache
478
479    if [[ -n "${CHECK_MU_CONFIG:-}" ]]; then
480      check_mu_config
481    fi
482}
483
484unset COMMON_LUNCH_CHOICES_CACHE
485# Tab completion for lunch.
486function _lunch()
487{
488    local cur prev opts
489    COMPREPLY=()
490    cur="${COMP_WORDS[COMP_CWORD]}"
491    prev="${COMP_WORDS[COMP_CWORD-1]}"
492
493    if [ -z "$COMMON_LUNCH_CHOICES_CACHE" ]; then
494        COMMON_LUNCH_CHOICES_CACHE=$(TARGET_BUILD_APPS= _get_build_var_cached COMMON_LUNCH_CHOICES)
495    fi
496
497    COMPREPLY=( $(compgen -W "${COMMON_LUNCH_CHOICES_CACHE}" -- ${cur}) )
498    return 0
499}
500
501function _lunch_usage()
502{
503    (
504        echo "The lunch command selects the configuration to use for subsequent"
505        echo "Android builds."
506        echo
507        echo "Usage: lunch TARGET_PRODUCT [TARGET_RELEASE [TARGET_BUILD_VARIANT]]"
508        echo
509        echo "  Choose the product, release and variant to use. If not"
510        echo "  supplied, TARGET_RELEASE will be 'trunk_staging' and"
511        echo "  TARGET_BUILD_VARIANT will be 'eng'"
512        echo
513        echo
514        echo "Usage: lunch TARGET_PRODUCT-TARGET_RELEASE-TARGET_BUILD_VARIANT"
515        echo
516        echo "  Chose the product, release and variant to use. This"
517        echo "  legacy format is maintained for compatibility."
518        echo
519        echo
520        echo "Note that the previous interactive menu and list of hard-coded"
521        echo "list of curated targets has been removed. If you would like the"
522        echo "list of products, release configs for a particular product, or"
523        echo "variants, run list_products list_releases or list_variants"
524        echo "respectively."
525        echo
526    ) 1>&2
527}
528
529function lunch()
530{
531    if [[ $# -eq 1 && $1 = "--help" ]]; then
532        _lunch_usage
533        return 0
534    fi
535    if [[ $# -eq 0 ]]; then
536        echo "No target specified. See lunch --help" 1>&2
537        return 1
538    fi
539    if [[ $# -gt 3 ]]; then
540        echo "Too many parameters given. See lunch --help" 1>&2
541        return 1
542    fi
543
544    local product release variant
545
546    # Handle the legacy format
547    local legacy=$(echo $1 | grep "-")
548    if [[ $# -eq 1 && -n $legacy ]]; then
549        IFS="-" read -r product release variant <<< "$1"
550        if [[ -z "$product" ]] || [[ -z "$release" ]] || [[ -z "$variant" ]]; then
551            echo "Invalid lunch combo: $1" 1>&2
552            echo "Valid combos must be of the form <product>-<release>-<variant> when using" 1>&2
553            echo "the legacy format.  Run 'lunch --help' for usage." 1>&2
554            return 1
555        fi
556    fi
557
558    # Handle the new format.
559    if [[ -z $legacy ]]; then
560        product=$1
561        release=$2
562        if [[ -z $release ]]; then
563            release=trunk_staging
564        fi
565        variant=$3
566        if [[ -z $variant ]]; then
567            variant=eng
568        fi
569    fi
570
571    # Validate the selection and set all the environment stuff
572    _lunch_meat $product $release $variant
573}
574
575unset ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE
576unset ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT
577unset ANDROID_LUNCH_COMPLETION_RELEASE_CACHE
578# Tab completion for lunch.
579function _lunch_completion()
580{
581    # Available products
582    if [[ $COMP_CWORD -eq 1 ]] ; then
583        if [[ -z $ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE ]]; then
584            ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE=$(list_products)
585        fi
586        COMPREPLY=( $(compgen -W "${ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE}" -- "${COMP_WORDS[COMP_CWORD]}") )
587    fi
588
589    # Available release configs
590    if [[ $COMP_CWORD -eq 2 ]] ; then
591        if [[ -z $ANDROID_LUNCH_COMPLETION_RELEASE_CACHE || $ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT != ${COMP_WORDS[1]} ]] ; then
592            ANDROID_LUNCH_COMPLETION_RELEASE_CACHE=$(list_releases ${COMP_WORDS[1]})
593            ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT=${COMP_WORDS[1]}
594        fi
595        COMPREPLY=( $(compgen -W "${ANDROID_LUNCH_COMPLETION_RELEASE_CACHE}" -- "${COMP_WORDS[COMP_CWORD]}") )
596    fi
597
598    # Available variants
599    if [[ $COMP_CWORD -eq 3 ]] ; then
600        COMPREPLY=(user userdebug eng)
601    fi
602
603    return 0
604}
605
606
607# Configures the build to build unbundled apps.
608# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
609function tapas()
610{
611    local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
612    local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|arm64|x86_64)$' | xargs)"
613    # TODO(b/307975293): Expand tapas to take release arguments (and update hmm() usage).
614    local release="trunk_staging"
615    local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
616    local density="$(echo $* | xargs -n 1 echo | \grep -E '^(ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
617    local keys="$(echo $* | xargs -n 1 echo | \grep -E '^(devkeys)$' | xargs)"
618    local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|arm64|x86_64|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi|devkeys)$' | xargs)"
619
620
621    if [ "$showHelp" != "" ]; then
622      $(gettop)/build/make/tapasHelp.sh
623      return
624    fi
625
626    if [ $(echo $arch | wc -w) -gt 1 ]; then
627        echo "tapas: Error: Multiple build archs supplied: $arch"
628        return
629    fi
630    if [ $(echo $release | wc -w) -gt 1 ]; then
631        echo "tapas: Error: Multiple build releases supplied: $release"
632        return
633    fi
634    if [ $(echo $variant | wc -w) -gt 1 ]; then
635        echo "tapas: Error: Multiple build variants supplied: $variant"
636        return
637    fi
638    if [ $(echo $density | wc -w) -gt 1 ]; then
639        echo "tapas: Error: Multiple densities supplied: $density"
640        return
641    fi
642    if [ $(echo $keys | wc -w) -gt 1 ]; then
643        echo "tapas: Error: Multiple keys supplied: $keys"
644        return
645    fi
646
647    local product=aosp_arm
648    case $arch in
649      x86)    product=aosp_x86;;
650      arm64)  product=aosp_arm64;;
651      x86_64) product=aosp_x86_64;;
652    esac
653    if [ -n "$keys" ]; then
654        product=${product/aosp_/aosp_${keys}_}
655    fi;
656
657    if [ -z "$variant" ]; then
658        variant=eng
659    fi
660    if [ -z "$apps" ]; then
661        apps=all
662    fi
663    if [ -z "$density" ]; then
664        density=alldpi
665    fi
666
667    export TARGET_PRODUCT=$product
668    export TARGET_RELEASE=$release
669    export TARGET_BUILD_VARIANT=$variant
670    export TARGET_BUILD_DENSITY=$density
671    export TARGET_BUILD_TYPE=release
672    export TARGET_BUILD_APPS=$apps
673
674    build_build_var_cache
675    set_stuff_for_environment
676    printconfig
677    destroy_build_var_cache
678}
679
680# Configures the build to build unbundled Android modules (APEXes).
681# Run banchan with one or more module names (from apex{} modules).
682function banchan()
683{
684    local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
685    local product="$(echo $* | xargs -n 1 echo | \grep -E '^(.*_)?(arm|x86|arm64|riscv64|x86_64|arm64only|x86_64only)$' | xargs)"
686    # TODO: Expand banchan to take release arguments (and update hmm() usage).
687    local release="trunk_staging"
688    local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
689    local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|(.*_)?(arm|x86|arm64|riscv64|x86_64))$' | xargs)"
690
691    if [ "$showHelp" != "" ]; then
692      $(gettop)/build/make/banchanHelp.sh
693      return
694    fi
695
696    if [ -z "$product" ]; then
697        product=arm64
698    elif [ $(echo $product | wc -w) -gt 1 ]; then
699        echo "banchan: Error: Multiple build archs or products supplied: $products"
700        return
701    fi
702    if [ $(echo $release | wc -w) -gt 1 ]; then
703        echo "banchan: Error: Multiple build releases supplied: $release"
704        return
705    fi
706    if [ $(echo $variant | wc -w) -gt 1 ]; then
707        echo "banchan: Error: Multiple build variants supplied: $variant"
708        return
709    fi
710    if [ -z "$apps" ]; then
711        echo "banchan: Error: No modules supplied"
712        return
713    fi
714
715    case $product in
716      arm)    product=module_arm;;
717      x86)    product=module_x86;;
718      arm64)  product=module_arm64;;
719      riscv64) product=module_riscv64;;
720      x86_64) product=module_x86_64;;
721      arm64only)  product=module_arm64only;;
722      x86_64only) product=module_x86_64only;;
723    esac
724    if [ -z "$variant" ]; then
725        variant=eng
726    fi
727
728    export TARGET_PRODUCT=$product
729    export TARGET_RELEASE=$release
730    export TARGET_BUILD_VARIANT=$variant
731    export TARGET_BUILD_DENSITY=alldpi
732    export TARGET_BUILD_TYPE=release
733
734    # This setup currently uses TARGET_BUILD_APPS just like tapas, but the use
735    # case is different and it may diverge in the future.
736    export TARGET_BUILD_APPS=$apps
737
738    build_build_var_cache
739    set_stuff_for_environment
740    printconfig
741    destroy_build_var_cache
742}
743
744function croot()
745{
746    local T=$(gettop)
747    if [ "$T" ]; then
748        if [ "$1" ]; then
749            \cd $(gettop)/$1
750        else
751            \cd $(gettop)
752        fi
753    else
754        echo "Couldn't locate the top of the tree.  Try setting TOP."
755    fi
756}
757
758function _croot()
759{
760    local T=$(gettop)
761    if [ "$T" ]; then
762        local cur="${COMP_WORDS[COMP_CWORD]}"
763        k=0
764        for c in $(compgen -d ${T}/${cur}); do
765            COMPREPLY[k++]=${c#${T}/}/
766        done
767    fi
768}
769
770function cproj()
771{
772    local TOPFILE=build/make/core/envsetup.mk
773    local HERE=$PWD
774    local T=
775    while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
776        T=$PWD
777        if [ -f "$T/Android.mk" ]; then
778            \cd $T
779            return
780        fi
781        \cd ..
782    done
783    \cd $HERE
784    echo "can't find Android.mk"
785}
786
787# Ensure that we're always using the adb in the tree. This works around the fact
788# that bash caches $PATH lookups, so if you use adb before lunching/building the
789# one in your tree, you'll continue to get /usr/bin/adb or whatever even after
790# you have the one from your current tree on your path. Historically this would
791# cause confusion because glinux had adb in /usr/bin/ by default, though that
792# doesn't appear to be the case on my rodete hosts; it is however still the case
793# that my Mac has /usr/local/bin/adb installed by default and on the default
794# path.
795function adb() {
796    # We need `command which` because zsh has a built-in `which` that's more
797    # like `type`.
798    local ADB=$(command which adb)
799    if [ -z "$ADB" ]; then
800        echo "Command adb not found; try lunch (and building) first?"
801        return 1
802    fi
803    run_tool_with_logging "ADB" $ADB "${@}"
804}
805
806function fastboot() {
807    local FASTBOOT=$(command which fastboot)
808    if [ -z "$FASTBOOT" ]; then
809        echo "Command fastboot not found; try lunch (and building) first?"
810        return 1
811    fi
812    # Support tool event logging for fastboot command.
813    run_tool_with_logging "FASTBOOT" $FASTBOOT "${@}"
814}
815
816# communicate with a running device or emulator, set up necessary state,
817# and run the hat command.
818function runhat()
819{
820    # process standard adb options
821    local adbTarget=""
822    if [ "$1" = "-d" -o "$1" = "-e" ]; then
823        adbTarget=$1
824        shift 1
825    elif [ "$1" = "-s" ]; then
826        adbTarget="$1 $2"
827        shift 2
828    fi
829    local adbOptions=${adbTarget}
830    #echo adbOptions = ${adbOptions}
831
832    # runhat options
833    local targetPid=$1
834
835    if [ "$targetPid" = "" ]; then
836        echo "Usage: runhat [ -d | -e | -s serial ] target-pid"
837        return
838    fi
839
840    # confirm hat is available
841    if [ -z $(which hat) ]; then
842        echo "hat is not available in this configuration."
843        return
844    fi
845
846    # issue "am" command to cause the hprof dump
847    local devFile=/data/local/tmp/hprof-$targetPid
848    echo "Poking $targetPid and waiting for data..."
849    echo "Storing data at $devFile"
850    adb ${adbOptions} shell am dumpheap $targetPid $devFile
851    echo "Press enter when logcat shows \"hprof: heap dump completed\""
852    echo -n "> "
853    read
854
855    local localFile=/tmp/$$-hprof
856
857    echo "Retrieving file $devFile..."
858    adb ${adbOptions} pull $devFile $localFile
859
860    adb ${adbOptions} shell rm $devFile
861
862    echo "Running hat on $localFile"
863    echo "View the output by pointing your browser at http://localhost:7000/"
864    echo ""
865    hat -JXmx512m $localFile
866}
867
868function godir () {
869    if [[ -z "$1" ]]; then
870        echo "Usage: godir <regex>"
871        return
872    fi
873    local T=$(gettop)
874    local FILELIST
875    if [ ! "$OUT_DIR" = "" ]; then
876        mkdir -p $OUT_DIR
877        FILELIST=$OUT_DIR/filelist
878    else
879        FILELIST=$T/filelist
880    fi
881    if [[ ! -f $FILELIST ]]; then
882        echo -n "Creating index..."
883        (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > $FILELIST)
884        echo " Done"
885        echo ""
886    fi
887    local lines
888    lines=($(\grep "$1" $FILELIST | sed -e 's/\/[^/]*$//' | sort | uniq))
889    if [[ ${#lines[@]} = 0 ]]; then
890        echo "Not found"
891        return
892    fi
893    local pathname
894    local choice
895    if [[ ${#lines[@]} > 1 ]]; then
896        while [[ -z "$pathname" ]]; do
897            local index=1
898            local line
899            for line in ${lines[@]}; do
900                printf "%6s %s\n" "[$index]" $line
901                index=$(($index + 1))
902            done
903            echo
904            echo -n "Select one: "
905            unset choice
906            read choice
907            if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then
908                echo "Invalid choice"
909                continue
910            fi
911            pathname=${lines[@]:$(($choice-1)):1}
912        done
913    else
914        pathname=${lines[@]:0:1}
915    fi
916    \cd $T/$pathname
917}
918
919# Go to a specific module in the android tree, as cached in module-info.json. If any build change
920# is made, and it should be reflected in the output, you should run 'refreshmod' first.
921# Note: This function is in envsetup because changing the directory needs to happen in the current
922# shell. All other functions that use module-info.json should be in build/soong/bin.
923function gomod() {
924    if [[ $# -ne 1 ]]; then
925        echo "usage: gomod <module>" >&2
926        return 1
927    fi
928
929    local path="$(pathmod $@)"
930    if [ -z "$path" ]; then
931        return 1
932    fi
933    cd $path
934}
935
936function _complete_android_module_names() {
937    local word=${COMP_WORDS[COMP_CWORD]}
938    COMPREPLY=( $(allmod | grep -E "^$word") )
939}
940
941function get_make_command()
942{
943    # If we're in the top of an Android tree, use soong_ui.bash instead of make
944    if [ -f build/soong/soong_ui.bash ]; then
945        # Always use the real make if -C is passed in
946        for arg in "$@"; do
947            if [[ $arg == -C* ]]; then
948                echo command make
949                return
950            fi
951        done
952        echo build/soong/soong_ui.bash --make-mode
953    else
954        echo command make
955    fi
956}
957
958function make()
959{
960    _wrap_build $(get_make_command "$@") "$@"
961}
962
963# Zsh needs bashcompinit called to support bash-style completion.
964function enable_zsh_completion() {
965    # Don't override user's options if bash-style completion is already enabled.
966    if ! declare -f complete >/dev/null; then
967        autoload -U compinit && compinit
968        autoload -U bashcompinit && bashcompinit
969    fi
970}
971
972function validate_current_shell() {
973    local current_sh="$(ps -o command -p $$)"
974    case "$current_sh" in
975        *bash*)
976            function check_type() { type -t "$1"; }
977            ;;
978        *zsh*)
979            function check_type() { type "$1"; }
980            enable_zsh_completion ;;
981        *)
982            echo -e "WARNING: Only bash and zsh are supported.\nUse of other shell would lead to erroneous results."
983            ;;
984    esac
985}
986
987# Execute the contents of any vendorsetup.sh files we can find.
988# Unless we find an allowed-vendorsetup_sh-files file, in which case we'll only
989# load those.
990#
991# This allows loading only approved vendorsetup.sh files
992function source_vendorsetup() {
993    unset VENDOR_PYTHONPATH
994    local T="$(gettop)"
995    allowed=
996    for f in $(cd "$T" && find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
997        if [ -n "$allowed" ]; then
998            echo "More than one 'allowed_vendorsetup_sh-files' file found, not including any vendorsetup.sh files:"
999            echo "  $allowed"
1000            echo "  $f"
1001            return
1002        fi
1003        allowed="$T/$f"
1004    done
1005
1006    allowed_files=
1007    [ -n "$allowed" ] && allowed_files=$(cat "$allowed")
1008    for dir in device vendor product; do
1009        for f in $(cd "$T" && test -d $dir && \
1010            find -L $dir -maxdepth 4 -name 'vendorsetup.sh' 2>/dev/null | sort); do
1011
1012            if [[ -z "$allowed" || "$allowed_files" =~ $f ]]; then
1013                echo "including $f"; . "$T/$f"
1014            else
1015                echo "ignoring $f, not in $allowed"
1016            fi
1017        done
1018    done
1019
1020    setup_cog_env_if_needed
1021}
1022
1023function showcommands() {
1024    local T=$(gettop)
1025    if [[ -z "$TARGET_PRODUCT" ]]; then
1026        >&2 echo "TARGET_PRODUCT not set. Run lunch."
1027        return
1028    fi
1029    case $(uname -s) in
1030        Darwin)
1031            PREBUILT_NAME=darwin-x86
1032            ;;
1033        Linux)
1034            PREBUILT_NAME=linux-x86
1035            ;;
1036        *)
1037            >&2 echo Unknown host $(uname -s)
1038            return
1039            ;;
1040    esac
1041    OUT_DIR="$(_get_abs_build_var_cached OUT_DIR)"
1042    if [[ "$1" == "--regenerate" ]]; then
1043      shift 1
1044      NINJA_ARGS="-t commands $@" m
1045    else
1046      (cd $T && prebuilts/build-tools/$PREBUILT_NAME/bin/ninja \
1047          -f $OUT_DIR/combined-${TARGET_PRODUCT}.ninja \
1048          -t commands "$@")
1049    fi
1050}
1051
1052# These functions used to be here but are now standalone scripts
1053# in build/soong/bin.  Unset these for the time being so the real
1054# script is picked up.
1055# TODO: Remove this some time after a suitable delay (maybe 2025?)
1056unset allmod
1057unset aninja
1058unset cgrep
1059unset core
1060unset coredump_enable
1061unset coredump_setup
1062unset dirmods
1063unset get_build_var
1064unset get_abs_build_var
1065unset getlastscreenshot
1066unset getprebuilt
1067unset getscreenshotpath
1068unset getsdcardpath
1069unset gettargetarch
1070unset ggrep
1071unset gogrep
1072unset hmm
1073unset installmod
1074unset is64bit
1075unset isviewserverstarted
1076unset jgrep
1077unset jsongrep
1078unset key_back
1079unset key_home
1080unset key_menu
1081unset ktgrep
1082unset m
1083unset mangrep
1084unset mgrep
1085unset mm
1086unset mma
1087unset mmm
1088unset mmma
1089unset outmod
1090unset overrideflags
1091unset owngrep
1092unset pathmod
1093unset pez
1094unset pygrep
1095unset qpid
1096unset rcgrep
1097unset refreshmod
1098unset resgrep
1099unset rsgrep
1100unset run_tool_with_logging
1101unset sepgrep
1102unset sgrep
1103unset startviewserver
1104unset stopviewserver
1105unset systemstack
1106unset syswrite
1107unset tomlgrep
1108unset treegrep
1109
1110
1111validate_current_shell
1112set_global_paths
1113source_vendorsetup
1114addcompletions
1115
1116
1117