天天看點

Android系統篇(二)——Android編譯核心Build系統

《深入解析Android5.0系統》 一書筆記

Android的Build系統非常的龐大,他是基于GUN Make以及shell來建構的,我們主要的面對方向是Android.mk檔案,這也是Android為我們處理好的,不用直接跟shell打交道,Build不光可以處理系統的編譯打包,還能生成img鏡像等,十分的強大。

從大的方面來說,Build系統分為三大塊,第一塊處于build/core目錄下的檔案,這是Build的基礎架構和核心部分,第二塊處于device目錄下的檔案,存放的是項目的一些配置資訊,第三塊就是各大子產品的Android.mk了。

我們本篇文章依葫蘆畫瓢的來侃侃Build,我也是跟着書上來的,我也不是很會C/C++

在說Build前,我簡單帶過一下,我們之前有教過通過SecureCRT遠端連接配接Linux,我們現在用Xshell去連接配接

其實Xshell連接配接是非常簡單的,我們隻需要在ubuntu的終端輸入ifconfig,來檢視你的ip:比如我的ip是:192.111.11.11(假設)

那麼我的Xshell隻需要建立一個端口

Android系統篇(二)——Android編譯核心Build系統

但是如果連接配接失敗,那你就要檢查一下ssh了,在ubuntu的終端輸入:

ps -e |grep ssh      

如果沒有反應,說明你的ssh沒有安裝

sudo apt install openssh-server      

最後就可成功連接配接了

Android系統篇(二)——Android編譯核心Build系統

一.Build系統核心

我們進入build/core目錄下,這個目錄裡有很多的mk檔案以及shell腳本,perl腳本,我們跟蹤一下源碼的編譯

source build/envsetup.sh
lunch
make      

我們順着這三條指令來檢視源碼

1.envsetup.sh

這個腳本我們先來看看他的内容是什麼,我們打開build/envsetup.sh,可以看到裡面的腳本中,中間部分插入了lunch選擇的參數清單,在結尾處,find了device和vendor目錄下的vendorsetuo.sh檔案,然後運作他們,我們找一下,看下是否有vendorsetuo.sh,在 device/lge/hammerhead/目錄下可以看到有一個vendorsetuo.sh腳本

Android系統篇(二)——Android編譯核心Build系統

我們打開它你可以發現,它裡面就一行代碼

add_lunch_combo aosp_hammerhead-userdebug      

它依舊調用add_lunch_combo函數,這樣看來,envsetup.sh除了建立shell指令外,就是執行這一句指令了,我們來看下add_lunch_combo的定義:

Android系統篇(二)——Android編譯核心Build系統

add_lunch_combo指令的功能,是将調用這個指令所傳遞的參數放在一個全局的數組變量LUNCH_MENU_CHOICES中,執行lunch就是列印出這個數組的内容了,也就是我們上篇末尾所展示的樣子,還記得嗎?我選了5

envsetup.sh中還定義了一些實用的shell腳本

  • lunch:指定編譯産品
  • tapas:以互動方式
  • croot:快速切換到源碼的根目錄
  • m:編譯整個源碼,可以不用切換到根目錄
  • mm:編譯目前目錄下的源碼,不包含他們的依賴子產品
  • mmm:編譯指定目錄下的所有子產品,不包含他們的依賴子產品
  • mma:編譯目前目錄下的源碼,包含他們的依賴子產品
  • mmmma:編譯指定目錄下的所有子產品,包含他們的依賴子產品
  • cgrep:對系統下所有的C/C++執行grep指令
  • ggrep:對系統本地所有的Gradle執行grep指令
  • jgrep:對系統下所有的Java執行grep指令
  • resgrep:對系統下所有的res目錄下的xml執行grep指令
  • sgrep:對系統下所有的源檔案執行grep指令
  • godir:根據godir後的參數檔案名在整個目錄下查找,并且切換目錄

2.lunch指令的功能

