本文使用Android版本为2.1,采用开发板为华清远见研发的FS_S5PC100A8开发板。+--------------------------------------------------------------------------------------------------------------------+1.sourcebuild/envsetup.sh这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去,我们来分析下它。envsetup.sh里的主要命令如下:?functionhelp()#显示帮助信息functionget_abs_build_var()#获取绝对变量functionget_build_var()#获取绝对变量functioncheck_product()#检查productfunctioncheck_variant()#检查变量functionsetpaths()#设置文件路径functionprintconfig()#打印配置functionset_stuff_for_environment()#设置环境变量functionset_sequence_number()#设置序号functionsettitle()#设置标题functionchoosetype()#设置typefunctionchooseproduct()#设置productfunctionchoosevariant()#设置variantfunctiontapas()#功能同choosecombo()#设置编译参数functionadd_lunch_combo()#添加lunch项目functionprint_lunch_menu()#打印lunch列表functionlunch()#配置lunchfunctionm()#makefromtopfunctionfindmakefile()#查找makefilefunctionmm()#makefromcurrentdirectoryfunctionmmm()#makethesupplieddirectoriesfunctioncroot()#回到根目录functioncproj()functionpid()functionsystemstack()functiongdbclient()functionjgrep()#查找java文件functioncgrep()#查找c/cpp文件functionresgrep()functiontracedmdump()functionrunhat()functiongetbugreports()functionstartviewserver()functionstopviewserver()functionisviewserverstarted()functionsmoketest()functionruntest()functiongodir()#跳到指定目录这是系统自动增加了一个默认的编译项generic-eng#addthedefaultonehereadd_lunch_combogeneric-eng#下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它#Executethecontentsofanyvendorsetup.shfileswecanfind.forfin`/bin/lsvendor/*/vendorsetup.shvendor/*/build/vendorsetup.sh2/dev/null`doechoincluding$f.$fdone根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envsetup.sh最后,添加上add_lunch_combomyProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项?#mkdirvendor/farsight/#touchvendor/farsight/vendorsetup.sh#echoadd_lunch_combofs100-engvendor/farsight/vendorsetup.sh这样,当我们在执行sourcebuild/envsetup.sh命令的时候,可以在shell上看到下面的信息:?includingvendor/farsight/vendorsetup.sh2.按照android官网的步骤,开始执行lunchfull-eng当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现:?You'rebuildingonLinuxgeneric-engsimulatorfs100-engLunchmenu...pickacombo:1.generic-eng2.simulator3.fs100-eng其中第3项是我们自己添加的编译项。lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。我们一直没有说明前面的fs100-eng是什么意思,现在来说明下,fs100是我定义的产品的名字,eng是产品的编译类型,除了eng外,还有user,userdebug,分别表示:eng:工程机,user:最终用户机userdebug:调试测试机由此可见,除了eng和user外,另外两个一般不能交给最终用户的,记得m8出来的时候,先放出了一部分eng工程机,然后出来了user机之后,可以用工程机换。好了,我们来分析下lunch命令干了什么??functionlunch(){localanswerif[$1];then#lunch后面直接带参数answer=$1else#lunch后面不带参数,则打印处所有的targetproduct和variant菜单提供用户选择print_lunch_menuecho-nWhichwouldyoulike?[generic-eng]readanswerfilocalselection=if[-z$answer]then#如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-engselection=generic-engelif[$answer=simulator]then#如果是模拟器selection=simulatorelif(echo-n$answer|grep-q-e^[0-9][0-9]*$)then#如果answer是选择菜单的数字,则获取该数字对应的字符串if[$answer-le${#LUNCH_MENU_CHOICES[@]}]thenselection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}fi#如果answer字符串匹配*-*模式(*的开头不能为-)elif(echo-n$answer|grep-q-e^[^\-][^\-]*-[^\-][^\-]*$)thenselection=$answerfiif[-z$selection]thenechoechoInvalidlunchcombo:$answerreturn1fi#specialcasethesimulatorif[$selection=simulator]then#模拟器模式exportTARGET_PRODUCT=simexportTARGET_BUILD_VARIANT=engexportTARGET_SIMULATOR=trueexportTARGET_BUILD_TYPE=debugelse#将product-variant模式种的product分离出来localproduct=$(echo-n$selection|sed-es/-.*$//)#检查之,调用关系check_product()-get_build_var()-build/core/config.mk比较罗嗦,不展开了check_product$productif[$?-ne0]thenechoecho**Don'thaveaproductspecfor:'$product'echo**Doyouhavetherightrepomanifest?product=fi#将product-variant模式种的variant分离出来localvariant=$(echo-n$selection|sed-es/^[^\-]*-//)#检查之,看看是否在(useruserdebugeng)范围内check_variant$variantif[$?-ne0]thenechoecho**Invalidvariant:'$variant'echo**Mustbeoneof${VARIANT_CHOICES[@]}variant=fiif[-z$product-o-z$variant]thenechoreturn1fi#导出环境变量,这儿很重要,因为后面的编译系统都是依赖于这里定义的几个变量的exportTARGET_PRODUCT=$productexportTARGET_BUILD_VARIANT=$variantexportTARGET_SIMULATOR=falseexportTARGET_BUILD_TYPE=releasefi#!simulatorecho#设置到环境变量,比较多,不再一一列出,最简单的方法setenv.txt可获得set_stuff_for_environment#打印一些主要的变量,调用关系printconfig()-get_build_var()-build/core/config.mk-build/core/envsetup.mk比较罗嗦,不展开了printconfig}由上面分析可知,lunch命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果。导出的变量如下(以实际运行情况为例)?TARGET_PRODUCT=fs100TARGET_BUILD_VARIANT=engTARGET_SIMULATOR=falseTARGET_BUILD_TYPE=release执行完上述两个步骤,就该执行:make命令了,下篇来分析。通过上篇文章,我们分析了编译android时sourcebuild/envsetup.sh和lunch命令,在执行完上述两个命令后,我们就可以进行编译android了。1.make执行make命令的结果就是去执行当前目录下的Makefile文件,我们来看下它的内容:?###DONOTEDITTHISFILE###includebuild/core/main.mk###DONOTEDITTHISFILE###呵呵,看到上面的内容,我们都会笑,这是我见过最简单的Makefile了,我们再看下build/core/main.mk在main.mk里,定义了变量TOPDIR,TOP为当前目录,BUILD_SYSTEM为build/core目录。在49行,包含了build/core/config.mk文件。后面的代码是check环境变量,所有的Makefile都通过build/core/main.mk这个文件组织在一起,它定义了一个默认goals:droid,当我们在TOP目录下,敲Make实际上就等同于我们执行makedroid。当Makeinclude所有的文件,完成对所有make我文件的解析以后就