| 关键词: nbsp function product variant lunch 变量 编译 build echo answer |
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] 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 () # 跳到指定目录 # 这是系统自动增加了一个默认的编译项 generic-eng # add the default one here <strong><span style="color:#ff0000;">add_lunch_combo generic-eng</span></strong> # 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它 # Execute the contents of any vendorsetup.sh files we can find. <strong><span style="color:#ff0000;">for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null` do echo "including $f" . $f done</span></strong> function help() # 显示帮助信息function get_abs_build_var() # 获取绝对变量function get_build_var() # 获取绝对变量function check_product() # 检查productfunction check_variant() # 检查变量function setpaths() # 设置文件路径function printconfig() # 打印配置function set_stuff_for_environment() # 设置环境变量function set_sequence_number() # 设置序号function settitle() # 设置标题function choosetype() # 设置typefunction chooseproduct() # 设置productfunction choosevariant() # 设置variantfunction tapas() # 功能同choosecombofunction choosecombo() # 设置编译参数function add_lunch_combo() # 添加lunch项目function print_lunch_menu() # 打印lunch列表function lunch() # 配置lunchfunction m() # make from topfunction findmakefile() # 查找makefilefunction mm() # make from current directoryfunction mmm() # make the supplied directoriesfunction 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 () # 跳到指定目录 # 这是系统自动增加了一个默认的编译项 generic-eng# add the default one here<strong><span style="color:#ff0000;">add_lunch_combo generic-eng</span></strong> # 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它# Execute the contents of any vendorsetup.sh files we can find.<strong><span style="color:#ff0000;">for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null`do echo "including $f" . $fdone</span></strong>根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envsetup.sh最后,添加上add_lunch_combo myProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项 [plain] #mkdir vendor/farsight/ #touch vendor/farsight/vendorsetup.sh #echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh #mkdir vendor/farsight/#touch vendor/farsight/vendorsetup.sh#echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh这样,当我们在执行source build/envsetup.sh命令的时候,可以在shell上看到下面的信息: [plain] including vendor/farsight/vendorsetup.sh including vendor/farsight/vendorsetup.sh2. 按照android官网的步骤,开始执行lunch full-eng 当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项 如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现: [plain] You're building on Linux generic-eng simulator fs100-eng Lunch menu... pick a combo: 1. generic-eng 2. simulator 3. fs100-eng You're building on Linux generic-eng simulator fs100-engLunch menu... pick a combo: 1. generic-eng 2. simulator 3. fs100-eng其中第3项是我们自己添加的编译项。 lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。 我们一直没有说明前面的fs100-eng是什么意思,现在来说明下,fs100是我定义的产品的名字,eng是产品的编译类型,除了eng外,还有user, userdebug,分别表示: eng: 工程机, user:最终用户机 userdebug:调试测试机 由此可见,除了eng和user外,另外两个一般不能交给最终用户的,记得m8出来的时候,先放出了一部分eng工程机,然后出来了user机之后,可以用工程机换。 好了,我们来分析下lunch命令干了什么? [plain] function lunch() { local answer if [ "$1" ] ; then # lunch后面直接带参数 answer=$1 else # lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择 print_lunch_menu echo -n "Which would you like? [generic-eng] " read answer fi local selection= if [ -z "$answer" ] then # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng selection=generic-eng elif [ "$answer" = "simulator" ] then # 如果是模拟器 selection=simulator elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$") then # 如果answer是选择菜单的数字,则获取该数字对应的字符串 if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] then selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]} fi # 如果 answer字符串匹配 *-*模式(*的开头不能为-) elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$") then selection=$answer fi if [ -z "$selection" ] then echo echo "Invalid lunch combo: $answer" return 1 fi # special case the simulator if [ "$selection" = "simulator" ] then # 模拟器模式 www.2cto.com export TARGET_PRODUCT=sim export TARGET_BUILD_VARIANT=eng export TARGET_SIMULATOR=true export TARGET_BUILD_TYPE=debug else # 将 product-variant模式种的product分离出来 local product=$(echo -n $selection | sed -e "s/-.*$//") # 检查之,调用关系 check_product()->get_build_var()->build/core/config.mk比较罗嗦,不展开了 check_product $product if [ $? -ne 0 ] then echo echo "** Don't have a product spec for: '$product'" echo "** Do you have the right repo manifest?" product= fi # 将 product-variant模式种的variant分离出来 local variant=$(echo -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 <span style="white-space:pre"> </span># 导出环境变量,这儿很重要,因为后面的编译系统都是依赖于这里定义的几个变量的 export TARGET_PRODUCT=$product export TARGET_BUILD_VARIANT=$variant export TARGET_SIMULATOR=false export TARGET_BUILD_TYPE=release fi # !simulator echo # 设置到环境变量,比较多,不再一一列出,最简单的方法 set >env.txt 可获得 set_stuff_for_environment # 打印一些主要的变量, 调用关系 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk 比较罗嗦,不展开了 printconfig } function lunch(){ local answer if [ "$1" ] ; then # lunch后面直接带参数 answer=$1 else # lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择 print_lunch_menu echo -n "Which would you like? [generic-eng] " read answer fi local selection= if [ -z "$answer" ] then # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng selection=generic-eng elif [ "$answer" = "simulator" ] then # 如果是模拟器 selection=simulator elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$") then # 如果answer是选择菜单的数字,则获取该数字对应的字符串 if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] then selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]} fi # 如果 answer字符串匹配 *-*模式(*的开头不能为-) elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$") then selection=$answer fi if [ -z "$selection" ] then echo echo "Invalid lunch combo: $answer" return 1 fi # special case the simulator if [ "$selection" = "simulator" ] then # 模拟器模式 export TARGET_PRODUCT=sim export TARGET_BUILD_VARIANT=eng export TARGET_SIMULATOR=true export TARGET_BUILD_TYPE=debug else # 将 product-variant模式种的product分离出来 local product=$(echo -n $selection | sed -e "s/-.*$//") # 检查之,调用关系 check_product()->get_build_var()->build/core/config.mk比较罗嗦,不展开了 check_product $product if [ $? -ne 0 ] then echo echo "** Don't have a product spec for: '$product'" echo "** Do you have the right repo manifest?" product= fi # 将 product-variant模式种的variant分离出来 local variant=$(echo -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<span style="white-space:pre"> </span># 导出环境变量,这儿很重要,因为后面的编译系统都是依赖于这里定义的几个变量的 export TARGET_PRODUCT=$product export TARGET_BUILD_VARIANT=$variant export TARGET_SIMULATOR=false export TARGET_BUILD_TYPE=release 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] TARGET_PRODUCT=fs100 TARGET_BUILD_VARIANT=eng TARGET_SIMULATOR=false TARGET_BUILD_TYPE=release TARGET_PRODUCT=fs100 TARGET_BUILD_VARIANT=eng TARGET_SIMULATOR=false TARGET_BUILD_TYPE=release执行完上述两个步骤,就该执行:make命令了,下篇来分析。 摘自 mr_raptor的专栏 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|