我們來看第二行代碼lunch,這裡我們分析下這個函數

function lunch()
{
    local answer
    # 如果lunch後面沒有參數,那麼列印菜單,并将選擇值放入answer
    # 如果有參數,直接指派
    if [ "$1" ] ; then
        answer=$1
    else
        print_lunch_menu
        echo -n "Which would you like? [aosp_arm-eng] "
        read answer
    fi

    local selection=
    # 如果answer為空,則selection=aosp_arm-eng
    # 如果answer為數字并且小于或等于菜單數目,則把相應的菜單欄的數字指派給他
    # 如果answer包含了一個-,則将answer指派給selection,否則報錯
    if [ -z "$answer" ]
    then
        selection=aosp_arm-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=
    # 将selection中的-分割前半部分給product
    # 并調用函數check_product去檢查是否存在這個配置檔案
    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
    # 将selection中的-分割前半部分給variant
    # 并調用函數check_variant來檢查這個值是否是:eng,user,debuguser
    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
    # 将變量product指派給TARGET_PRODUCT
    # 将變量variant指派給TARGET_BUILD_VARIANT
    # 将TARGET_BUILD_TYP的環境變量設定為release
    export TARGET_PRODUCT=$product
    export TARGET_BUILD_VARIANT=$variant
    export TARGET_BUILD_TYPE=release

    echo
    # 設定更多的環境變量
    set_stuff_for_environment
    printconfig
}      

lunch指令如果沒有帶參數,直接菜單選擇,他的格式如下:

lunch<product_name>-<build_variant>      

product_name必須是你定義好的産品配置,build_variant必須是eng,user,debuguser其中一個

lunch指令主要還是根據你輸入的産品配置并且設定環境變量,環境變量和産品編譯相關的主要是下面這些:

  • TARGET_PRODUCT 對應 product_name
  • TARGET_BUILD_VARIAN 對應 build_variant
  • TARGET_BUILD_TYPE 一般是release

最後他調用set_stuff_for_environment還會設定一些

3.Build相關的環境變量

我們注意看,執行完我們可以看到列印了很多的配置資訊

Android系統篇(二)——Android編譯核心Build系統

這些配置将影響到我們的編譯過程,我們來分析下

  • PLATFORM_VERSION_CODENAME
  • 表示平台版本的名稱
  • PLATFORM_VERSION
  • Android平台的版本号
  • TARGET_PRODUCT
  • 所編譯的産品名稱
  • TARGET_BUILD_VARIANT
  • 所編譯産品的類型
  • TARGET_BUILD_TYPE
  • 編譯的類型,debug和release
  • TARGET_BUILD_APPS
  • 編譯Android系統時,這個值為null,編譯單子產品時,這個值為所編譯子產品的路徑
  • TARGET_ARCH
  • 表示編譯目标的CPU架構
  • TARGET_ARCH_VARIANT
  • 表示編譯目标的CPU架構版本
  • TARGET_CPU_VARIANT
  • 表示編譯目标的CPU代号
  • TARGET_2ND_ARCH
  • 表示編譯目标的第二CPU架構
  • TARGET_2ND_ARCH_VARIANT
  • 表示編譯目标的第二CPU架構版本
  • TARGET_2ND_CPU_VARIANT
  • 表示編譯目标的第二CPU代号
  • HOST_ARCH
  • 表示編譯平台的架構
  • HOST_OS
  • 表示編譯平台的作業系統
  • HOST_OS_EXTRA
  • 編譯系統之外的額外資訊
  • BUILD_ID
  • BUILD_ID會出現在版本資訊中,可以利用
  • OUT_DIR
  • 編譯結果輸出的路徑

這些變量中第二CPU是Android5.0才加入的,因為當運作64位環境的時候還要考慮32

對于環境變量的修改,可以放到産品的定義中,也可以臨時的修改,比如:

make BUILD_ID="liuguilin"      
Android系統篇(二)——Android編譯核心Build系統

