搜索
 找回密码
 立即注册

简单一步 , 微信登陆

Android编译系统环境初始化过程分析(3)

作者:liuwei | 时间:2016-9-28 14:07:09 | 阅读:4336| 只看该作者

再回到build/core/config.mk文件中,它最后加载build/core/dumpvar.mk文件。加载build/core/dumpvar.mk文件是为了生成make目标,以便可以对这些目标进行操作。例如,在我们这个情景中,我们要执行的make目标是dumpvar-TARGET_DEVICE,因此在加载build/core/dumpvar.mk文件的过程中,就会生成dumpvar-TARGET_DEVICE目标。

       文件build/core/dumpvar.mk的内容也比较多,这里我们只关注生成make目标相关的逻辑:


[plain] view plain copy


  • ......  
  •   
  • # The "dumpvar" stuff lets you say something like  
  • #  
  • #     CALLED_FROM_SETUP=true \  
  • #       make -f config/envsetup.make dumpvar-TARGET_OUT  
  • # or  
  • #     CALLED_FROM_SETUP=true \  
  • #       make -f config/envsetup.make dumpvar-abs-HOST_OUT_EXECUTABLES  
  • #  
  • # The plain (non-abs) version just dumps the value of the named variable.  
  • # The "abs" version will treat the variable as a path, and dumps an  
  • # absolute path to it.  
  • #  
  • dumpvar_goals := \  
  •     $(strip $(patsubst dumpvar-%,%,$(filter dumpvar-%,$(MAKECMDGOALS))))  
  • ifdef dumpvar_goals  
  •   
  •   ifneq ($(words $(dumpvar_goals)),1)  
  •     $(error Only one "dumpvar-" goal allowed. Saw "$(MAKECMDGOALS)")  
  •   endif  
  •   
  •   # If the goal is of the form "dumpvar-abs-VARNAME", then  
  •   # treat VARNAME as a path and return the absolute path to it.  
  •   absolute_dumpvar := $(strip $(filter abs-%,$(dumpvar_goals)))  
  •   ifdef absolute_dumpvar  
  •     dumpvar_goals := $(patsubst abs-%,%,$(dumpvar_goals))  
  •     ifneq ($(filter /%,$($(dumpvar_goals))),)  
  •       DUMPVAR_VALUE := $($(dumpvar_goals))  
  •     else  
  •       DUMPVAR_VALUE := $(PWD)/$($(dumpvar_goals))  
  •     endif  
  •     dumpvar_target := dumpvar-abs-$(dumpvar_goals)  
  •   else  
  •     DUMPVAR_VALUE := $($(dumpvar_goals))  
  •     dumpvar_target := dumpvar-$(dumpvar_goals)  
  •   endif  
  •   
  • .PHONY: $(dumpvar_target)  
  • $(dumpvar_target):  
  •     @echo $(DUMPVAR_VALUE)  
  •   
  • endif # dumpvar_goals  
  •   
  • ......  

      我们在执行make命令时,指定的目示会经由MAKECMDGOALS变量传递到Makefile中,因此通过变量MAKECMDGOALS可以获得make目标。

      上述代码的逻辑很简单,例如,在我们这个情景中,指定的make目标为dumpvar-TARGET_DEVICE,那么就会得到变量DUMPVAR_VALUE的值为$(TARGET_DEVICE)。TARGET_DEVICE的值在前面已经被设置为“generic”,因此变量DUMPVAR_VALUE的值就等于“generic”。此外,变量dumpvar_target的被设置为“dumpvar-TARGET_DEVICE”。最后我们就可以得到以下的make规则:

[plain] view plain copy


  • .PHONY dumpvar-TARGET_DEVICE  
  • dumpvar-TARGET_DEVICE:  
  •     @echo generic  

       至此,在build/envsetup.sh文件中定义的函数check_product就分析完成了。看完了之后,小伙伴们可能会问,前面不是说这个函数是用来检查用户输入的产品名称是否合法的吗?但是这里没看出哪一段代码给出了true或者false的答案啊。实际上,在前面分析的build/core/config.mk和build/core/product_config.mk等文件的加载过程中,如果发现输入的产品名称是非法的,也就是找不到相应的产品Makefile文件,那么就会通过调用error函数来产生一个错误,这时候函数check_product的返回值$?就会等于非0值。

       接下来我们还要继续分析在build/envsetup.sh文件中定义的函数check_variant的实现,如下所示:


[plain] view plain copy


  • VARIANT_CHOICES=(user userdebug eng)  
  •   
  • # check to see if the supplied variant is valid  
  • function check_variant()  
  • {  
  •     for v in ${VARIANT_CHOICES[@]}  
  •     do  
  •         if [ "$v" = "$1" ]  
  •         then  
  •             return 0  
  •         fi  
  •     done  
  •     return 1  
  • }  

       这个函数的实现就简单多了。合法的编译类型定义在数组VARIANT_CHOICES中,并且它只有三个值user、userdebug和eng。其中,user表示发布版本,userdebug表示带调试信息的发布版本,而eng表标工程机版本。

       最后,我们再来分析在build/envsetup.sh文件中定义的函数printconfig的实现,如下所示:


[plain] view plain copy


  • function printconfig()  
  • {  
  •     T=$(gettop)  
  •     if [ ! "$T" ]; then  
  •         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2  
  •         return  
  •     fi  
  •     get_build_var report_config  
  • }  

       对比我们前面对函数check_product的分析,就会发现函数printconfig的实现与这很相似,都是通过调用get_build_var来获得相关的信息,但是这里传递给函数get_build_var的参数为report_config。

       我们跳过前面build/core/config.mk和build/core/envsetup.mk等文件对目标产品Makefile文件的加载,直接跳到build/core/dumpvar.mk文件来查看与report_config这个make目标相关的逻辑:


[plain] view plain copy


  • ......  
  •   
  • dumpvar_goals := \  
  •     $(strip $(patsubst dumpvar-%,%,$(filter dumpvar-%,$(MAKECMDGOALS))))  
  • .....  
  •   
  • ifneq ($(dumpvar_goals),report_config)  
  • PRINT_BUILD_CONFIG:=  
  • endif  
  •   
  • ......  
  •   
  • ifneq ($(PRINT_BUILD_CONFIG),)  
  • HOST_OS_EXTRA:=$(shell python -c "import platform; print(platform.platform())")  
  • $(info ============================================)  
  • $(info   PLATFORM_VERSION_CODENAME=$(PLATFORM_VERSION_CODENAME))  
  • $(info   PLATFORM_VERSION=$(PLATFORM_VERSION))  
  • $(info   TARGET_PRODUCT=$(TARGET_PRODUCT))  
  • $(info   TARGET_BUILD_VARIANT=$(TARGET_BUILD_VARIANT))  
  • $(info   TARGET_BUILD_TYPE=$(TARGET_BUILD_TYPE))  
  • $(info   TARGET_BUILD_APPS=$(TARGET_BUILD_APPS))  
  • $(info   TARGET_ARCH=$(TARGET_ARCH))  
  • $(info   TARGET_ARCH_VARIANT=$(TARGET_ARCH_VARIANT))  
  • $(info   HOST_ARCH=$(HOST_ARCH))  
  • $(info   HOST_OS=$(HOST_OS))  
  • $(info   HOST_OS_EXTRA=$(HOST_OS_EXTRA))  
  • $(info   HOST_BUILD_TYPE=$(HOST_BUILD_TYPE))  
  • $(info   BUILD_ID=$(BUILD_ID))  
  • $(info   OUT_DIR=$(OUT_DIR))  
  • $(info ============================================)  
  • endif  

       变量PRINT_BUILD_CONFIG定义在文件build/core/envsetup.mk中,默认值设置为true。当make目标为report-config的时候,变量PRINT_BUILD_CONFIG的值就会被设置为空。因此,接下来就会打印一系列用来描述编译环境配置的变量的值,也就是我们执行lunch命令后看到的输出。注意,这些环境配置相关的变量量都是在加载build/core/config.mk和build/core/envsetup.mk文件的过程中设置的,就类似于前面我们分析的TARGET_DEVICE变量的值的设置过程。

       至此,我们就分析完成Android编译系统环境的初始化过程了。从分析的过程可以知道,Android编译系统环境是由build/core/config.mk、build/core/envsetup.mk、build/core/product_config.mk、AndroidProducts.mk和BoardConfig.mk等文件来完成的。这些mk文件涉及到非常多的细节,而我们这里只提供了一个大体的骨架和脉络,希望能够起到抛砖引玉的作用。


收藏
收藏0
分享
分享
点赞
点赞0
反对
反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
手机版