. build/envsetup.sh2.执行lunch命令,选择你要的target
3.make
这些步骤的确很简单,但是背后实际做了什么呢?这篇文章会分析envsetup.sh文件,对shell不熟悉的同学可以打开(http://www.gnu.org/software/bash/manual/bash.html),遇到不懂的地方可以参考一下。
首先我们看envsetup.sh,里面声明了很多方法,但是我们用户一般就使用lunch就够了,所以不一一讲解,不然会昏了。在执行完这个文件后,这些方法都可以在当前的shell里使用,lunch便是其中的一个方法,所以我们必须先执行envsetup.sh,才能使用lunch。我们看看除了方法的声明外,它还做了什么。
77行:
VARIANT_CHOICES=(user userdebug eng)
191-257行:
case `uname -s` in Linux) function choosesim() { echo "Build for the simulator or the device?" echo " 1. Device" echo " 2. Simulator" echo export TARGET_SIMULATOR= local ANSWER while [ -z $TARGET_SIMULATOR ] do echo -n "Which would you like? [1] " if [ -z "$1" ] ; then read ANSWER else echo $1 ANSWER=$1 fi case $ANSWER in "") export TARGET_SIMULATOR=false ;; 1) export TARGET_SIMULATOR=false ;; Device) export TARGET_SIMULATOR=false ;; 2) export TARGET_SIMULATOR=true ;; Simulator) export TARGET_SIMULATOR=true ;; *) echo echo "I didn't understand your response. Please try again." echo ;; esac if [ -n "$1" ] ; then break fi done set_stuff_for_environment } ;; *) function choosesim() { echo "Only device builds are supported for" `uname -s` echo " Forcing TARGET_SIMULATOR=false" echo if [ -z "$1" ] then echo -n "Press enter: " read fi export TARGET_SIMULATOR=false set_stuff_for_environment } ;; esac
这是shell的一个case,其实就像我们平时c,java里面的switch。`uname -s`返回的是内核的名字,如果你使用的是基于Linux内核的系统,如Ubuntu,Fedora,OpenSuse等,此时则返回Linux,使用Mac的就返回Darwin。这个case是根据Linux内核和其他内核定义不同choosesim方法。
434行:
unset LUNCH_MENU_CHOICES清除LUNCH_MENU_CHOICES变量的值 448-449行:
add_lunch_combo full-eng add_lunch_combo full_x86-eng
这2行代码的调用了add_lunch_combo方法
453-455行:function add_lunch_combo() { local new_combo=$1 local c for c in ${LUNCH_MENU_CHOICES[@]} ; do if [ "$new_combo" = "$c" ] ; then return fi done LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo) }
可以看出是给LUNCH_MENU_CHOICES数组增加内容。
528行:alias bib=breakfastif [ "$(uname)" = "Linux" ] ; then add_lunch_combo simulator fi再次调用uname,获得内核名字,如是Linux则添加simulator的选项。
924-938行:设定一个别名,以后调用bib就等于调用breakfast。
955-980行:case `uname -s` in Darwin) function sgrep() { find -E . -type f -iregex '.*\.(c|h|cpp|S|java|xml|sh|mk)' -print0 | xargs -0 grep --color -n "$@" } ;; *) function sgrep() { find . -type f -iregex '.*\.\(c\|h\|cpp\|S\|java\|xml\|sh\|mk\)' -print0 | xargs -0 grep --color -n "$@" } ;; esac
又一次调用了uname,根据Mac和其他系统的find命令不同,声明了其对应的sgrep方法。
1590-1597行:case `uname -s` in Darwin) function mgrep() { find -E . -type f -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -print0 | xargs -0 grep --color -n "$@" } function treegrep() { find -E . -type f -iregex '.*\.(c|h|cpp|S|java|xml)' -print0 | xargs -0 grep --color -n -i "$@" } ;; *) function mgrep() { find . -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -type f -print0 | xargs -0 grep --color -n "$@" } function treegrep() { find . -regextype posix-egrep -iregex '.*\.(c|h|cpp|S|java|xml)' -type f -print0 | xargs -0 grep --color -n -i "$@" } ;; esac
跟上者一样。
_xarray=(a b c) if [ -z "${_xarray[${#_xarray[@]}]}" ] then _arrayoffset=1 #zero-based (bash) else _arrayoffset=0 #one-based (zsh) fi unset _xarray
这里是要测试当前shell的数组第一个元素的index是从1还是0开始。这里有点复杂,有的同学可能没看懂,那我就慢慢解释一下了,首先
${#_xarray[@]}是获取_xarry数组的元素个数,这里返回3。然后
${_xarray[${#_xarray[@]}]}就是获取_xarray中index为3的元素,如果使用的bash,这里返回空,因为bash是zero-based,如果是zsh,则返回 'c' ,因为zsh是one-based。如果返回的是空,也就是当前使用bash,则设置_arrayoffset = 1 , 否则设置为0.
这里一开始不太明白,因为bash是zero-based的,不是应该设置_arrayoffset = 0 吗?怎么倒过来了,想了好久,后来看了下它的具体使用情况,如下篇文章会说到的lunch命令,直接执行lunch命令时,会列出各种combo:
You're building on Linux Lunch menu... pick a combo: 1. full-eng 2. full_x86-eng 3. simulator 4. generic_sholest-userdebug 5. cyanogen_ace-eng 6. cyanogen_anzu-eng 7. cyanogen_blade-eng 8. cyanogen_bravo-eng 9. cyanogen_bravoc-eng 10. cyanogen_buzz-eng 11. cyanogen_c660-eng 12. cyanogen_click-eng 13. cyanogen_captivatemtd-eng 14. cyanogen_coconut-eng 15. cyanogen_cooper-eng 16. cyanogen_crespo-eng 17. cyanogen_crespo4g-eng 18. cyanogen_desirec-eng 19. cyanogen_dream_sapphire-eng 20. cyanogen_droid2-eng 21. cyanogen_droid2we-eng 22. cyanogen_e510-eng 23. cyanogen_e730-eng 24. cyanogen_encore-eng 25. cyanogen_epicmtd-eng 26. cyanogen_es209ra-eng 27. cyanogen_espresso-eng 28. cyanogen_fascinatemtd-eng 29. cyanogen_galaxys2-eng 30. cyanogen_galaxys2att-eng 31. cyanogen_galaxysbmtd-eng 32. cyanogen_galaxysmtd-eng 33. cyanogen_generic-eng 34. cyanogen_glacier-eng 35. cyanogen_hallon-eng 36. cyanogen_hero-eng 37. cyanogen_heroc-eng 38. cyanogen_inc-eng 39. cyanogen_iyokan-eng 40. cyanogen_jordan-eng 41. cyanogen_legend-eng 42. cyanogen_leo-eng 43. cyanogen_liberty-eng 44. cyanogen_mango-eng 45. cyanogen_mecha-eng 46. cyanogen_mesmerizemtd-eng 47. cyanogen_mimmi-eng 48. cyanogen_morrison-eng 49. cyanogen_motus-eng 50. cyanogen_one-eng 51. cyanogen_olympus-eng 52. cyanogen_p500-eng 53. cyanogen_p920-eng 54. cyanogen_p925-eng 55. cyanogen_p970-eng 56. cyanogen_p990-eng 57. cyanogen_p999-eng 58. cyanogen_passion-eng 59. cyanogen_robyn-eng 60. cyanogen_saga-eng 61. cyanogen_satsuma-eng 62. cyanogen_shadow-eng 63. cyanogen_shakira-eng 64. cyanogen_sholes-eng 65. cyanogen_showcasemtd-eng 66. cyanogen_smb_a1002-eng 67. cyanogen_smb_a1004-eng 68. cyanogen_smb_a1011-eng 69. cyanogen_smb_b9701-eng 70. cyanogen_smultron-eng 71. cyanogen_speedy-eng 72. cyanogen_supersonic-eng 73. cyanogen_tass-eng 74. cyanogen_u8150-eng 75. cyanogen_u8220-eng 76. cyanogen_urushi-eng 77. cyanogen_v9-eng 78. cyanogen_vega-eng 79. cyanogen_vision-eng 80. cyanogen_vivo-eng 81. cyanogen_vivow-eng 82. cyanogen_z71-eng 83. cyanogen_zeppelin-eng 84. cyanogen_zero-eng 85. cyanogen_zeus-eng 86. cyanogen_zeusc-eng 87. cyanogen_sholest-eng Which would you like? [full-eng]
可以看到是从序号1开始递增的,这时用户是输入序号或者相应的字符串以选择想要的combo,如果用户使用了序号,看看lunch中的处理:selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
answer变量是用户输入的数值,如我输入了87,要获得相应的字符串,则必须减去_arrayoffset,就是减去1,也就解释了为什么当使用bash时要设_arrayoffset为1了!
1600-1605行:
for f in `{ setopt nullglob; /bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh device/*/*/vendorsetup.sh; } 2> /dev/null` do echo "including $f" . $f done unset f
setopt是zsh的东西,我使用bash就没管它了。这里使用ls列出了vendor下指定位置的vendorsetup.sh,把文件列表传给for循环,echo打印出include了哪个文件,并且执行了它。
其实vendorsetup.sh的内容就是一堆add_lunch_combo,到此为止,我们的envsetup.sh已经执行完了,其实它的作用主要是2点:
1.声明了之后会使用的各种方法和变量。
2.设定好lunch命令需要使用的combos。