4.Build系統的層次關系

我們lunch後,就是make了,make 後面可以接參數,也是編譯過程的開始,make最終生成的也是zip以及各種img,Build會收集編譯子產品編譯,然後複制二進制檔案,産品配置檔案等最後打包。

一套Android的源碼能編譯出多個不同的産品配置,我們反過來看,實際上我們也可以猜想到,源碼的各個子產品都是分開的,當我們標明了一個産品配置之後,Build會把他們拼接起來,我們來看下具體的工作流程:

在執行make後,實際上執行的是根目錄/Makefile檔案

include build/core/main.mk      
Android系統篇(二)——Android編譯核心Build系統

可以看到,他裡面就一行代碼,執行了main.mk,我們檢視main.mk就可以發現,他實際上是通過include将所有的mk都包含進來,最終在記憶體中形成一個編譯腳本的集合,這才是最終形态的Makefile

Makefile是很龐大的,但是他主要由三種内容構成:變量定義,函數定義和目标,我們如果有必要,還是要看一下他們的親戚關系:

Android系統篇(二)——Android編譯核心Build系統

這些mk檔案的主要作用,我們來看下:

  • main.mk
  • Build的主要檔案,主要作用是包含其他mk,以及定義幾個最重要的編譯目标,同時檢查編譯工具的版本,90如gcc等
  • help.mk
  • Build的幫助檔案,輸入make help會列印出相關的資訊
  • config.mk
  • Build的配置檔案,主要是區分各個産品的配置,并将這些編譯器參數引入産品配置BoardConfig.mk,同時也配置了一些編譯器的路徑等
  • pathmap.mk
  • 給一些頭檔案所在的路徑定義别名,将framework下的源碼目錄按類别引用
  • buildspec.mk
  • 産品定義的參數,不常用
  • envsetup.mk
  • 包含進product_config.mk檔案并且根據其内容設定編譯産品所需要的環境變量,并檢查合法性,指定輸出路徑等
  • version_defaults.mk
  • 定義系統版本相關的配置
  • build_id.mk
  • 定義環境變量 BUILD_ID
  • product_config.mk
  • 包含系統所有的AndroidProdut.mk檔案,并根據目前的産品配置來設定相關的環境變量
  • product.mk
  • 定義product_config.mk檔案中使用的各種函數
  • combo/select.mk
  • 根據環境變量的設定,指定對應的系統和架構總所使用的工具和路徑
  • clang/config.mk
  • 定義了LLVM編譯器clang在不同架構下的路徑和參數
  • dumpvar.mk
  • 列印輸出本次編譯的配置結果
  • cleanbuild.mk
  • 包含了源碼中所有的CleanSoec.mk,定義編譯目标dataclean和installclean
  • definitions.mk
  • 定義了大量Build中使用的函數,如果熟悉這些函數,編寫産品配置會清晰很多
  • dex_preopt.mk
  • 定義了dex優化相關的路徑和參數
  • pdk_config.mk
  • 編譯pdk的配置檔案
  • post_clean.mk
  • 比較目前系統的overlay目錄和上一次build發生的變化
  • legacy_prebuilts.mk
  • 定義系統orebuild子產品清單
  • Makefile
  • 系統最終編譯完成所需要的各種目标和規則

總結:Build系統中定義了大量的編譯變量,每一個都是很值得我們去了解熟悉的,雖然Google并沒有給出太多的介紹。

5.分析main.mk檔案

由于太多了,我們分段來分析

  • 1.檢查gun make 的版本号是否大于等于3.81,否則報錯停止編譯
