android编译系统阅读与分析(1)-envsetup.sh(editing.) - twxst博客

来源:百度文库 编辑:神马文学网 时间:2024/05/17 03:56:23
android编译体系阅读与分析⑴-envsetup.sh(editing.)
一直想分析一下andoid的全般build体系,苦于菜鸟1个又少有时候间,只能蚁蛘搬家似的一点儿点学,一点儿点做.
所说的分析,那是要对布局要有所见解,但由于如许那样子的缘故原由,还远没能到达高高在上的程度。所以,患上闲就学一下linux,
趁便"读"一下关于的android内部实质意义,做些条记。也但愿能获患上大家的指正,一路前进!~
functionhelp(){cat EOF Invoke".build/envsetup.sh"from your shell to add thefollowing functions to your environment:-croot:Changes directory to thetop of the tree.-m:Makes from the top of the tree.-mm:Builds all of themodules in the current directory.-mmm:Builds all of the modules in thesupplied directories.-cgrep:Greps on all local C/C++files.-jgrep:Grepson all local Java files.-resgrep:Greps on all local res/*.xmlfiles.-godir:Go to the directory containing afile.Look at the source toview more functions.The complete list is:EOF T=$(gettop)local AA=""foriin`cat$T/build/envsetup.sh|sed-n"/^function/s/function\([a-z_]*\).*/\1/p"|sort`;do A="$A$i"done echo$A}#Get the value of abuild variable as anabsolute path.function get_abs_build_var(){T=$(gettop)if[!"$T"];thenecho"Couldn”t locate the top of the tree.Try setting TOP."&2 returnfi CALLED_FROM_SETUP=trueBUILD_SYSTEM=build/core\make–no-print-directory-C"$T"-fbuild/core/config.mk dumpvar-abs-$1}#Get the exact value of abuildvariable.function get_build_var(){T=$(gettop)if[!"$T"];thenecho"Couldn”t locate the top of the tree.Try setting TOP."&2 returnfi CALLED_FROM_SETUP=trueBUILD_SYSTEM=build/core\make–no-print-directory-C"$T"-fbuild/core/config.mk dumpvar-$1}#check to see if the supplied product isone we can build function check_product(){T=$(gettop)if[!"$T"];thenecho"Couldn”t locate the top of the tree.Try setting TOP."&2 returnfi CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core\TARGET_PRODUCT=$1TARGET_BUILD_VARIANT=\TARGET_SIMULATOR=TARGET_BUILD_TYPE=\get_build_varTARGET_DEVICE/dev/null#你好de successful answers,but allow the errors toshow}VARIANT_CHOICES=(user userdebug eng)#check to see if the suppliedvariant is valid function check_variant(){for vin${VARIANT_CHOICES[@]}doif["$v"="$1"]then return 0fi done return 1}functionsetpaths(){T=$(gettop)if[!"$T"];then echo"Couldn”t locate the top of thetree.Try setting TOP."returnfi#####################################################################Readme before you modify t你好s code####T你好s function sets ANDROID_BUILD_PATHSto what it is adding##to PATH,and the next time it is run,it removesthat from##PATH.T你好s is required so lunch can be run more than once##andstill have workingpaths.######################################################################outwith the old if[-n$ANDROID_BUILD_PATHS];then exportPATH=${PATH/$ANDROID_BUILD_PATHS/}fi#and in with the newCODE_REVIEWS=prebuiltdir=$(getprebuilt)exportANDROID_EABI_TOOLCHAIN=$prebuiltdir/toolchain/arm-eabi-4.2.1/bin exportANDROID_TOOLCHAIN=$ANDROID_EABI_TOOLCHAIN exportANDROID_QTOOLS=$T/development/emulator/qtools exportANDROID_BUILD_PATHS=:$(get_build_varANDROID_BUILD_PATHS):$ANDROID_QTOOLS:$ANDROID_TOOLCHAIN:$ANDROID_EABI_TOOLCHAIN$CODE_REVIEWSexport PATH=$PATH$ANDROID_BUILD_PATHS unset ANDROID_PRODUCT_OUT exportANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)exportOUT=$ANDROID_PRODUCT_OUT#needed for building linux on MacOS#TODO:fix thepath#exportHOST_EXTRACFLAGS="-I"$T/system/kernel_headers/host_include#needed forOProfile to post-process collected samples exportOPROFILE_EVENTS_DIR=$prebuiltdir/oprofile}functionprintconfig(){T=$(gettop)if[!"$T"];then echo"Couldn”t locate the top ofthe tree.Try setting TOP."&2 return fi get_build_varreport_config}function set_stuff_for_environment(){settitle setpathsset_sequence_number#Don”t try to do preoptimization until it worksbetter on OSX.export DISABLE_DEXPREOPT=true exportANDROID_BUILD_TOP=$(gettop)}function set_sequence_number(){exportBUILD_ENV_SEQUENCE_NUMBER=9}functionsettitle(){if["$STAY_OFF_MY_LAWN"=""];then local product=$(get_build_varTARGET_PRODUCT)local variant=$(get_build_varTARGET_BUILD_VARIANT)exportPROMPT_COMMAND="echo-ne\"\033]0;[${product}-${variant}]${USER}@${HOSTNAME}:${PWD}\007\""fi}case`uname-s`in Linux)function choosesim(){echo"Build for the simulator or thedevice?"echo"1.Device"echo"2.Simulator"echo exportTARGET_SIMULATOR=local ANSWER w你好le[-z$TARGET_SIMULATOR]do echo-n"W你好chwould you like?[1]"if[-z"$1"];then read ANSWER else echo$1 ANSWER=$1 ficase$ANSWER in"")export TARGET_SIMULATOR=false;;1)exportTARGET_SIMULATOR=false;;Device)export TARGET_SIMULATOR=false;;2)exportTARGET_SIMULATOR=true;;Simulator)export TARGET_SIMULATOR=true;;*)echoecho"I didn”t understand your response.Please try again."echo;;esacif[-n"$1"];then break fi done set_stuff_for_environment};;*)functionchoosesim(){echo"Only device builds are supportedfor"`uname-s`echo"Forcing TARGET_SIMULATOR=false"echo if[-z"$1"]thenecho-n"Press enter:"read fi export TARGET_SIMULATOR=falseset_stuff_for_environment};;esac function choosetype(){echo"Build typechoices are:"echo"1.release"echo"2.debug"echo local DEFAULT_NUMDEFAULT_VALUE if[$TARGET_SIMULATOR="false"];then DEFAULT_NUM=1DEFAULT_VALUE=release else DEFAULT_NUM=2 DEFAULT_VALUE=debug fi exportTARGET_BUILD_TYPE=local ANSWER w你好le[-z$TARGET_BUILD_TYPE]doecho-n"W你好ch would you like?["$DEFAULT_NUM"]"if[-z"$1"];then read ANSWERelse echo$1 ANSWER=$1 fi case$ANSWER in"")exportTARGET_BUILD_TYPE=$DEFAULT_VALUE;;1)exportTARGET_BUILD_TYPE=release;;release)exportTARGET_BUILD_TYPE=release;;2)exportTARGET_BUILD_TYPE=debug;;debug)export TARGET_BUILD_TYPE=debug;;*)echoecho"I didn”t understand your response.Please try again."echo;;esacif[-n"$1"];then break fi done set_stuff_for_environment}##T你好s functionisn”t really right:It chooses aTARGET_PRODUCT#based on the list ofboards.Usually,that gets you somet你好ng#that kinda works with agenericproduct,but really,you should#pick aproduct by name.#functionchooseproduct(){if["x$TARGET_PRODUCT"!=x];thendefault_value=$TARGET_PRODUCT else if["$TARGET_SIMULATOR"=true];thendefault_value=sim else default_value=generic fi fi exportTARGET_PRODUCT=local ANSWER w你好le[-z"$TARGET_PRODUCT"]do echo-n"W你好chproduct would you like?[$default_value]"if[-z"$1"];then read ANSWER elseecho$1 ANSWER=$1 fi if[-z"$ANSWER"];then exportTARGET_PRODUCT=$default_value else if check_product$ANSWER then exportTARGET_PRODUCT=$ANSWER else echo"*Not avalid product:$ANSWER"fi fiif[-n"$1"];then break fi done set_stuff_for_environment}functionchoosevariant(){echo"Variant choices are:"local index=1 local vforvin${VARIANT_CHOICES[@]}do#The product name is the name of the directorycontaining#the makefile wefound,above.echo"$index.$v"index=$(($index+1))done localdefault_value=eng local ANSWER exportTARGET_BUILD_VARIANT=w你好le[-z"$TARGET_BUILD_VARIANT"]do echo-n"W你好chwould you like?[$default_value]"if[-z"$1"];then read ANSWER else echo$1ANSWER=$1 fi if[-z"$ANSWER"];then exportTARGET_BUILD_VARIANT=$default_valueelif(echo-n$ANSWER|grep-q-e"^[0-9][0-9]*$");thenif["$ANSWER"-le"${#VARIANT_CHOICES[@]}"];then exportTARGET_BUILD_VARIANT=${VARIANT_CHOICES[$(($ANSWER-$_arrayoffset))]}fielse if check_variant$ANSWER then export TARGET_BUILD_VARIANT=$ANSWERelse echo"*Not avalid variant:$ANSWER"fi fi if[-n"$1"];then break fidone}function tapas(){choosecombo}function choosecombo(){choosesim$1echo echo choosetype$2 echo echo chooseproduct$3 echo echochoosevariant$4 echo set_stuff_for_environment printconfig}#Clear t你好svariable.It will be built up again when the vendorsetup.sh#files areincluded at the end of t你好s file.unset LUNCH_MENU_CHOICES functionadd_lunch_combo(){local new_combo=$1 local cforcin${LUNCH_MENU_CHOICES[@]};do if["$new_combo"="$c"];then return fi doneLUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]}$new_combo)}#add thedefault one here add_lunch_combo generic-eng#if we”re on linux,add thesimulator.There is aspecial case#in lunch to deal with the simulatorif["$(uname)"="Linux"];then add_lunch_combo simulator fi functionprint_lunch_menu(){local uname=$(uname)echo echo"You”re buildingon"$uname echo echo${LUNCH_MENU_CHOICES[@]}echo"Lunch menu.pickacombo:"local i=1 local choice for choice in${LUNCH_MENU_CHOICES[@]}doecho"$i.$choice"i=$(($i+1))done echo}function lunch(){local answerif["$1"];then answer=$1 else print_lunch_menu echo-n"W你好ch would youlike?[generic-eng]"read answer fi local selection=if[-z"$answer"]thenselection=generic-eng elif["$answer"="simulator"]thenselection=simulator elif(echo-n$answer|grep-q-e"^[0-9][0-9]*$")thenif[$answer-le${#LUNCH_MENU_CHOICES[@]}]thenselection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}fielif(echo-n$answer|grep-q-e"^[^\-][^\-]*-[^\-][^\-]*$")thenselection=$answer fi if[-z"$selection"]then echo echo"Invalid lunchcombo:$answer"return 1fi#special case the simulatorif["$selection"="simulator"]then export TARGET_PRODUCT=sim exportTARGET_BUILD_VARIANT=eng export TARGET_SIMULATOR=true exportTARGET_BUILD_TYPE=debug else localproduct=$(echo-n$selection|sed-e"s/-.*$//")check_product$productif[$?-ne 0]then echo echo"*Don”t have aproduct specfor:”$product”"echo"*Do you have the right repo manifest?"product=filocalvariant=$(echo-n$selection|sed-e"s/^[^\-]*-//")check_variant$variantif[$?-ne 0]then echo echo"*Invalid variant:”$variant”"echo"*Must be oneof${VARIANT_CHOICES[@]}"variant=fi if[-z"$product"-o-z"$variant"]thenecho return 1fi export TARGET_PRODUCT=$product exportTARGET_BUILD_VARIANT=$variant export TARGET_SIMULATOR=false exportTARGET_BUILD_TYPE=release fi#!simulator echo set_stuff_for_environmentprintconfig}
#gettop函数将归回mydroid目次地点路径,mydroid在全般build体系中被以为是top目次#例如mydroid地点路径为:/opt/cupcake/mydroid,则函数将归回此路径,不然归回空
#但改路径下一坨文件的相对于路径也必需不错function gettop{local TOPFILE=build/core/envsetup.mkif[-n"$TOP"-a-f"$TOP/$TOPFILE"];thenecho$TOP#要是TOP不为空,而且envsetup.mk存在,函数直接归回TOP对应路径else#不然(指找不到envsetup.mk)如次措置惩罚:if[-f$TOPFILE];then echo$PWD else#We redirect cd to/dev/null incase it’’s aliased to#a command that prints somet你好ng asaside-effect#(like pushd)local HERE=$PWDT=w你好le[\(!\(-f$TOPFILE\)\)-a\($PWD!="/"\)];do cd./dev/null T=$PWDdone#一直往上层目次顺次查找envsetup.mk是不是存在,直至到体系根目次下cd$HERE/dev/nullif[-f"$T/$TOPFILE"];then echo$T fi fifi#要是,找不到不错的envsetup.mk地点路径,函数gettop将归回空}
functionm(){T=$(gettop)if["$T"];then make-C$T$@else echo"Couldn”t locate the topof the tree.Try setting TOP."fi}functionfindmakefile(){TOPFILE=build/core/envsetup.mk#We redirect cd to/dev/nullin case it’’s aliased to#a command that prints somet你好ng asaside-effect#(like pushd)local HERE=$PWDT=w你好le[\(!\(-f$TOPFILE\)\)-a\($PWD!="/"\)];do T=$PWD if[-f"$T/Android.mk"];thenecho$T/Android.mk cd$HERE/dev/null return fi cd./dev/null donecd$HERE/dev/null}function mm(){#If we”re sitting in the root of thebuild tree,just do a#normal make.if[-f build/core/envsetup.mk-a-fMakefile];then make$@else#Find the 关上st Android.mk file.T=$(gettop)localM=$(findmakefile)if[!"$T"];then echo"Couldn”t locate the top of thetree.Try setting TOP."elif[!"$M"];then echo"Couldn”t locate amakefilefrom the current directory."else ONE_SHOT_MAKEFILE=$M make-C$T files$@fifi}function mmm(){T=$(gettop)if["$T"];then local MAKEFILE=localARGS=local DIR TO_CHOP local DASH_ARGS=$(echo"$@"|awk-v RS=""-vORS=""”/^-.*$/”)local DIRS=$(echo"$@"|awk-v RS=""-vORS=""”/^[^-].*$/”)for DIR in$DIRS;doDIR=`echo$DIR|sed-e’’s:/$:”`if[-f$DIR/Android.mk];thenTO_CHOP=`echo$T|wc-c|tr-d””`TO_CHOP=`expr$TO_CHOP+1`MFILE=`echo$PWD|cut-c${TO_CHOP}-`if["$MFILE"=""];then MFILE=$DIR/Android.mk elseMFILE=$MFILE/$DIR/Android.mk fi MAKEFILE="$MAKEFILE$MFILE"elseif["$DIR"=snod];then ARGS="$ARGS snod"elif["$DIR"=showcommands];thenARGS="$ARGS showcommands"else echo"No Android.mk in$DIR."fi fi doneONE_SHOT_MAKEFILE="$MAKEFILE"make-C$T$DASH_ARGS files$ARGS elseecho"Couldn”t locate the top of the tree.Try setting TOP."fi}functioncroot(){T=$(gettop)if["$T"];then cd$(gettop)else echo"Couldn”t locatethe top of the tree.Try setting TOP."fi}function pid(){localEXE="$1"if["$EXE"];then local PID=`adb shellps|fgrep$1|sed-e’’s/[^]**\([0-9]*\).*/\1/”`echo"$PID"else echo"usage:pidname"fi}function gdbclient(){local OUT_ROOT=$(get_abs_build_varPRODUCT_OUT)local OUT_SYMBOLS=$(get_abs_build_varTARGET_OUT_UNSTRIPPED)local OUT_SO_SYMBOLS=$(get_abs_build_varTARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)localOUT_EXE_SYMBOLS=$(get_abs_build_varTARGET_OUT_EXECUTABLES_UNSTRIPPED)local PREBUILTS=$(get_abs_build_varANDROID_PREBUILTS)if["$OUT_ROOT"-a"$PREBUILTS"];then localEXE="$1"if["$EXE"];then EXE=$1 else EXE="app_process"fi localPORT="$2"if["$PORT"];then PORT=$2 else PORT=":5039"fi local PID localPROG="$3"if["$PROG"];then PID=`pid$3`adb forward"tcp$PORT""tcp$PORT"adbshell gdbserver$PORT–attach$PID&sleep 2else echo""echo"If youhaven”t done so already,do t你好s first on thedevice:"echo"gdbserver$PORT/system/bin/$EXE"echo"or"echo"gdbserver$PORT–attach$PID"echo""fi echo|"$OUT_ROOT/gdbclient.cmds""setsolib-absolute-prefix$OUT_SYMBOLS"echo"$OUT_ROOT/gdbclient.cmds""setsolib-search-path$OUT_SO_SYMBOLS"echo"$OUT_ROOT/gdbclient.cmds""targetremote$PORT"echo"$OUT_ROOT/gdbclient.cmds"""arm-eabi-gdb-x"$OUT_ROOT/gdbclient.cmds""$OUT_EXE_SYMBOLS/$EXE"elseecho"Unable to determine build system output dir."fi}case`uname-s`inDarwin)function sgrep(){find-E.-typef-iregex”.*\.(c|h|cpp|S|java|xml)”-print0|xargs-0 grep–color-n"$@"};;*)function sgrep(){find.-typef-iregex”.*\.\(c\|h\|cpp\|S\|java\|xml\)”-print0|xargs-0grep–color-n"$@"};;esac function jgrep(){find.-typef-name"*\.java"-print0|xargs-0 grep–color-n"$@"}functioncgrep(){find.-type f-name"*\.c*"-print0|xargs-0grep–color-n"$@"}function resgrep(){for dir in`find.-name res-type d`;dofind$dir-type f-name”*\.xml”-print0|xargs-0grep–color-n"$@";done;}case`uname-s`in Darwin)functionmgrep(){find-E.-typef-iregex”.*/(Makefile|Makefile\.*|.*\.make|.*\.mak|.*\.mk)”-print0|xargs-0grep–color-n"$@"}function treegrep(){find-E.-typef-iregex”.*\.(c|h|cpp|S|java|xml)”-print0|xargs-0grep–color-n-i"$@"};;*)function mgrep(){find.-regextypeposix-egrep-iregex”(.*\/Makefile|.*\/Makefile\.*|.*\.make|.*\.mak|.*\.mk)”-typef-print0|xargs-0 grep–color-n"$@"}function treegrep(){find.-regextypeposix-egrep-iregex”.*\.(c|h|cpp|S|java|xml)”-type f-print0|xargs-0grep–color-n-i"$@"};;esac function getprebuilt{get_abs_build_varANDROID_PREBUILTS}function tracedmdump(){T=$(gettop)if[!"$T"];thenecho"Couldn”t locate the top of the tree.Try setting TOP."return filocal prebuiltdir=$(getprebuilt)localKERNEL=$T/prebuilt/android-arm/kernel/vmlinux-qemu local TRACE=$1if[!"$TRACE"];then echo"usage:tracedmdump tracename"return fiif[!-r"$KERNEL"];then echo"Error:cannot find kernel:”$KERNEL”"return filocal BASETRACE=$(basename$TRACE)if["$BASETRACE"="$TRACE"];thenTRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE fi echo"post-processingtraces."rm-f$TRACE/qtrace.dexlist post_trace$TRACE if[$?-ne 0];thenecho"*"echo"*Error:malformed trace.Did you remember to exit theemulator?"echo"*"return fi echo"generating dexlistoutput."/bin/ls$ANDROID_PRODUCT_OUT/system/framework/*.jar$ANDROID_PRODUCT_OUT/system/app/*.apk$ANDROID_PRODUCT_OUT/data/app/*.apk2/dev/null|xargs dexlist$TRACE/qtrace.dexlist echo"generating dmtracedata."q2dm-r$ANDROID_PRODUCT_OUT/symbols$TRACE$KERNEL$TRACE/dmtrace||returnecho"generating htmlfile."dmtracedump-h$TRACE/dmtrace|$TRACE/dmtrace.html||returnecho"done,see$TRACE/dmtrace.html for details"echo"orrun:"echo"traceview$TRACE/dmtrace"}#communicate with arunning device oremulator,set up necessary state,#and run the hat command.functionrunhat(){#process standard adb options localadbTarget=""if[$1="-d"-o$1="-e"];then adbTarget=$1 s你好ft1elif[$1="-s"];then adbTarget="$1$2"s你好ft 2fi localadbOptions=${adbTarget}echo adbOptions=${adbOptions}#runhat optionslocal targetPid=$1 local outputFile=$2 if["$targetPid"=""];thenecho"Usage:runhat[-d|-e|-s serial]target-pid[output-file]"returnfi#confirm hat is available if[-z$(w你好ch hat)];then echo"hat is notavailable in t你好s configuration."return fiadb${adbOptions}shell/dev/null mkdir/data/misc adb${adbOptions}shellchmod 777/data/misc#send aSIGUSR1 to cause the hprof dumpecho"Poking$targetPid and waiting for data."adb${adbOptions}shellkill-10$targetPid echo"Press enter when logcat shows\"hprof:heap dumpcompleted\""echo-n""read local availFiles=($(adb${adbOptions}shellls/data/misc|grep”^heap-dump”|sed-e’’s/.*heap-dump-/heap-dump-/”|sort-r|tr”[:space:][:cntrl:]”””))localdevFile=/data/misc/${availFiles[0]}local localFile=/tmp/$$-hprofecho"Retrieving file$devFile."adb${adbOptions}pull$devFile$localFileadb${adbOptions}shell rm$devFile echo"Running hat on$localFile"echo"Viewthe output by pointing your browser at echo""hat$localFile}functiongetbugreports(){local reports=(`adb shellls/sdcard/bugreports|tr-d”\r”`)if[!"$reports"];then echo"Could notlocate any bugreports."return fi local report for reportin${reports[@]}do echo"/sdcard/bugreports/${report}"adbpull/sdcard/bugreports/${report}${report}gunzip${report}done}functionstartviewserver(){local port=4939 if[$#-gt 0];then port=$1 fi adb shellservice call window 1i32$port}function stopviewserver(){adb shellservice call window 2}function isviewserverstarted(){adb shell servicecall window 3}function smoketest(){if[!"$ANDROID_PRODUCT_OUT"];thenecho"Couldn”t locate output files.Try running”lunch”first."&2 returnfi T=$(gettop)if[!"$T"];then echo"Couldn”t locate the top of thetree.Try setting TOP."&2 return fi(cd"$T"&&mmmtests/SmokeTest)&&adb uninstallcom.android.smoketest/dev/null&&adb uninstallcom.android.smoketest.tests/dev/null&&adbinstall$ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk&&adbinstall$ANDROID_PRODUCT_OUT/data/app/SmokeTest.apk&&adb shell aminstrument-wcom.android.smoketest.tests/android.test.InstrumentationTestRunner}#simpleshortcut to the runtest command functionruntest(){T=$(gettop)if[!"$T"];then echo"Couldn”t locate the top of thetree.Try setting TOP."&2 returnfi(cd"$T"&&development/testrunner/runtest.py$@)}#TODO:Removet你好s some time after 1June 2009 function runtest_py(){echo"runtest_py isobsolete;use runtest instead"&2 return 1}functiongodir(){if[[-z"$1"]];then echo"Usage:godir regex"return fiif[[!-f$T/filelist]];then echo-n"Creatingindex."(cd$T;find.-wholename./out-prune-o-typeffilelist)echo"Done"echo""fi local lineslines=($(grep"$1"$T/filelist|sed-e’’s/\/[^/]*$//”|sort|uniq))if[[${#lines[@]}=0]];then echo"Not found"return filocal pathname local choice if[[${#lines[@]}1]];thenw你好le[[-z"$pathname"]];do local index=1 local line for linein${lines[@]};do printf"%6s%s\n""[$index]"$line index=$(($index+1))doneecho echo-n"Select one:"unset choice read choiceif[[$choice-gt${#lines[@]}||$choice-lt 1]];then echo"Invalidchoice"continue fi pathname=${lines[$(($choice-$_arrayoffset))]}doneelse#even though zsh arrays are 1-based,$foo[0]is an aliasfor$foo[1]pathname=${lines[0]}fi cd$T/$pathname}#determine whetherarrays are zero-based(bash)or one-based(zsh)_xarray=(abc)if[-z"${_xarray[${#_xarray[@]}]}"]then _arrayoffset=1 else_arrayoffset=0 fi unset _xarray#Execute the contents of anyvendorsetup.sh files we can find.for fin`/bin/ls vendor/*/vendorsetup.shvendor/*/build/vendorsetup.sh 2/dev/null`do echo"including$f".$f doneunset f