Android编译环境初始化,核心文件层级关系,阅读时可以参考

├──build/envsetup.sh 

 │   ├── device/vendor-platform/my-product/vendorsetup.sh 

 │ 

 ├── build/core/config.mk 

 │   ├── build/core/envsetup.mk 

 │   │   ├── build/core/product_config.mk 

 │   │   │   ├── build/core/node_fns.mk 

 │   │   │   ├── build/core/product.mk 

 │   │   │   │   ├── device/vendor-platform/my-product/AndroidProducts.mk 

 │   │   │   │   │   ├── device/vendor-platform/my-product/my_product.mk 

 │   │   │   │ 

 │   │   │   ├── build/core/device.mk 

 │   │      

 │   ├── device/vendor-platform/my-product/BoardConfig.mk 

 │   └── build/core/dumpvar.mk 



 ------------------------------------------------------------------------------------------------ 

 $ source build/envsetup.sh 

 including device/moto/stingray/vendorsetup.sh 

 including device/samsung/maguro/vendorsetup.sh 

 including device/samsung/toro/vendorsetup.sh 

 including device/samsung/tuna/vendorsetup.sh 

 including device/vendor-platform/my-product/vendorsetup.sh 

 including device/vendor-platform/apollo-a70tb/vendorsetup.sh 

 including sdk/bash_completion/adb.bash 


 envsetup.sh有两个主要目的: 

 1.定义一些全局函数和一些命令 比如:add_lunch_combo、mm、jgrep等等 

 2.加载我们自己定义的产品 比如: my_product-eng 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/envsetup.sh -c $     友情提示: 编辑模式下“:$” 为跳到文件末尾 


 # Execute the contents of any vendorsetup.sh files we can find. 

 for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/*/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null` 

 do 

     echo "including $f" 

     . $f --> 执行 xxx/vendorsetup.sh 

 done 

 unset f 


 执行envsetup.sh第一步就是通过 for 去遍历 vendor、device下面的vendorsetup.sh 文件,目的是去加载我们自定义的产品 

 ------------------------------------------------------------------------------------------------ 

 vendorsetup.sh 我们自己产品,和相关模块加载都定义在这个文件里面 


 abner@THTFIT-Compiler:~/allwinner/a10/android$ vi device/vendor-platform/my-product/vendorsetup.sh 


 add_lunch_combo my_product-eng 


 ------------------------------------------------------------------------------------------------ 

 add_lunch_combo函数定义在 build/envsetup.sh 


 $ vi build/envsetup.sh -c /add_lunch_combo 


 # Clear this variable.  It will be built up again when the vendorsetup.sh 

 # files are included at the end of this file. 

 unset LUNCH_MENU_CHOICES 

 function add_lunch_combo() 

 { 

     local new_combo=$1 

     local c 

     for c in ${LUNCH_MENU_CHOICES[@]} ; do  --> "@" 表示数组所有元素 

         if [ "$new_combo" = "$c" ] ; then 

             return 

         fi    

     done 

     LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo) --> 等同于 “array = array + new” 模式 

 } 


 LUNCH_MENU_CHOICES : 这个里面保存的就是,在lunch时终端展示给我们的选单 

 所以到了这步我们就可以lunch了 


 ------------------------------------------------------------------------------------------------ 


 $ lunch 


 You're building on Linux 


 Lunch menu... pick a combo: 

      1. full-eng             --> 这个就是通过 add_lunch_combo 函数加载进来的 

      2. full_x86-eng 

      3. vbox_x86-eng 

      4. full_stingray-userdebug 

      5. full_wingray-userdebug 

      6. full_crespo4g-userdebug 

      7. full_crespo-userdebug 

      8. full_maguro-userdebug 

      9. full_toro-userdebug 

      10. full_tuna-userdebug 

      11. my_product-eng 


 Which would you like? [full-eng]11 

 ============================================ 

 PLATFORM_VERSION_CODENAME=REL 

 PLATFORM_VERSION=4.0.4 

 TARGET_PRODUCT=my_product 

 TARGET_BUILD_VARIANT=eng 

 TARGET_BUILD_TYPE=release 

 TARGET_BUILD_APPS= 

 TARGET_ARCH=arm 

 TARGET_ARCH_VARIANT=armv7-a-neon 

 HOST_ARCH=x86 

 HOST_OS=linux 

 HOST_BUILD_TYPE=release 

 BUILD_ID=IMM76D 

 ============================================ 


 ------------------------------------------------------------------------------------------------ 

 接下来分析lunch 

 $ vi build/envsetup.sh -c /lunch\(\) 

 function lunch() 

 { 

     local answer 


     if [ "$1" ] ; then 

         answer=$1 

     else 

         print_lunch_menu  --> 如果lunch没有参数,则打印列表 

         echo -n "Which would you like? [full-eng] " 

         read answer --> 等待用户输入 

     fi 


     local selection= 


     if [ -z "$answer" ] 

     then 

         selection=full-eng 

     elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$") --> 匹配0-9数值,-q 为静默模式,不向标准输出,输出信息 

     then 

         if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] --> #LUNCH_MENU_CHOICES[@] 求整个数组长度 

         then 

             selection=${LUNCH_MENU_CHOICES[$(($answer-1))]} 

         fi 

     elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$") --> 匹配类似abc-efg,字符串部分不能有“-”的字符串 

     then 

         selection=$answer --> 获得要选择的产品,我们选择11,对应 “my_product-eng” 

     fi 


     if [ -z "$selection" ] 

     then 

         echo 

         echo "Invalid lunch combo: $answer" 

         return 1 

     fi 


     export TARGET_BUILD_APPS= 


     local product=$(echo -n $selection | sed -e "s/-.*$//") --> 意思是用空“”去替换“-”开始后面的串,就得到product 

                                                                 对应例子: my_product 

     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 


     local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//") --> 同理替换前面字符串,对应: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 


     export TARGET_PRODUCT=$product 

     export TARGET_BUILD_VARIANT=$variant 

     export TARGET_BUILD_TYPE=release 

     echo 


     set_stuff_for_environment 

     printconfig 


     if [ "$NEED_TOUCH_SWITCH_PRODUCT_FILE" = "1" ]; then #added by lxj 2013-12-09 

         touch_switch_product_file 

         NEED_TOUCH_SWITCH_PRODUCT_FILE="0" 

     fi 

 } 


 ------------------------------------------------------------------------------------------------ 

 lunch打印函数 

 $ vi build/envsetup.sh -c /print_lunch_menu\(\) 

 function print_lunch_menu() 

 { 

     local uname=$(uname)  --> 执行uname命令获得编译平台 等同: “local uname=`uname`” 

     echo 

     echo "You're building on" $uname 

     echo 

     echo "Lunch menu... pick a combo:" 


     local i=1 

     local choice 

     for choice in ${LUNCH_MENU_CHOICES[@]} 

     do 

         echo "     $i. $choice" --> 打印选单 

         i=$(($i+1)) 

     done 


     echo 

 } 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/envsetup.sh -c /check_product\(\) 

 # check to see if the supplied product is one we can build 

 function check_product() 

 { 

     T=$(gettop) 

     if [ ! "$T" ]; then 

         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2 

         return 

     fi    

     CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ 

         TARGET_PRODUCT=$1 \       --> TARGET_PRODUCT = my_product 

         TARGET_BUILD_VARIANT= \ 

         TARGET_BUILD_TYPE= \ 

         TARGET_BUILD_APPS= \ 

         get_build_var TARGET_DEVICE > /dev/null  --> 调用函数  get_build_var TARGET_DEVICE 

     # hide successful answers, but allow the errors to show 

 } 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/envsetup.sh -c /get_build_var\(\) 

 # Get the exact value of a build variable. 

 function get_build_var() 

 { 

     T=$(gettop) 

     if [ ! "$T" ]; then 

         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2 

         return 

     fi 

     CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ 

       make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-$1 


     --> 相当于 make -f build/core/config.mk dumpvar-TARGET_DEVICE 

 } 


 ------------------------------------------------------------------------------------------------ 


 下一步我们要分析 

 vi build/core/config.mk 


 # Define most of the global variables.  These are the ones that 

 # are specific to the user's build configuration. 

 include $(BUILD_SYSTEM)/envsetup.mk  --> BUILD_SYSTEM在envsetup.sh定义,相当于build/core/envsetup.mk 

                                          定义了各种目标文件的目录,还用来确定“TARGET_DEVICE” 


 # Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE) 

 # or under vendor/*/$(TARGET_DEVICE).  Search in both places, but 

 # make sure only one exists. 

 # Real boards should always be associated with an OEM vendor. 

 board_config_mk := \   --> 遍历build/target、device、vendor这几个目录的BoardConfig.mk文件,主要是板的配置信息 

                这里比较核心的问题就是如何确定“TARGET_DEVICE” 

     $(strip $(wildcard \ 

         $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \ 

         device/*/$(TARGET_DEVICE)/BoardConfig.mk \ 

         vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \ 

     )) 

 ifeq ($(board_config_mk),) 

   $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE)) 

 endif 

 ifneq ($(words $(board_config_mk)),1) 

   $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk)) 

 endif 

 include $(board_config_mk) 


 ... 

 include $(BUILD_SYSTEM)/dumpvar.mk 


 config.mk主要引入这几个文件envsetup.mk、BoardConfig.mk、dumpvar.mk 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/core/envsetup.mk 


 分析和“TARGET_DEVICE”相关代码 

 # Read the product specs so we an get TARGET_DEVICE and other 

 # variables that we need in order to locate the output files. 

 include $(BUILD_SYSTEM)/product_config.mk 


 这是目标产品输出目录 

 ifneq ($(TARGET_BUILD_TYPE),debug) 

 TARGET_BUILD_TYPE := release 

 endif 


 TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE)) 

 TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product 

 PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE) 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/core/product_config.mk 


 # Include the product definitions. 

 # We need to do this to translate TARGET_PRODUCT into its 

 # underlying TARGET_DEVICE before we start defining any rules. 

 # 

 include $(BUILD_SYSTEM)/node_fns.mk --> 定义函数 import-nodes 

 include $(BUILD_SYSTEM)/product.mk --> 定义函数 import-products、resolve-short-product-name、 

                                                 get-all-product-makefiles、get-product-makefiles 

 include $(BUILD_SYSTEM)/device.mk 


 ifneq ($(strip $(TARGET_BUILD_APPS)),) 

   # An unbundled app build needs only the core product makefiles. 

   $(call import-products,$(call get-product-makefiles,\ 

       $(SRC_TARGET_DIR)/product/AndroidProducts.mk))  --> build/target/product/AndroidProducts.mk 

                                                           里面定义了一下些核心产品的makefile文件,比如core.mk 

                                                           一并添加到“PRODUCT_MAKEFILES” 

 else 

   # Read in all of the product definitions specified by the AndroidProducts.mk 

   # files in the tree. 

   # 

   #TODO: when we start allowing direct pointers to product files, 

   #    guarantee that they're in this list. 

   $(call import-products, $(get-all-product-makefiles)) --> 遍历所有AndroidProducts.mk,比如我们自己定义的产品 

                                                             vi device/vendor-platform/my-product/AndroidProducts.mk 

                                                             PRODUCT_MAKEFILES := $(LOCAL_DIR)/my_product.mk 

 endif # TARGET_BUILD_APPS 

 $(check-all-products) 


 ifneq ($(filter dump-products, $(MAKECMDGOALS)),) 

 $(dump-products) 

 $(error done) 

 endif 


 # Convert a short name like "sooner" into the path to the product 

 # file defining that product. 

 # 

 INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT)) 

 --> $(TARGET_PRODUCT)为my_product,resolve-short-product-name 函数通过产品名字获取makefile文件 

 --> 根据如下分析可以得出 “INTERNAL_PRODUCT” 为 device/vendor-platform/my-product/my_product.mk 


 #$(error TARGET_PRODUCT $(TARGET_PRODUCT) --> $(INTERNAL_PRODUCT)) 


 # Find the device that this product maps to. 

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

 --> 等同于: 

 --> TARGET_DEVICE := $(PRODUCTS.device/vendor-platform/my-product/my_product.mk.PRODUCT_DEVICE) 

 --> "PRODUCTS.device/vendor-platform/my-product/my_product.mk.PRODUCT_DEVICE" 在 node_fns.mk分析给出,见如下分析 

 --> 最终得出: TARGET_DEVICE := my_product 


 ------------------------------------------------------------------------------------------------ 


 build/core/product.mk 

 # 

 # Returns the list of all AndroidProducts.mk files. 

 # $(call ) isn't necessary. 

 # 

 define _find-android-products-files --> 查找device、vendor、build/target/product 目录下说所有的AndroidProducts.mk 

 $(shell test -d device && find device -maxdepth 6 -name AndroidProducts.mk) \ 

   $(shell test -d vendor && find vendor -maxdepth 6 -name AndroidProducts.mk) \ 

   $(SRC_TARGET_DIR)/product/AndroidProducts.mk 

 endef 


 # 

 # Returns the sorted concatenation of PRODUCT_MAKEFILES 

 # variables set in the given AndroidProducts.mk files. 

 # $(1): the list of AndroidProducts.mk files. 

 # 

 define get-product-makefiles 

 $(sort \ 

   $(foreach f,$(1), \ 

     $(eval PRODUCT_MAKEFILES :=) \ 

     $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \ 

     $(eval include $(f)) \  --> 包含 device/xxx/AndroidProducts.mk 

     $(PRODUCT_MAKEFILES) \  --> 具体产品的makefile文件,返回给调用者,比如:device/xxx/my_product.mk 

    ) \ 

   $(eval PRODUCT_MAKEFILES :=) \ 

   $(eval LOCAL_DIR :=) \ 

  ) 

 endef 


 # 

 # Returns the sorted concatenation of all PRODUCT_MAKEFILES 

 # variables set in all AndroidProducts.mk files. 

 # $(call ) isn't necessary. 

 # 

 define get-all-product-makefiles 

 $(call get-product-makefiles,$(_find-android-products-files)) 

 endef 


 _product_var_list := \ --> 具体每个产品属性定义在“PRODUCT_MAKEFILES” 

                            如: device/vendor-platform/my-product/my_product.mk 

     PRODUCT_NAME \ 

     PRODUCT_MODEL \ 

     PRODUCT_LOCALES \ 

     PRODUCT_AAPT_CONFIG \ 

     PRODUCT_AAPT_PREF_CONFIG \ 

     PRODUCT_PACKAGES \ 

     PRODUCT_DEVICE \ 

     PRODUCT_MANUFACTURER \ 

     PRODUCT_BRAND \ 

     PRODUCT_PROPERTY_OVERRIDES \ 

     PRODUCT_DEFAULT_PROPERTY_OVERRIDES \ 

     PRODUCT_CHARACTERISTICS \ 

     PRODUCT_COPY_FILES \ 

     PRODUCT_OTA_PUBLIC_KEYS \ 

     PRODUCT_EXTRA_RECOVERY_KEYS \ 

     PRODUCT_PACKAGE_OVERLAYS \ 

     DEVICE_PACKAGE_OVERLAYS \ 

     PRODUCT_TAGS \ 

     PRODUCT_SDK_ADDON_NAME \ 

     PRODUCT_SDK_ADDON_COPY_FILES \ 

     PRODUCT_SDK_ADDON_COPY_MODULES \ 

     PRODUCT_SDK_ADDON_DOC_MODULES \ 

     PRODUCT_DEFAULT_WIFI_CHANNELS \ 

     PRODUCT_DEFAULT_DEV_CERTIFICATE \ 


 # 

 # $(1): product makefile list 

 # 

 #TODO: check to make sure that products have all the necessary vars defined 

 define import-products 

 $(call import-nodes,PRODUCTS,$(1),$(_product_var_list))   --> PRODUCTS 为返回的产品信息 

 endef 


 # 

 # Returns the product makefile path for the product with the provided name 

 # 

 # $(1): short product name like "generic" 

 # 

 define _resolve-short-product-name  --> 根据product名字获得产品的makefile文件路径 

   $(eval pn := $(strip $(1))) 

   $(eval p := \ 

       $(foreach p,$(PRODUCTS), \ 

           $(if $(filter $(pn),$(PRODUCTS.$(p).PRODUCT_NAME)), \ --> 这个就是my_product.mk定义的产品名字 

             $(p) \ 

        )) \ 

    ) 

   $(eval p := $(sort $(p))) 

   $(if $(filter 1,$(words $(p))), \ 

     $(p), \ 

     $(if $(filter 0,$(words $(p))), \ 

       $(error No matches for product "$(pn)"), \ 

       $(error Product "$(pn)" ambiguous: matches $(p)) \ 

     ) \ 

   ) 

 endef 

 define resolve-short-product-name 

 $(strip $(call _resolve-short-product-name,$(1))) 

 endef 


 ------------------------------------------------------------------------------------------------ 

 $ vi device/vendor-platform/my-product/my_product.mk 

 # Overrides 

 PRODUCT_BRAND  := abner 

 PRODUCT_NAME   := my_product 

 PRODUCT_DEVICE := my-product 

 PRODUCT_MODEL  := love-1026 


 ------------------------------------------------------------------------------------------------ 

 $ find . -name "AndroidProducts.mk" 

 ./device/vendor-platform/my-product/AndroidProducts.mk 

 ./device/samsung/crespo/AndroidProducts.mk 

 ./device/samsung/tuna/AndroidProducts.mk 

 ./build/target/product/AndroidProducts.mk 


 $ vi device/vendor-platform/my-product/AndroidProducts.mk 

 PRODUCT_MAKEFILES := \ 

     $(LOCAL_DIR)/my_product.mk \ 

     $(LOCAL_DIR)/my_product_tw.mk 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/core/node_fns.mk 


 # $(1): output list variable name, like "PRODUCTS" or "DEVICES" 

 # $(2): list of makefiles representing nodes to import 

 # $(3): list of node variable names 

 # 

 define import-nodes 

 $(if \ 

   $(foreach _in,$(2), \ 

     $(eval _node_import_context := _nic.$(1).[[$(_in)]]) \ 

     $(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \ 

                 should be empty here: $(_include_stack))),) \ 

     $(eval _include_stack := ) \ 

     $(call _import-nodes-inner,$(_node_import_context),$(_in),$(3)) \ 

     $(call move-var-list,$(_node_import_context).$(_in),$(1).$(_in),$(3)) \ --> 分析见下 

     $(eval _node_import_context :=) \ 

     $(eval $(1) := $($(1)) $(_in)) \  --> 返回的“PRODUCTS”,就是$(2)里面的值累加 

     $(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \ 

                 should be empty here: $(_include_stack))),) \ 

    ) \ 

 ,) 

 endef 


 # 

 # $(1): context prefix 

 # $(2): makefile representing this node 

 # $(3): list of node variable names 

 # 

 # _include_stack contains the list of included files, with the most recent files first. 

 define _import-node 

   $(eval _include_stack := $(2) $$(_include_stack)) 

   $(call clear-var-list, $(3)) 

   $(eval LOCAL_PATH := $(patsubst %/,%,$(dir $(2)))) 

   $(eval MAKEFILE_LIST :=) 

   $(eval include $(2)) 

   $(eval _included := $(filter-out $(2),$(MAKEFILE_LIST))) 

   $(eval MAKEFILE_LIST :=) 

   $(eval LOCAL_PATH :=) 

   $(call copy-var-list, $(1).$(2), $(3)) --> 分析见下 

   $(call clear-var-list, $(3)) 


   $(eval $(1).$(2).inherited := \ 

       $(call get-inherited-nodes,$(1).$(2),$(3))) 

   $(call _import-nodes-inner,$(1),$($(1).$(2).inherited),$(3)) 


   $(call _expand-inherited-values,$(1),$(2),$(3)) 


   $(eval $(1).$(2).inherited :=) 

   $(eval _include_stack := $(wordlist 2,9999,$$(_include_stack))) 

 endef 


 # $(1): destination prefix 

 # $(2): list of variable names to copy 

 define copy-var-list 

 $(foreach v,$(2),$(eval $(strip $(1)).$(v):=$($(v)))) 

 endef 


 # $(1): source prefix 

 # $(2): destination prefix 

 # $(3): list of variable names to move 

 define move-var-list 

 $(foreach v,$(3), \ 

   $(eval $(2).$(v) := $($(1).$(v))) \ 

   $(eval $(1).$(v) :=) \ 

  ) 

 endef 


 调试分析:$(info print info : $(xo)) 

 $(call copy-var-list, $(1).$(2), $(3)) 

 $(1).$(2) --> _nic.PRODUCTS.[[device/vendor-platform/my-product/my_product.mk]].device/vendor-platform/my-product/my_product.mk 

 $(3) --> PRODUCT_NAME PRODUCT_MODEL PRODUCT_LOCALES 


 根据 copy-var-list定义 

 $(foreach v,$(2),$(eval $(strip $(1)).$(v):=$($(v)))) 

 _nic.PRODUCTS.[[device/vendor-platform/my-product/my_product.mk]].device/vendor-platform/my-product/my_product.mk.PRODUCT_NAME := $(PRODUCT_NAME) 


 move-var-list 

 $(2).$(v) := $($(1).$(v) 

 PRODUCTS.device/vendor-platform/my-product/my_product.mk.PRODUCT_NAME := $(_nic.PRODUCTS.[[device/vendor-platform/my-product/my_product.mk]].device/vendor-platform/my-product/my_product.mk.PRODUCT_NAME) 

 --> PRODUCTS.device/vendor-platform/my-product/my_product.mk.PRODUCT_NAME =: $(PRODUCT_NAME)  //my_product 


 --> PRODUCTS.device/vendor-platform/my-product/my_product.mk.PRODUCT_NAME =: my_product 

 --> PRODUCTS.device/vendor-platform/my-product/my_product.mk.PRODUCT_DEVICE =: my_product 

 --> PRODUCTS.device/vendor-platform/my-product/my_product.mk.PRODUCT_MODEL =: A15S2 


 ------------------------------------------------------------------------------------------------ 

 再次回到build/core/config.mk 


 include $(board_config_mk) 

 此时是包含 BoardConfig.mk,同样是在 build/target、device、vendor这几个目录寻找 

 例如: 

 $ vi device/vendor-platform/my-product/BoardConfig.mk 


 TARGET_NO_BOOTLOADER := true 

 TARGET_NO_RECOVERY := false 

 TARGET_NO_KERNEL := false 


 INSTALLED_KERNEL_TARGET := kernel 

 BOARD_KERNEL_BASE := 0x40000000 

 #BOARD_KERNEL_CMDLINE := console=ttyS0,115200 rw init=/init loglevel=8 

 TARGET_USERIMAGES_USE_EXT4 := true 

 BOARD_FLASH_BLOCK_SIZE := 4096 

 BOARD_SYSTEMIMAGE_PARTITION_SIZE := 335544320 

 #BOARD_USERDATAIMAGE_PARTITION_SIZE := 1073741824 

 BOARD_USES_GSENSOR_TYPE := bma250 

 BOARD_GSENSOR_DIRECT_X := true 

 BOARD_GSENSOR_DIRECT_Y := true 

 BOARD_GSENSOR_DIRECT_Z := true 

 BOARD_GSENSOR_XY_REVERT := false 


 BOARD_HAVE_BLUETOOTH := true 


 TARGET_HARDWARE_NAME := a15s2 



 主要定义了一些板载模块的相关配置信息 


 ------------------------------------------------------------------------------------------------ 

 再一次回到build/core/config.mk 


 include $(BUILD_SYSTEM)/dumpvar.mk 


 $ vi build/core/dumpvar.mk 


 # the setpath shell function in envsetup.sh uses this to figure out 

 # what to add to the path given the config we have chosen. 

 ifeq ($(CALLED_FROM_SETUP),true) 


 ABP:=$(PWD)/$(HOST_OUT_EXECUTABLES) 


 # Add the toolchain bin dir if it actually exists 

 ifneq ($(wildcard $(PWD)/prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-linux-androideabi-4.4.x/bin),) 

     # this should be copied to HOST_OUT_EXECUTABLES instead 

     ABP:=$(ABP):$(PWD)/prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-linux-androideabi-4.4.x/bin 

 endif 

 ANDROID_BUILD_PATHS := $(ABP) 

 ANDROID_PREBUILTS := prebuilt/$(HOST_PREBUILT_TAG) 


 # 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)))) --> dumpvar_goals的值为 “TARGET_DEVICE” 

 ifdef dumpvar_goals 


   ifneq ($(words $(dumpvar_goals)),1) --> 只能有一个 dumpvar-TARGET_DEVICE 目标 

     $(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)) 

     DUMPVAR_VALUE := $(PWD)/$($(dumpvar_goals)) 

     dumpvar_target := dumpvar-abs-$(dumpvar_goals) 

   else 

     DUMPVAR_VALUE := $($(dumpvar_goals)) --> $(TARGET_DEVICE) 的值为 my_product 

     dumpvar_target := dumpvar-$(dumpvar_goals) --> dumpvar-TARGET_DEVICE 

   endif 


 .PHONY: $(dumpvar_target) 

 $(dumpvar_target): --> dumpvar-TARGET_DEVICE: 

     @echo $(DUMPVAR_VALUE) --> echo my_product 


 endif # dumpvar_goals 


 ifneq ($(dumpvar_goals),report_config) -->用来打印配置消息,如果目标是report_config才打印 

 PRINT_BUILD_CONFIG:= 

 endif 


 endif # CALLED_FROM_SETUP 



 ifneq ($(PRINT_BUILD_CONFIG),) --> 检查“PRINT_BUILD_CONFIG” 不为空才会打印 

 $(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_BUILD_TYPE=$(HOST_BUILD_TYPE)) 

 $(info   BUILD_ID=$(BUILD_ID)) 

 $(info ============================================) 

 endif 


 最最终打印 --> 


 =========================================== 

 PLATFORM_VERSION_CODENAME=REL 

 PLATFORM_VERSION=4.0.4 

 TARGET_PRODUCT=my_product 

 TARGET_BUILD_VARIANT=eng 

 TARGET_BUILD_TYPE=release 

 TARGET_BUILD_APPS= 

 TARGET_ARCH=arm 

 TARGET_ARCH_VARIANT=armv7-a-neon 

 HOST_ARCH=x86 

 HOST_OS=linux 

 HOST_BUILD_TYPE=release 

 BUILD_ID=IMM76D 

 ============================================ 


 ------------------------------------------------------------------------------------------------ 

 以上是chek_product 的过程分析,基本完毕 

 接下来就是 chek_variant的过程分析就很简单了 


 export TARGET_BUILD_APPS= 


 local product=$(echo -n $selection | sed -e "s/-.*$//") 

 echo "check product : $product" 

 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 


 local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//") 

 check_variant $variant --> 检测变量是否为user、userdebug、eng其中一个 

 if [ $? -ne 0 ] 

 then 

   echo 

   echo "** Invalid variant: '$variant'" 

   echo "** Must be one of ${VARIANT_CHOICES[@]}" 

   variant= 

 fi   



 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 

 } 


 --> user表示发布版本 

 --> userdebug表示带调试信息的发布版本 

 --> eng表标工程机版本 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/envsetup.sh 


 打印配置信息函数 

 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  --> 相当于 make -f build/core/config.mk dumpvar-report_config 

 } 


 check 完 product和variant 后再到 build/core/dumpvar.mk 


 dumpvar_goals := \  --> 此时“dumpvar_goals” 为 report_config 

     $(strip $(patsubst dumpvar-%,%,$(filter dumpvar-%,$(MAKECMDGOALS)))) 


 ............. 


 ifneq ($(dumpvar_goals),report_config) --> 如果是目标report_config,则不会设置“PRINT_BUILD_CONFIG” 

 PRINT_BUILD_CONFIG:= 

 endif 


 ............. 


 ifneq ($(PRINT_BUILD_CONFIG),) "PRINT_BUILD_CONFIG" 定义在 build/core/envsetup.mk 默认设置为true 

 $(info ============================================) 

 $(info   PLATFORM_VERSION_CODENAME=$(PLATFORM_VERSION_CODENAME)) 

 $(info   PLATFORM_VERSION=$(PLATFORM_VERSION)) 

 ........ 

 $(info ============================================) 

 endif 


 ------------------------------------------------------------------------------------------------ 

 $ vi build/core/envsetup.mk 


 ifeq ($(PRINT_BUILD_CONFIG),) 

 PRINT_BUILD_CONFIG := true 

 endif


------------------------------------------------------------------------------------------------

至此,Android编译环境初始化过程基本分析完毕,但还有很多细节需要进一步完善
提示:在阅读时参照层级关系树,最好对着源码工程分析,逻辑就会很清晰明白了