# Check for broken versions of make.
# (Allow any version under Cygwin since we don't actually build the platform there.)
ifeq (,$(findstring CYGWIN,$(shell uname -sm)))
ifneq (1,$(strip $(shell expr $(MAKE_VERSION) \>= 3.81)))
$(warning ********************************************************************************)
$(warning *  You are using version $(MAKE_VERSION) of make.)
$(warning *  Android can only be built by versions 3.81 and higher.)
$(warning *  see https://source.android.com/source/download.html)
$(warning ********************************************************************************)
$(error stopping)
endif
endif      
  • 2.定義預設的編譯目标為“droid”,是以,指令make 相當于 “make droid”
# This is the default target.  It must be the first declared target.
.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL):      
  • 3.引入幾個mk檔案,注意 include和-include的差別,後者包含的檔案如果不存在不會報錯,前者會停止編譯
# Targets that provide quick help on the build system.
include $(BUILD_SYSTEM)/help.mk

# Set up various standard variables based on configuration
# and host information.
include $(BUILD_SYSTEM)/config.mk

# This allows us to force a clean build - included after the config.mk
# environment setup is done, but before we generate any dependencies.  This
# file does the rm -rf inline so the deps which are all done below will
# be generated correctly
include $(BUILD_SYSTEM)/cleanbuild.mk

# Include the google-specific config
-include vendor/google/build/config.mk

VERSION_CHECK_SEQUENCE_NUMBER := 5
-include $(OUT_DIR)/versions_checked.mk      
  • 4.檢查JAVA的版本是否是1.7或者1.6,不然則會報錯推出,如果使用的版本是1.7,還要求必須是openJDK1.7版本
# Check for the correct version of java, should be 1.7 by
# default, and 1.6 if LEGACY_USE_JAVA6 is set.
ifeq ($(LEGACY_USE_JAVA6),)
required_version := "1.7.x"
required_javac_version := "1.7"
java_version := $(shell echo '$(java_version_str)' | grep '^java .*[ "]1\.7[\. "$$]')
javac_version := $(shell echo '$(javac_version_str)' | grep '[ "]1\.7[\. "$$]')
else # if LEGACY_USE_JAVA6
required_version := "1.6.x"
required_javac_version := "1.6"
java_version := $(shell echo '$(java_version_str)' | grep '^java .*[ "]1\.6[\. "$$]')
javac_version := $(shell echo '$(javac_version_str)' | grep '[ "]1\.6[\. "$$]')
endif # if LEGACY_USE_JAVA6

