【Android源码 栏目提醒】:网学会员为需要Android源码 的朋友们搜集整理了Android编译系统详解(一) - 电子设计相关资料,希望对各位网友有所帮助!
Android编译系统详解一
Android的优势就在于其开源手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品如小米LePhoneM9等因此在我们在对
Android的
源码进行定制的时候很有必要了解下
Android的编译过程。
如果你从来没有做过
Android代码的编译那么最官方的编译过程就是查看
Android的官方网站http://source.
android.com/source/building.html 但是这儿只是告诉你了如何去编译一个通用的系统并没有详细告诉你细节我们跟着编译过程来了解下。
-------------------------------------------------------------------------------------------------------------------- 本文使用
Android版本为2.1采用开发板为华清远见研发的FS_S5PC100 A8开发板。
-------------------------------------------------------------------------------------------------------------------- 按照google给出的编译步骤如下 1 source build/envsetup.sh:加载命令 2 lunch选择平台编译选项 3 make执行编译 我们按照编译步骤来分析编译过程的细节最终添加自己的平台产品的编译选项。
1. source build/envsetup.sh 这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去我们来分析下它。
envsetup.sh里的主要命令如下 function help 显示帮助信息 function get_abs_build_var 获取绝对变量 function get_build_var 获取绝对变量 function check_product 检查product function check_variant 检查变量 function setpaths 设置文件路径 function printconfig 打印配置 function set_stuff_for_environment 设置环境变量 function set_sequence_number 设置序号 function settitle 设置标题 function choosetype 设置type function chooseproduct 设置product function choosevariant 设置variant function tapas 功能同choosecombo function choosecombo 设置编译参数 function add_lunch_combo 添加lunch项目 function print_lunch_menu 打印lunch列表 function lunch 配置lunch function m make from top function findmakefile 查找makefile function mm make from current directory function mmm make the supplied directories function croot 回到根目录 function cproj function pid function systemstack function gdbclient function jgrep 查找java文件 function cgrep 查找c/cpp文件 function resgrep function tracedmdump function runhat function getbugreports function startviewserver function stopviewserver function isviewserverstarted function smoketest function runtest function godir 跳到指定目录 405 add_lunch_combo函数被多次调用就是它来添加
Android编译选项 Clear this variable. It will be built up again when the vendorsetup.sh 406 files are included at the end of this file. 清空LUNCH_MENU_CHOICES变量用来保存编译选项 407 unset LUNCH_MENU_CHOICES 408 function add_lunch_combo 409 410 local new_combo1 获得add_lunch_combo被调用时的参数 411 local c 依次遍历LUNCH_MENU_CHOICES里的值其实该函数第一次调用时该值为空 412 for c in LUNCH_MENU_CHOICES do 413 if new_combo c then 如果参数里的值已经存在于LUNCH_MENU_CHOICES变量里则返回 414 return 415 fi 416 done 如果参数的值不存在则添加到LUNCH_MENU_CHOICES变量里 417 LUNCH_MENU_CHOICESLUNCH_MENU_CHOICES new_combo 418 这是系统自动增加了一个默认的编译项 generic-eng 420 add the default one here 421 add_lunch_combo generic-eng 调用上面的add_lunch_combo函数将generic-eng作为参数传递过去 422 423 if were on linux add the simulator. There is a special case 424 in lunch to deal with the simulator 425 if uname Linux then 426 add_lunch_combo simulator 427 fi 下面的代码很重要它要从vendor目录下查找vendorsetup.sh文件如果查到了就加载它 1037 Execute the contents of any vendorsetup.sh files we can find. 1038 for f in /bin/ls vendor//vendorsetup.sh vendor//build/vendorsetup.sh 2 /dev/null 1039 do 1040 echo including f 1041 . f 执行找到的脚本其实里面就是厂商自己定义的编译选项 1042 done 1043 unset f envsetup.sh其主要作用如下 1. 加载了编译时使用到的函数命令如helplunchmmmmmm等 2. 添加了两个编译选项generic-eng和simulator这两个选项是系统默认选项 3. 查找vendor//和vendor//build/目录下的vendorsetup.sh如果存在的话加载执行它添加厂商自己定义产品的编译选项 其实上述第3条是向编译系统添加了厂商自己定义产品的编译选项里面的代码就是add_lunch_combo xxx-xxx。
根据上面的内容可以推测出如果要想定义自己的平台产品编译项简单的办法是直接在envsetup.sh最后添加上add_lunch_combo myProduct-eng当然这么做不太符合上面代码最后的本意我们还是老实的在vendor目录下创建自己公司名字然后在公司目录下创建一个新的vendorsetup.sh在里面添加上自己的产品编译项 plain view plaincopy 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 plaincopy 1. including vendor/farsight/vendorsetup.sh 2. 按照
android官网的步骤开始执行lunch full-eng 当然如果你按上述命令执行它编译的还是通用的eng版本系统不是我们个性定制系统我们可以执行lunch命令它会打印出一个选择菜单列出可用的编译选项 如果你按照第一步中添加了vendorsetup.sh那么你的选项中会出现 plain view plaincopy 1. Youre building on Linux 2. 3. generic-eng simulator fs100-eng 4. Lunch menu... pick a combo: 5. 1. generic-eng 6. 2. simulator 7. 3. fs100-eng 其中第3项是我们自己添加的编译项。
lunch命令是envsetup.sh里定义的一个命令用来让用户选择编译项来定义Product和编译过程中用到的全局变量。
我们一直没有说明前面的fs100-eng是什么意思现在来说明下fs100是我定义的产品的名字eng是产品的编译类型除了eng外还有user userdebug分别表示 eng: 工程机 user:最终用户机 userdebug:调试测试机 tests:测试机 由此可见除了eng和user外另外两个一般不能交给最终用户的记得m8出来的时候先放出了一部分eng工程机然后出来了user机之后可以用工程机换。
那么这四个类型是干什么用的呢其实在main.mk里有说明在
Android的
源码里每一个目标也可以看成工程目录都有一个
Android.mk的makefile每个目标的
Android.mk中有一个类型声明LOCAL_MODULE_TAGS这个TAGS就是用来指定当前的目标编译完了属于哪个分类里。
PS:
Android.mk和Linux里的makefile不太一样它是
Android编译系统自己定义的一个makefile来方便编译成cc的动态、静态库或可执行程序或java库或
android的程序 好了我们来分析下lunch命令干了什么 function lunch local answer lunch后面直接带参数的情况则编译项为指定的参数 1 if 1 then answer1 else lunch后面不带参数的情况则调用print_lunch_menu函数打印所有的target product和variant菜单提供用户选择 print_lunch_menu echo -n Which would you like generic-eng read answer 读取用户选择的结果注意这儿可以是数字也可以是字符串的选项内容 fi local selection 如果用户在菜单中没有输入任何内容直接回车则为系统缺省的generic-eng编译项 if -z answer then selectiongeneric-eng elif answer simulator then 如果是用户输入的是模拟器simulator selectionsimulator 如果answer是菜单中的数字则获取该数字 elif echo -n answer grep -q -e 0-90-9 then if answer -le LUNCH_MENU_CHOICES 如果用户输入的菜单数字不合法超过全部选项数组的元素个数 LUNCH_MENU_CHOICES是指取得LUNCH_MENU_CHOICES这个数组的元素个数LUNCH_MENU_CHOICES指引用数组里的全部元素以列表返回 then selectionLUNCH_MENU_CHOICESanswer-_arrayoffset 这儿通过answer - _arrayoffset来引用用户输入的数字对应的数组LUNCH_MENU_CHOICES中的编译项其中_arrayoffset这个变量表示是否是数组下标从0开始这儿其值为1 fi 如果 answer字符串匹配 -模式开头结尾不能为- elif echo -n answer grep -q -e ----- then selectionanswer fi 如果selection为空出错退出 if -z selection then echo echo Invalid lunch combo: answer return 1 fi special case the simulator if selection simulator 如果用户选项为使用模拟器 then 导出4个环境变量这4个环境变量将指定编译系统编译为模拟器 export TARGET_PRODUCTsim 产品变量 export TARGET_BUILD_VARIANTeng 版本型号变量 export TARGET_SIMULATORtrue 编译在模拟器中 export TARGET_BUILD_TYPEdebug 类型变量 else 将 product-variant模式中的product分离出来sed命令是将-后面的字符串替换为空串也就是只保留-前面的内容 local productecho -n selection sed -e s/-.// 检查之调用关系 check_product-get_build_var-build/core/config.mk比较罗嗦不展开了 check_product product if -ne 0 then echo echo Dont have a product spec for: product echo Do you have the right repo manifest product fi 将 product-variant模式中的variant分离出来sed命令将-前面的内容替换为空串 local variantecho -n selection sed -e s/--// 检查之看看是否在 user userdebug eng 范围内 check_variant variant if -ne 0 then echo echo Invalid variant: variant echo Must be one of VARIANT_CHOICES variant fi if -z product -o -z variant 再次检查两个变量是否为空 then echo return 1 fi 导出4个环境变量和上面模拟器的对比着看这里很重要因为后面的编译系统都是依赖于这里定义的几个变量的 export TARGET_PRODUCTproduct export TARGET_BUILD_VARIANTvariant export TARGET_SIMULATORfalse export TARGET_BUILD_TYPErelease fi simulator echo 设置到环境变量比较多不再一一列出最简单的方法 set env.txt 可获得 set_stuff_for_environment 打印一些主要的变量 调用关系 printconfig-get_build_var-build/core/config.mk-build/core/envsetup.mk 比较罗嗦不展开了 printconfig 由上面分析可知lunch命令可以带参数和不带参数最终导出一些重要的环境变量从而影响编译系统的编译结果。
导出的变量如下以实际运行情况为例 plain view plaincopy 1. TARGET_PRODUCTfs100 2. TARGET_BUILD_VARIANTeng 3. TARGET_SIMULATORfalse 4. TARGET_BUILD_TYPErelease 执行完上述两个步骤就该执行make命令了当然如果你按照上述两个步骤做完执行make之后肯定会出问题我们还要做一些其它的操作下篇来分析。