在Android4.2的源码Build/prduct_config.mk里面遇到几个疑惑:

# 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))
ifneq ($(current_product_makefile),$(INTERNAL_PRODUCT))
$(error PRODUCT_NAME inconsistent in $(current_product_makefile) and $(INTERNAL_PRODUCT))
endif
current_product_makefile :=
all_product_makefiles :=
all_product_configs :=

# Find the device that this product maps to.
TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)

按道理Makefile在读取product_config.mk文件时,TARGET_DEVICE第一感觉就该被理解我一个合成的变量,当然这是Makefile的原理。但是这里发现却不是,为什么?因为引入了一个node_fns.mk文件。该文件的作用类似规定下完开始的content应该按照它的逻辑来处理,就好像比如定义了一种宏形式,那么接着的变量处理实际会变为另一中处理方式:

比如这里实际:

INTERNAL_PRODUCT = device/softwinner/fiber-3g/fiber_3g.mk

TARGET_DEVICE = fiber-3g

说实话自己也不是很理解node_fns.mk的作用,就把他理解为一个定义了好多宏的头文件吧。

看了下老罗的Android之旅,收获了很对。上述的内容实质就是$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)是一个全新的变量。通过对AndroidProducts.mk的内容进行分析,然后加上不同的_product_var_list ,这样就可以生成全新的变量,都是根据不同的自己定制的产品来生成的。如下的变量就变成了上面提到的TARGET_DEVICE,其实质是在AndroidProducts.mk里面进行了定义而已:

# Overrides
PRODUCT_BRAND  := Softwinner
PRODUCT_NAME   := fiber_3g
PRODUCT_DEVICE := fiber-3g
PRODUCT_MODEL  := Softwinn
PRODUCTS.build/target/product/full.mk.PRODUCT_NAME := fiber_3g  
PRODUCTS.build/target/product/full.mk.PRODUCT_DEVICE := fiber-3g
_product_var_list := \
    PRODUCT_NAME \
    PRODUCT_MODEL \
    PRODUCT_LOCALES \
    PRODUCT_AAPT_CONFIG \
    PRODUCT_AAPT_PREF_CONFIG \
    PRODUCT_PACKAGES \
    PRODUCT_PACKAGES_DEBUG \
    PRODUCT_PACKAGES_ENG \
    PRODUCT_PACKAGES_TESTS \
    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 \
    PRODUCT_RESTRICT_VENDOR_FILES \
    PRODUCT_VENDOR_KERNEL_HEADERS \
    PRODUCT_FACTORY_RAMDISK_MODULES \
    PRODUCT_FACTORY_BUNDLE_MODULES

 

对于Android系统中的.mk文件可以在source /build/envsetup.sh后进行调用。比如:

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
}

该脚本函数就会被在lunch 选择时,进行chenk products的操作,进一步执行get_build_var TARGET_DEVICE的函数处理。其实质是执行了一次Make的操作。看上去和系统编译的Make -j8等完全类似。只是他执行了的只有config.mk配置相关的内容而已。进一步依次执行envsetup.mk,到product_config.mk,最终获得TARGET_DEVICE变量的内容。

 


6.$DEVICE变量的生成过程,其实就是文件fiber-3g所在的路径:



首先通过source envsetup.sh将所有的device和vendor下的vendorsetup.sh加进来,并完成combo的整合。



lunch函数选择对应的平台后,并会设置好所有编译所需的环境变量使用下面函数来完成:



   #设置环境变量
    set_stuff_for_environment
   #打印最终的配置信息
    printconfig



set_stuff_for_environment的setpath函数中,该函数会export很多的环境路径,供后续脚本函数执行调用



有包括export DEVICE的导入:


     tdevice=$(get_build_var TARGET_DEVICE)

     export DEVICE=$T/device/*/$tdevice



 



如下自定义Android编译项和创建Product产品配置文件,Board板级配置文件:



7 lunch过程确定了TARGET_PRODUCT = fiber_3g的内容;





8  TARGET_DEVICE=fiber-3g,在 build/core/product_config.mk 中根据 PRODUCT_DEVICE来确定 。



通过遍历所有device目录下的AndroidProducts.mk中的引入的.mk文件,比如这里指fiber_3g.mk。通过TARGET_PRODUCT 来匹配查找到对应的AndroidProducts.mk。而PRODUCT_DEVICE在fiber_3g.mk中被确定为fiber-3g。通过node_fns.mk的宏作用,进而确定 TARGET_DEVICE的内容为fiber-3g。





9.Boardconfig.mk的作用。build/core/config.mk来决定。通过遍历device/*/$(TARGET_DEVICE)/boardconfig.mk来完成