Android编译环境的初始化

一般初始化android的编译环境,最简单的方法是这样的:

1. step 1: . build/envsetup.sh

2. step 2: lunch


下面我们看看这两个命令的底层细节是怎样的。

step 1 source了 build/envsetup.sh这文件,这个文件里面有什么内容呢? 看了一下全部是各种函数

 1 function hmm() {                                                                                                                                                                                               
   2 cat <<EOF
   3 Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
   4 - lunch:   lunch <product_name>-<build_variant>
   5 - tapas:   tapas [<App1> <App2> ...] [arm|x86|mips|armv5] [eng|userdebug|user]
   6 - croot:   Changes directory to the top of the tree.
   7 - m:       Makes from the top of the tree.
   8 - mm:      Builds all of the modules in the current directory, but not their dependencies.
   9 - mmm:     Builds all of the modules in the supplied directories, but not their dependencies.
  10 - mma:     Builds all of the modules in the current directory, and their dependencies.
  11 - mmma:    Builds all of the modules in the supplied directories, and their dependencies.
  12 - cgrep:   Greps on all local C/C++ files.
  13 - jgrep:   Greps on all local Java files.
  14 - resgrep: Greps on all local res/*.xml files.
  15 - godir:   Go to the directory containing a file.
  16 
  17 Look at the source to view more functions. The complete list is:
  18 EOF
  19     T=$(gettop)
  20     local A
  21     A=""
  22     for i in `cat $T/build/envsetup.sh | sed -n "/^function /s/function \([a-z_]*\).*/\1/p" | sort`; do
  23       A="$A $i"
  24     done
  25     echo $A
  26 }

上面是一个例子,也是一个帮助信息,可以列出了当前文件中所有的函数。然后看文件的最后实际执行了一小段脚本:

1328 if [ "x$SHELL" != "x/bin/bash" ]; then                                                                                                                                                                         
1329     case `ps -o command -p $$` in
1330         *bash*)
1331             ;;
1332         *)
1333             echo "WARNING: Only bash is supported, use of other shell would lead to erroneous results"
1334             ;;
1335     esac
1336 fi
1337 
1338 # Execute the contents of any vendorsetup.sh files we can find.
1339 for f in `test -d device && find device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null` \
1340          `test -d vendor && find vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null`
1341 do
1342     echo "including $f"
1343     . $f
1344 done
1345 unset f
1346 
1347 addcompletions


做了两件重要的事情 : (1)source device,vendor目录下面的vendorsetup.sh文件 (2)添加命令adb 补全功能(无关紧要)


vendorsetup.sh中都只有一行,举个例子 device/asus/flo/vendorsetup.sh有这么一行:

17 add_lunch_combo aosp_flo-userdebug 

那么add_lunch_combo做了什么呢?他吧aosp_flo-userdebug  这些变量放到一个叫做LUNCH_MENU_CHOICES的数组里面。看看代码吧:

413 # Clear this variable.  It will be built up again when the vendorsetup.sh
 414 # files are included at the end of this file.
 415 unset LUNCH_MENU_CHOICES
 416 function add_lunch_combo()                                                                                                                                                                                     
 417 {
 418     local new_combo=$1
 419     local c
 420     for c in ${LUNCH_MENU_CHOICES[@]} ; do
 421         if [ "$new_combo" = "$c" ] ; then
 422             return
 423         fi
 424     done
 425     LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
 426 }

如果这个变量没有重复的话,就放到数组里面吧。

综上所述,. build/envsetup.sh 的执行就是添加了各种函数,而且建立起了一个数组,这个数组是所有(厂商——设备)的组合,以供你下面选择你需要编译那个设备的代码。





step 2: 下面是step 2 : lunch 的执行细节。

lunch这个函数有两个用法,一个是有参数的用法,另一个是没有参数的用法。 有参数的那么参数就是你要选择的那个设备。没参数的时候会把所有设备列出来,供你选择。

当然,这个列出的菜单,有名字也有前面的数字标号,你可以直接填数字,这样会快,不用敲一大堆字母了。

之后会对你的输入(这个输入包括参数和选择)做sanity check。最后通过你的选择得到两个很重要的变量,并且export粗来:

515 
 516     export TARGET_PRODUCT=$product                                                                                                                                                                             
 517     export TARGET_BUILD_VARIANT=$variant
 518     export TARGET_BUILD_TYPE=release

最后把搜集到的信息打印粗来。整个lunch过程到此结束。多说无意,上代码吧:

453 function lunch()
 454 {
 455     local answer
 456 
 457     if [ "$1" ] ; then
 458         answer=$1
 459     else                                                                                                                                                                                                       
 460         print_lunch_menu
 461         echo -n "Which would you like? [aosp_arm-eng] "
 462         read answer
 463     fi
 464 
 465     local selection=
 466 
 467     if [ -z "$answer" ]
 468     then
 469         selection=aosp_arm-eng
 470     elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
 471     then
 472         if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
 473         then
 474             selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
 475         fi
 476     elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
 477     then
 478         selection=$answer
 479     fi
 480 
 481     if [ -z "$selection" ]
 482     then
 483         echo
 484         echo "Invalid lunch combo: $answer"
 485         return 1
 486     fi
 487 
 488     export TARGET_BUILD_APPS=
 489 
 490     local product=$(echo -n $selection | sed -e "s/-.*$//")
 491     check_product $product
 492     if [ $? -ne 0 ]
 493     then
 494         echo
 495         echo "** Don't have a product spec for: '$product'"
 496         echo "** Do you have the right repo manifest?"
 497         product=
 498     fi
 499 
 500     local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
 501     check_variant $variant
 502     if [ $? -ne 0 ]
 503     then
 504         echo
 505         echo "** Invalid variant: '$variant'"

506         echo "** Must be one of ${VARIANT_CHOICES[@]}"
 507         variant=
 508     fi
 509 
 510     if [ -z "$product" -o -z "$variant" ]
 511     then
 512         echo
 513         return 1
 514     fi
 515 
 516     export TARGET_PRODUCT=$product
 517     export TARGET_BUILD_VARIANT=$variant
 518     export TARGET_BUILD_TYPE=release
 519 
 520     echo
 521 
 522     set_stuff_for_environment
 523     printconfig
 524 }