ifeq ($(strip $(java_version)),)
$(info ************************************************************)
$(info You are attempting to build with the incorrect version)
$(info of java.)
$(info $(space))
$(info Your version is: $(java_version_str).)
$(info The required version is: $(required_version))
$(info $(space))
$(info Please follow the machine setup instructions at)
$(info $(space)$(space)$(space)$(space)https://source.android.com/source/initializing.html)
$(info ************************************************************)
$(error stop)
endif

# Check for the current JDK.
#
# For Java 1.7, we require OpenJDK on linux and Oracle JDK on Mac OS.
# For Java 1.6, we require Oracle for all host OSes.
requires_openjdk := false
ifeq ($(LEGACY_USE_JAVA6),)
ifeq ($(HOST_OS), linux)
requires_openjdk := true
endif
endif


# Check for the current jdk
ifeq ($(requires_openjdk), true)
# The user asked for java7 openjdk, so check that the host
# java version is really openjdk
ifeq ($(shell echo '$(java_version_str)' | grep -i openjdk),)
$(info ************************************************************)
$(info You asked for an OpenJDK 7 build but your version is)
$(info $(java_version_str).)
$(info ************************************************************)
$(error stop)
endif # java version is not OpenJdk
else # if requires_openjdk
ifneq ($(shell echo '$(java_version_str)' | grep -i openjdk),)
$(info ************************************************************)
$(info You are attempting to build with an unsupported JDK.)
$(info $(space))
$(info You use OpenJDK but only Sun/Oracle JDK is supported.)
$(info Please follow the machine setup instructions at)
$(info $(space)$(space)$(space)$(space)https://source.android.com/source/download.html)
$(info ************************************************************)
$(error stop)
endif # java version is not Sun Oracle JDK
endif # if requires_openjdk

# Check for the correct version of javac
ifeq ($(strip $(javac_version)),)
$(info ************************************************************)
$(info You are attempting to build with the incorrect version)
$(info of javac.)
$(info $(space))
$(info Your version is: $(javac_version_str).)
$(info The required version is: $(required_javac_version))
$(info $(space))
$(info Please follow the machine setup instructions at)
$(info $(space)$(space)$(space)$(space)https://source.android.com/source/download.html)
$(info ************************************************************)
$(error stop)
endif      
  • 5.将變量VERSIONS_CHECKED 和 BUILD_EMULATOR寫入out/versions_checked.mk,下次build時會重新包含這些檔案
$(shell echo 'VERSIONS_CHECKED := $(VERSION_CHECK_SEQUENCE_NUMBER)' \
        > $(OUT_DIR)/versions_checked.mk)
$(shell echo 'BUILD_EMULATOR ?= $(BUILD_EMULATOR)' \
        >> $(OUT_DIR)/versions_checked.mk)      
  • 6.再包含3個mk
# Bring in standard build system definitions.
include $(BUILD_SYSTEM)/definitions.mk

# Bring in dex_preopt.mk
include $(BUILD_SYSTEM)/dex_preopt.mk

ifneq ($(filter user userdebug eng,$(MAKECMDGOALS)),)
$(info ***************************************************************)
$(info ***************************************************************)
$(info Do not pass '$(filter user userdebug eng,$(MAKECMDGOALS))' on \
       the make command line.)
$(info Set TARGET_BUILD_VARIANT in buildspec.mk, or use lunch or)
$(info choosecombo.)
$(info ***************************************************************)
$(info ***************************************************************)
$(error stopping)
endif

ifneq ($(filter-out $(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)
$(info ***************************************************************)
$(info ***************************************************************)
$(info Invalid variant: $(TARGET_BUILD_VARIANT)
$(info Valid values are: $(INTERNAL_VALID_VARIANTS)
$(info ***************************************************************)
$(info ***************************************************************)
$(error stopping)
endif

# -----------------------------------------------------------------
# Variable to check java support level inside PDK build.
# Not necessary if the components is not in PDK.
# not defined : not supported
# "sdk" : sdk API only
# "platform" : platform API supproted
TARGET_BUILD_JAVA_SUPPORT_LEVEL := platform

# -----------------------------------------------------------------
# The pdk (Platform Development Kit) build
include build/core/pdk_config.mk      
  • 7.如果變量ONE_SHOT_MAKEFLTE的值不為空,那麼将他定義的檔案包含進來,當編譯一個單獨的子產品時,ONE_SHOT_MAKEFLTE的值會設為一個子產品的make檔案路徑,如果值ONE_SHOT_MAKEFLTE為空,說明正在編譯整個系統,是以,調用findleayes.py腳本搜尋系統裡所有的Android.mk檔案并将它們包含進來
ifneq ($(ONE_SHOT_MAKEFILE),)
# We've probably been invoked by the "mm" shell function
# with a subdirectory's makefile.
include $(ONE_SHOT_MAKEFILE)
# Change CUSTOM_MODULES to include only modules that were
# defined by this makefile; this will install all of those
# modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE
# so that the modules will be installed in the same place they
# would have been with a normal make.
CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS)))
FULL_BUILD :=
# Stub out the notice targets, which probably aren't defined
# when using ONE_SHOT_MAKEFILE.
NOTICE-HOST-%: ;
NOTICE-TARGET-%: ;

# A helper goal printing out install paths
.PHONY: GET-INSTALL-PATH
GET-INSTALL-PATH:
    @$(foreach m, $(ALL_MODULES), $(if $(ALL_MODULES.$(m).INSTALLED), \
        echo 'INSTALL-PATH: $(m) $(ALL_MODULES.$(m).INSTALLED)';))

else # ONE_SHOT_MAKEFILE

ifneq ($(dont_bother),true)
#
# Include all of the makefiles in the system
#

# Can't use first-makefiles-under here because
# --mindepth=2 makes the prunes not work.
subdir_makefiles := \
    $(shell build/tools/findleaves.py --prune=$(OUT_DIR) --prune=.repo --prune=.git $(subdirs) Android.mk)

$(foreach mk, $(subdir_makefiles), $(info including $(mk) ...)$(eval include $(mk)))

endif # dont_bother

endif # ONE_SHOT_MAKEFILE      
  • 8.根據編譯類型來設定ro.secure的屬性
## user/userdebug ##

user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
enable_target_debugging := true
tags_to_install :=
ifneq (,$(user_variant))
  # Target is secure in user builds.
  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1

  ifeq ($(user_variant),userdebug)
    # Pick up some extra useful tools
    tags_to_install += debug

    # Enable Dalvik lock contention logging for userdebug builds.
    ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.lockprof.threshold=500
  else
    # Disable debugging in plain user builds.
    enable_target_debugging :=
  endif

  # Turn on Dalvik preoptimization for libdvm.so user builds, but only if not
  # explicitly disabled and the build is running on Linux (since host
  # Dalvik isn't built for non-Linux hosts).
  ifeq (,$(WITH_DEXPREOPT))
    ifeq ($(DALVIK_VM_LIB),libdvm.so)
      ifeq ($(user_variant),user)
        ifeq ($(HOST_OS),linux)
          WITH_DEXPREOPT := true
        endif
      endif
    endif
  endif

  # Disallow mock locations by default for user builds
  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0

else # !user_variant
  # Turn on checkjni for non-user builds.
  ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1
  # Set device insecure for non-user builds.
  ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0
  # Allow mock locations by default for non user builds
  ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1
endif # !user_variant

ifeq (true,$(strip $(enable_target_debugging)))
  # Target is more debuggable and adbd is on by default
  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1
  # Include the debugging/testing OTA keys in this build.
  INCLUDE_TEST_OTA_KEYS := true
else # !enable_target_debugging
  # Target is less debuggable and adbd is off by default
  ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0
endif # !enable_target_debugging

## eng ##

ifeq ($(TARGET_BUILD_VARIANT),eng)
tags_to_install := debug eng
ifneq ($(filter ro.setupwizard.mode=ENABLED, $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))),)
  # Don't require the setup wizard on eng builds
  ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\
          $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))) \
          ro.setupwizard.mode=OPTIONAL
