当前位置: 代码迷 >> Android >> Android 4.03 编译系统-lunch
  详细解决方案

Android 4.03 编译系统-lunch

热度:7   发布时间:2016-05-01 14:59:36.0
Android 4.03 编译系统------lunch

        前面分析了Android 4.03编译系统-------envsetup.sh,今天来说lunch命令。

        在Android目录下执行了envsetup.sh后,下一部就是执行:lunch。lunch是在envsetup.sh里面定义的函数,函数原型如下:

/**********************************************begin**********************************************/

function lunch()
{
    local answer
    if [ "$1" ] ; then
        answer=$1
    else
        print_lunch_menu
        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]*$")
    then
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
        then
            selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
        fi
    elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
    then
        selection=$answer
    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/-.*$//")
    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
    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
} 

/***********************************************end***********************************************/

函数使用 print_lunch_menu 函数将envsetup.sh 设置的LUNCH_MENU_CHOICES变量打印出来,并等待用户的输入,读入用户输入后,将对应数字的字符串赋值给selection, local product=$(echo -n $selection | sed -e "s/-.*$//") local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//"),对selection进行处理,得到product以及variant,前者是将selection中最后一个 - 后面的所有内容去掉而得来,后者刚好相反,是将 - 前面的内容去掉,例如:选择了 4,对应:full_stingray-userdebug,则selection = full_stingray-userdebug,product=full_stingray,variant=userdebug,最后设置环境变量TARGET_PRODUCT=$product等。

        到这里,我们设置了一个重要的环境变量TARGET_PRODUCT,这个后面多处都是依靠它来寻找编译文件的。接下是两个函数:set_stuff_for_environment,printconfig.

set_stuff_for_environment 设置了一下环境变量,就不进去分析了。重点是printconfig函数,其函数体比较简单:get_build_var report_config,调用了另外一个函数,get_build_var 也比较简单,重要语句:

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

它的意思是执行build/core/config.mk,至于dumpvar-$1,我一直没找到,也不知道是什么意思,有知道的告知一下,多谢!

        好了,现在开始进入config.mk文件(其实后面的make命名重复执行,不管了,一步步往下走)。config.mk前面那一堆的变量定义赋值就不说了,直奔重点:

/**********************************************begin**********************************************/
include $(BUILD_SYSTEM)/envsetup.mk
board_config_mk := \
        $(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)
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

/**********************************************end**********************************************/

上面这段代码里,有个重要的变量TARGET_DEVICE,它在哪里定义的呢?它在envsetup.mk中定义的,注意,注意,是envsetup.mk,不要和前面的envsetup.sh搞混了,后则位于build/目录下,前者位于build/core/目录下,来看看envsetup.mk,envsetup.mk里面也设置了一大堆的变量,最重要的是:include $(BUILD_SYSTEM)/product_config.mk,

头是不是有点晕了?我也晕了,先整理一下思路:我们是进来寻找TARGET_DEVICE的,前面都没有设置,只能继续跟进了。finally,在product_config.mk中终于找到了TARGET_DEVICE的定义:

/**********************************************begin**********************************************/

ifneq ($(strip $(TARGET_BUILD_APPS)),)
  $(call import-products,$(call get-product-makefiles,\
      $(SRC_TARGET_DIR)/product/AndroidProducts.mk))
else
  $(call import-products, $(get-all-product-makefiles))
endif # TARGET_BUILD_APPS
$(check-all-products)
ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
$(dump-products)
$(error done)
endif

INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))
#$(error TARGET_PRODUCT $(TARGET_PRODUCT) --> $(INTERNAL_PRODUCT))
TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)
#$(error TARGET_DEVICE $(TARGET_DEVICE) --> $(INTERNAL_PRODUCT))

/***********************************************end***********************************************/

在分析TARGET_DEVICE之前,先说明一下前面的一小段代码,也是很重要的。TARGET_BUILD_APPS等于空,所以执行else分支,$(call import-products, $(get-all-product-makefiles))是读取所有的AndroidProducts.mk,并将其中定义的PRODUCT_MAKEFILES变量都赋值给PRODUCT变量,后面的操作都是在PRODUCT里面寻找需要的文件。好了现在开始分析TARGET_DEVICE

         首先,是INTERNAL_PRODUCT,TARGET_PRODUCT是前面定义的,至于函数resolve-short-product-name,定义再produck.mk文件中,我是没怎么看懂,我也没打算看懂了,因为有个好方法可以知道结果,可以将上面的两个error 打开,这样就能知道结果了:

               $(error TARGET_PRODUCT $(TARGET_PRODUCT) --> $(INTERNAL_PRODUCT))  ,输出如下:

                 TARGET_PRODUCT full_stingray --> device/moto/stingray/full_stingray.mk

经过测试,根据TARGET_PRODUCT=full_stingray寻找full_stingray.mk的条件是:full_stingray.mk文件中的

                                      PRODUCT_NAME ==TARGET_PRODUCT

               $(error TARGET_DEVICE $(TARGET_DEVICE) --> $(INTERNAL_PRODUCT)), 输出如下:

                  TARGET_DEVICE stingray--> device/moto/stingray/full_stingray.mk

经过测试,TARGET_DEVICE等于 full_stingray.mk 中的PRODUCT_DEVICE

          好了目标找到了,终于可以回去了,我们回到config.mk文件中:

/**********************************************begin**********************************************/
include $(BUILD_SYSTEM)/envsetup.mk
board_config_mk := \
        $(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)
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

/**********************************************end**********************************************/

board_config_mk 根据千辛万苦得来的TARGET_DEVICE来寻找BoardConfig.mk,里面是一些cpu级别的配置。

         终于把lunch的主线说完了,后面的make就简单得多了,因为make做了很多重复的操作。

  相关解决方案