这里面对参数用sed进行拆分,得到prduct和variant .然后调用 check_product 和 check_variant 对两个变量进行sanity check。下面看下这两个函数,都比较短。

52 # check to see if the supplied product is one we can build
  53 function check_product()                                                                                                                                                                                       
  54 {
  55     T=$(gettop)
  56     if [ ! "$T" ]; then
  57         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
  58         return
  59     fi
  60     CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
  61         TARGET_PRODUCT=$1 \
  62         TARGET_BUILD_VARIANT= \
  63         TARGET_BUILD_TYPE= \
  64         TARGET_BUILD_APPS= \
  65         get_build_var TARGET_DEVICE > /dev/null
  66     # hide successful answers, but allow the errors to show
  67 }

这个函数由调用了get_build_var,也很短:

 40 # Get the exact value of a build variable.                                                                                                                                                                     
  41 function get_build_var()
  42 {
  43     T=$(gettop)
  44     if [ ! "$T" ]; then
  45         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
  46         return
  47     fi
  48     CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
  49       make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-$1
  50 }

这里执行了一个make命令,命令执行的文件是 build/core/config.mk 目标为dumpvar-$1(dumpvar-TARGET_DEVICE).很显然,代码引导我们查看文件

build/core/config.mk 并且搜索目标dumpvar-TARGET_DEVICE.


通过查看build/core/config.mk 我们知道了,这个文件并没有dumpvar-TARGET_DEVICE.但是他包含了其他几个重要文件,这些文件里面有我们要找的目标。

buid/core/envsetup.mk BoardConfig.mk dumpvar.mk.包含关系相关的代码如下:

134 # ---------------------------------------------------------------
135 # Define most of the global variables.  These are the ones that  
136 # are specific to the user's build configuration.
137 include $(BUILD_SYSTEM)/envsetup.mk                                                                                                                                                                             
138 
139 # Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)     
140 # or under vendor/*/$(TARGET_DEVICE).  Search in both places, but                                    
141 # make sure only one exists.                                                                         
142 # Real boards should always be associated with an OEM vendor.                                        
143 board_config_mk := \                                                                                 
144     $(strip $(wildcard \                                                                             
145         $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
146         $(shell test -d device && find device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
147         $(shell test -d vendor && find vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
148     ))
149 ifeq ($(board_config_mk),)
150   $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))                                   
151 endif                                                                                                
152 ifneq ($(words $(board_config_mk)),1)
153   $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))        
154 endif                                                                                                
155 include $(board_config_mk)  


所以我们下面重点查看这三个文件,并搜索目标dumpva-TARGET_DEVICE.

第一个文件:build/core/envsetup.mk 的代码并不多,其中有这么一行:

115 include $(BUILD_SYSTEM)/product_config.mk

这个文件又包含了build/core/product_config.mk,查看这个文件,这个文件解密了TARGET_DEVICE这个变量

275 TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE) 

可以看出TARGET_DEVICE是根据PRODUCT来取得的,根据PRODUCT变量取得该目录下面的AndroidProduct.mk,进而取得 full_xx.mk这个是当前product的配置文件。

这里面有个变量叫做PRODUCT_DEVICE经过重命名之后得到的 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE) 。



第二个文件:BoardConfig.mk这个是在具体设备的目录下面的,内容不多,涉及到CPU的体系结构等。


第三个文件:dumpvar.mk 内容比较多。 但是这里面有我们要找的目标dumpvar-TARGET_DEVICE。

53 dumpvar_goals := \
 54     $(strip $(patsubst dumpvar-%,%,$(filter dumpvar-%,$(MAKECMDGOALS))))
 55 ifdef dumpvar_goals
 56 
 57   ifneq ($(words $(dumpvar_goals)),1)                                                                                                                                                                           
 58     $(error Only one "dumpvar-" goal allowed. Saw "$(MAKECMDGOALS)")
 59   endif
 60 
 61   # If the goal is of the form "dumpvar-abs-VARNAME", then
 62   # treat VARNAME as a path and return the absolute path to it.
 63   absolute_dumpvar := $(strip $(filter abs-%,$(dumpvar_goals)))
 64   ifdef absolute_dumpvar
 65     dumpvar_goals := $(patsubst abs-%,%,$(dumpvar_goals))
 66     ifneq ($(filter /%,$($(dumpvar_goals))),)
 67       DUMPVAR_VALUE := $($(dumpvar_goals))
 68     else
 69       DUMPVAR_VALUE := $(PWD)/$($(dumpvar_goals))
 70     endif
 71     dumpvar_target := dumpvar-abs-$(dumpvar_goals)
 72   else
 73     DUMPVAR_VALUE := $($(dumpvar_goals))
 74     dumpvar_target := dumpvar-$(dumpvar_goals)
 75   endif
 76 
 77 .PHONY: $(dumpvar_target)
 78 $(dumpvar_target):
 79     @echo $(DUMPVAR_VALUE)


可以看到这个目标,并没有干什么事,就是吧TARGET_DEVICE打印出来而已。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值