endif
ifndef is_sdk_build
  # Don't even verify the image on eng builds to speed startup
  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.image-dex2oat-filter=verify-none
  # Don't compile apps on eng builds to speed startup
  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.dex2oat-filter=interpret-only
endif
endif      
  • 9.包含進post_clean.mk和legacypre_buildts.mk腳本,根據legacypre_buildts.mk中定義的變量GRANDFATHERED_ALL_PREBUILT檢查是否有不在這個清單的prebuilt子產品,如果有則報錯推出
# Now with all Android.mks loaded we can do post cleaning steps.
include $(BUILD_SYSTEM)/post_clean.mk

ifeq ($(stash_product_vars),true)
  $(call assert-product-vars, __STASHED)
endif

include $(BUILD_SYSTEM)/legacy_prebuilts.mk
ifneq ($(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),)
  $(warning *** Some files have been added to ALL_PREBUILT.)
  $(warning *)
  $(warning * ALL_PREBUILT is a deprecated mechanism that)
  $(warning * should not be used for new files.)
  $(warning * As an alternative, use PRODUCT_COPY_FILES in)
  $(warning * the appropriate product definition.)
  $(warning * build/target/product/core.mk is the product)
  $(warning * definition used in all products.)
  $(warning *)
  $(foreach bad_prebuilt,$(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),$(warning * unexpected $(bad_prebuilt) in ALL_PREBUILT))
  $(warning *)
  $(error ALL_PREBUILT contains unexpected files)
endif      
  • 10.xxx