Android编译环境初始化浅析

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


参考博客:
http://blog.csdn.net/luoshengyang/article/details/18928789
http://www.360doc.com/content/13/0907/16/11813302_312848603.shtml



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值