編輯:關於Android編程
前面分析了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做了很多重復的操作。
寫在前面的話對於TextView,我想大家都已經熟的不能再熟了。但是它的用法我們真的熟麼?為了避免總是一言不合就去翻官方文檔,在這裡我總結一下我也可能是你容易忽視的一些細
當setCanceledOnTouchOutside(true),點擊陰影處,dialog dismiss時鍵盤不消失的問題。如圖一開始覺得很簡單,監聽下onDimiss
前言:工欲善其事,必先利其器,工作一段時間後,對於以上十個字的感觸是最深的。剛參加工作的時候,並沒有對於要做的事情有著自己的理解,經常是上面分配了工作,自己就乖乖地跑去做
(一)概述在上一節中我們對Fragment進行了一個初步的了解,學習了概念,生命周期,Fragment管理與 Fragment事務,以及動態與靜態加載Fragment。從