Android的优势就在于其开源,手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品,如小米,LePhone,M9等,因此,在我们在对Android的源码进行定制的时候,很有必要了解下,Android的编译过程。
如果你从来没有做过Android代码的编译,那么官方的编译过程就是查看Android的官方网站://source.android.com/source/building.html
但是,这儿只是告诉你了如何去编译一个通用的系统,并没有详细告诉你细节,我们跟着编译过程来了解下。
+--------------------------------------------------------------------------------------------+
本文使用Android版本为2.1,采用开发板为华清远见研发的FS_S5PC100 A8开发板。
+--------------------------------------------------------------------------------------------+
1、 source build/envsetup.sh
这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去,我们来分析下它。
envsetup.sh里的主要命令如下:
[plain] view plaincopyprint?
1. function help() # 显示帮助信息
2. function get_abs_build_var() # 获取绝对变量
3. function get_build_var() # 获取绝对变量
4. function check_product() # 检查product
5. function check_variant() # 检查变量
6. function setpaths() # 设置文件路径
7. function printconfig() # 打印配置
8. function set_stuff_for_environment() # 设置环境变量
9. function set_sequence_number() # 设置序号
10. function settitle() # 设置标题
11. function choosetype() # 设置type
12. function chooseproduct() # 设置product
13. function choosevariant() # 设置variant
14. function tapas() # 功能同choosecombo
15. function choosecombo() # 设置编译参数
16. function add_lunch_combo() # 添加lunch项目
17. function print_lunch_menu() # 打印lunch列表
18. function lunch() # 配置lunch
19. function m() # make from top
20. function findmakefile() # 查找makefile
21. function mm() # make from current directory
22. function mmm() # make the supplied directories
23. function croot() # 回到根目录
24. function cproj()
25. function pid()
26. function systemstack()
27. function gdbclient()
28. function jgrep() # 查找java文件
29. function cgrep() # 查找c/cpp文件
30. function resgrep()
31. function tracedmdump()
32. function runhat()
33. function getbugreports()
34. function startviewserver()
35. function stopviewserver()
36. function isviewserverstarted()
37. function smoketest()
38. function runtest()
39. function godir () # 跳到指定目录
40.
41.
42. # 这是系统自动增加了一个默认的编译项 generic-eng
43. # add the default one here
44. <strong><span style="color:#ff0000;">add_lunch_combo generic-eng</span></strong>
45.
46.
47. # 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它
48. # Execute the contents of any vendorsetup.sh files we can find.
49. <strong><span style="color:#ff0000;">for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null`
50. do
51. echo "including $f"
52. . $f
53. done</span></strong>
根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envsetup.sh后,添加上add_lunch_combo myProduct-eng,当然这么做,不太符合上面代码后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项。
[plain] view plaincopyprint?
1. #mkdir vendor/farsight/
2. #touch vendor/farsight/vendorsetup.sh
3. #echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh
这样,当我们在执行source build/envsetup.sh命令的时候,可以在shell上看到下面的信息:
[plain] view plaincopyprint?
1. including vendor/farsight/vendorsetup.sh
2. 按照android官网的步骤,开始执行lunch full-eng
当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项
如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现:
[plain] view plaincopyprint?
1. You're building on Linux
2.
3. generic-eng simulator fs100-eng
4. Lunch menu... pick a combo:
5. generic-eng
6. simulator
7. fs100-eng
其中第3项是我们自己添加的编译项。
lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。
我们一直没有说明前面的fs100-eng是什么意思,现在来说明下,fs100是我定义的产品的名字,eng是产品的编译类型,除了eng外,还有user, userdebug,分别表示:
eng: 工程机,
user:终用户机
userdebug:调试测试机
由此可见,除了eng和user外,另外两个一般不能交给终用户的,记得m8出来的时候,先放出了一部分eng工程机,然后出来了user机之后,可以用工程机换。
好了,我们来分析下lunch命令干了什么?
[plain] view plaincopyprint?
1. function lunch()
2. {
3. local answer
4.
5. if [ "$1" ] ; then
6. # lunch后面直接带参数
7. answer=$1
8. else
9. # lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择
10. print_lunch_menu
11. echo -n "Which would you like? [generic-eng] "
12. read answer
13. fi
14.
15. local selection=
16.
17. if [ -z "$answer" ]
18. then
19. # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng
20. selection=generic-eng
21. elif [ "$answer" = "simulator" ]
22. then
23. # 如果是模拟器
24. selection=simulator
25. elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
26. then
27. # 如果answer是选择菜单的数字,则获取该数字对应的字符串
28. if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
29. then
30. selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
31. fi
32. # 如果 answer字符串匹配 *-*模式(*的开头不能为-)
33. elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
34. then
35. selection=$answer
36. fi
37.
38. if [ -z "$selection" ]
39. then
40. echo
41. echo "Invalid lunch combo: $answer"
42. return 1
43. fi
44.
45. # special case the simulator
46. if [ "$selection" = "simulator" ]
47. then
48. # 模拟器模式
49. export TARGET_PRODUCT=sim
50. export TARGET_BUILD_VARIANT=eng
51. export TARGET_SIMULATOR=true
52. export TARGET_BUILD_TYPE=debug
53. else
54.
55. # 将 product-variant模式种的product分离出来
56. local product=$(echo -n $selection | sed -e "s/-.*$//")
57.
58. # 检查之,调用关系 check_product()->get_build_var()->build/core/config.mk比较罗嗦,不展开了
59. check_product $product
60. if [ $? -ne 0 ]
61. then
62. echo
63. echo "** Don't have a product spec for: '$product'"
64. echo "** Do you have the right repo manifest?"
65. product=
66. fi
67.
68. # 将 product-variant模式种的variant分离出来
69. local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
70.
71. # 检查之,看看是否在 (user userdebug eng) 范围内
72. check_variant $variant
73. if [ $? -ne 0 ]
74. then
75. echo
76. echo "** Invalid variant: '$variant'"
77. echo "** Must be one of ${VARIANT_CHOICES[@]}"
78. variant=
79. fi
80.
81. if [ -z "$product" -o -z "$variant" ]
82. then
83. echo
84. return 1
85. fi
86. <span style="white-space:pre"> </span># 导出环境变量,这儿很重要,因为后面的编译系统都是依赖于这里定义的几个变量的
87. export TARGET_PRODUCT=$product
88. export TARGET_BUILD_VARIANT=$variant
89. export TARGET_SIMULATOR=false
90. export TARGET_BUILD_TYPE=release
91. fi # !simulator
92.
93. echo
94.
95. # 设置到环境变量,比较多,不再一一列出,简单的方法 set >env.txt 可获得
96. set_stuff_for_environment
97. # 打印一些主要的变量, 调用关系 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk 比较罗嗦,不展开了
98. printconfig
99. }
由上面分析可知,lunch命令可以带参数和不带参数,终导出一些重要的环境变量,从而影响编译系统的编译结果。导出的变量如下(以实际运行情况为例)
[plain] view plaincopyprint?
1. TARGET_PRODUCT=fs100
2. TARGET_BUILD_VARIANT=eng
3. TARGET_SIMULATOR=false
4. TARGET_BUILD_TYPE=release
执行完上述两个步骤,就该执行:make命令了,下篇来分析。