您的位置:首页 > 移动开发 > Android开发

Android编译过程详解(一)

2012-06-08 16:54 621 查看
作者:唐攀,华清远见嵌入式培训中心讲师。
Android的优势就在于其开源,手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品,如小米,LePhone,M9等,因此,在我们在对Android的源码进行定制的时候,很有必要了解下,Android的编译过程。
如果你从来没有做过Android代码的编译,那么最官方的编译过程就是查看Android的官方网站:http://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命令了,下篇来分析。
嵌入式及3G相关资源及学习请点击:嵌入式开发视频 android开发视频 android培训 3G培训 QT培训 QT开发视频 物联网培训 物联网技术视频 嵌入式学习
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: