首页 > 移动平台 > 详细

Android编译系统过程研究

时间:2016-05-22 02:12:11      阅读:425      评论:0      收藏:0      [点我收藏+]

Android编译系统过程研究

大家平时用虚拟机编译Android系统源码的时候,无非就是下面三个步骤:

<!--[if !supportLists]-->1、<!--[endif]-->执行source?build/envsetup.sh命令

<!--[if !supportLists]-->2、<!--[endif]-->执行lunch命令,选择需要编译的系统版本

<!--[if !supportLists]-->3、<!--[endif]-->执行make命令,然后就是编译你选择好的系统版本

那么研究Android的编译过程,无非也就是研究这三个步骤各自做了哪些操作。

接下来,将会对这三个步骤进行详细的分析。

一、bulid/envsetup.sh脚本分析

source?build/envsetup.sh这个命令就是将envsetup.sh定义的所有命令加载到环境变量中,像后面要使用的lunch、make命令就是这里定义的。打开这个脚本文件,发现里面定义了很多函数(以function为开头),下面分析一下主要函数的一些功能:

function?hmm():显示帮助信息,列出所有支持的命令,比如lunch、mm、mmm等

function?get_abs_build_var():获取编译时一些变量的绝对路径(比如BUILD_SYSTEM)

function?get_build_var():获取编译时一些变量的路径

function?check_product():检查产品是否支持编译

function?check_variant():检查变量variant是否有效,只能是user、userdebug、eng

function?setpaths():设置一些文件路径,并将一些编译所需的路径添加到环境变量中去

function?printconfig():打印配置信息

function?set_sequence_number():设置BUILD_ENV_SEQUENCE_NUMBER的值

function?settitle():设置PROMPT_COMMAND的值

function?set_java_home():设置java主目录

function?set_stuff_for_environment():调用setpaths、settitle、set_java_home、set_sequence_number函数,并设置ANDROID_BUILD_TOP值为Android源码目录

function?choosetype():选择编译类型,release和debug中的一个

function?chooseproduct():用户输入编译产品

function?choosevariant():用户选择variant,只能是user、userdebug、eng中的一个

function?choosecombo():调用choosetype、chooseproduct、choosevariant等函数

function?add_lunch_combo():增加lunch命令的选择项

function?print_lunch_menu():打印lunch命令可选择的项目列表

function?lunch():lunch命令的执行逻辑

function?gettop():获取Android源码根目录

function?m():m命令的执行逻辑

function?findmakefile():查找当前目录下Android.mk文件路径

function?mm():mm命令的执行逻辑

function?mmm():mmm命令的执行逻辑

function?croot():进入Android源码根目录

function?pid():查看某个进程的id

function?runtest():执行测试脚本

function?godir?():进入用户输入文件的所在目录

function?set_java_home():设置环境变量JAVA_HOME

除了定义了很多函数之外,还执行了下面的操作:

for?f?in?`test?-d?device?&&?find?-L?device?-maxdepth?4?-name?‘vendorsetup.sh‘?2>?/dev/null`?\

?????????`test?-d?vendor?&&?find?-L?vendor?-maxdepth?4?-name?‘vendorsetup.sh‘?2>?/dev/null`

do

????echo?"including?$f"

????.?$f

done

unset?f

?

addcompletions

?

这里的操作就是查找vendor目录和device目录下的vendorsetup.sh文件,查找到之后就执行这些脚本文件。addcompletions函数主要是查找sdk/bash_completion目录下所有的.bash文件,找到之后执行这些文件。

?

1.1、执行vendorsetup.sh

vendorsetup.sh脚本都是类似“add_lunch_combo?sp7731geaplus_dt-userdebug”这样的内容,也就是调用add_lunch_combo这个函数,将各自产品添加到LUNCH_MENU_CHOICES变量中去。

?

1.2、执行.bash脚本

这些脚本主要是为命令提供tab支持,有了这些tab支持,输入命令后如果某个选项忘记了,只需要敲tab键,就能获得提示,使用命令更加方便。例如sdk/bash_completion/adb.bash就是为adb命令提供tab键提示功能。

?

二、lunch命令

接下来就分析一下lunch命令的流程,找到envsetup.sh脚本中lunch函数:

function?lunch()

{

????local?answer

?

????if?[?"$1"?]?;?then

????????answer=$1

????else

#如果没有输入参数,则打印出产品列表,让用户选择

????????print_lunch_menu

????????echo?-n?"Which?would?you?like??[aosp_arm-eng]?"

????????read?answer

????fi

?

????local?selection=

?

????if?[?-z?"$answer"?]

????then

????????selection=aosp_arm-eng??#默认产品为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=

?

#从用户的选择中提取出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

#从用户选择中提取出variant

????local?variant=$(echo?-n?$selection?|?sed?-e?"s/^[^\-]*-//")

?

#检查variant是否支持

????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 !supportLists]-->三、<!--[endif]-->make命令

Make命令就是去执行Android源码根目录下是Makefile脚本,脚本内容如下:

###?DO?NOT?EDIT?THIS?FILE?###

include?build/core/main.mk

###?DO?NOT?EDIT?THIS?FILE?###

意思就是去加载并执行build/core/main.mk脚本。

接下来分析main.mk脚本的执行流程:

<!--[if !supportLists]-->1、<!--[endif]-->根据ANDROID_BUILD_SHELL的定义来选择编译系统需要的SHELL,分别为/bin/sh/bin/bash

ifdef?ANDROID_BUILD_SHELL

SHELL?:=?$(ANDROID_BUILD_SHELL)

else

SHELL?:=?/bin/bash

endif

?

<!--[if !supportLists]-->2、<!--[endif]-->检查MAKE_VERSION,必须大于或等于3.81

ifeq?(,$(findstring?CYGWIN,$(shell?uname?-sm)))

ifneq?(1,$(strip?$(shell?expr?$(MAKE_VERSION)?\>=?3.81)))

endif

endif

?

<!--[if !supportLists]-->3、<!--[endif]-->定义一些编译时所需的变量值和默认目标droidmake命令不加任何参数就执行这个)

PWD?:=?$(shell?pwd)

TOP?:=?.

TOPDIR?:=

BUILD_SYSTEM?:=?$(TOPDIR)build/core

BUILD_SYSTEM_VENDOR?:=?$(TOPDIR)build/vendor

.PHONY:?droid

DEFAULT_GOAL?:=?droid

$(DEFAULT_GOAL):

?

<!--[if !supportLists]-->4、<!--[endif]-->加载一些其他的.mk脚本

include?$(BUILD_SYSTEM)/help.mk

include?$(BUILD_SYSTEM)/config.mk

include?$(BUILD_SYSTEM)/cleanbuild.mk

?

<!--[if !supportLists]-->5、<!--[endif]-->检查java版本、jdk版本、javac版本

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

ifeq?($(requires_openjdk),?true)

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

?

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

6、加载一些.mk脚本,并确定好TARGET_BUILD_VARIANT变量的值(user/userdebug/eng

include?$(BUILD_SYSTEM)/definitions.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

?

?

<!--[if !supportLists]-->7、<!--[endif]-->确定is_sdk_build的值(后面需要用到)

is_sdk_build?:=

?

ifneq?($(filter?sdk?win_sdk?sdk_addon,$(MAKECMDGOALS)),)

is_sdk_build?:=?true

endif

?

<!--[if !supportLists]-->8、<!--[endif]-->根据TARGET_BUILD_VARIANT的值,设置不同的ro属性

user_variant?:=?$(filter?user?userdebug,$(TARGET_BUILD_VARIANT))

enable_target_debugging?:=?true

tags_to_install?:=

ifneq?(,$(user_variant))

??ADDITIONAL_DEFAULT_PROPERTIES?+=?ro.secure=1

?

??ifeq?($(user_variant),userdebug)

????tags_to_install?+=?debug

????ADDITIONAL_BUILD_PROPERTIES?+=?dalvik.vm.lockprof.threshold=500

??else

????enable_target_debugging?:=

??endif

?

??ifeq?(,$(WITH_DEXPREOPT))

????ifeq?($(DALVIK_VM_LIB),libdvm.so)

??????ifeq?($(user_variant),user)

????????ifeq?($(HOST_OS),linux)

??????????WITH_DEXPREOPT?:=?true

????????endif

??????endif

????endif

??endif

?

else?#?!user_variant

??ADDITIONAL_BUILD_PROPERTIES?+=?ro.kernel.android.checkjni=1

??ADDITIONAL_DEFAULT_PROPERTIES?+=?ro.secure=0

??ADDITIONAL_DEFAULT_PROPERTIES?+=?ro.allow.mock.location=1

endif?#?!user_variant

?

ifeq?(true,$(strip?$(enable_target_debugging)))

??ADDITIONAL_DEFAULT_PROPERTIES?+=?ro.debuggable=1

??INCLUDE_TEST_OTA_KEYS?:=?true

else?#?!enable_target_debugging

??ADDITIONAL_DEFAULT_PROPERTIES?+=?ro.debuggable=0

endif?#?!enable_target_debugging

?

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

??ADDITIONAL_BUILD_PROPERTIES?+=?dalvik.vm.image-dex2oat-filter=verify-none

??ADDITIONAL_BUILD_PROPERTIES?+=?dalvik.vm.dex2oat-filter=interpret-only

endif

endif

?

?

?

?

9、判断是否sdk编译,如果是则检查MAKECMDGOALS的值并设置一些属性的值

ifdef?is_sdk_build

sdk_repo_goal?:=?$(strip?$(filter?sdk_repo,$(MAKECMDGOALS)))

MAKECMDGOALS?:=?$(strip?$(filter-out?sdk_repo,$(MAKECMDGOALS)))

?

ifneq?($(words?$(filter-out?$(INTERNAL_MODIFIER_TARGETS)?checkbuild?emulator_tests?target-files-package,$(MAKECMDGOALS))),1)

$(error?The?‘sdk‘?target?may?not?be?specified?with?any?other?targets)

endif

tags_to_install?:=?debug?eng

ADDITIONAL_BUILD_PROPERTIES?+=?xmpp.auto-presence=true

ADDITIONAL_BUILD_PROPERTIES?+=?ro.config.nocheckin=yes

else?#?!sdk

endif

?

<!--[if !supportLists]-->10、<!--[endif]-->判断PRODUCT_TAGS的值,然后设置虚拟机的一些参数

ifneq?($(filter?dalvik.gc.type-precise,$(PRODUCT_TAGS)),)??

??ADDITIONAL_BUILD_PROPERTIES?+=?dalvik.vm.dexopt-flags=m=y

endif

ADDITIONAL_BUILD_PROPERTIES?+=?net.bt.name=Android

ADDITIONAL_BUILD_PROPERTIES?+=?dalvik.vm.stack-trace-file=/data/anr/traces.txt

?

11、通过findleaves.py工具查找subdir下所有的mk文件

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)))

?

?

<!--[if !supportLists]-->12、<!--[endif]-->加载一些.mk文件

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

?

<!--[if !supportLists]-->13、<!--[endif]-->处理编译依赖,包含32/64位系统的编译

define?get-32-bit-modules

$(strip?$(foreach?m,$(1),\

??$(if?$(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\

????$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX))))

endef

define?get-32-bit-modules-if-we-can

$(strip?$(foreach?m,$(1),\

??$(if?$(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\

????$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX),

????$(m))))

endef

?

$(foreach?m,$(ALL_MODULES),\

??$(eval?r?:=?$(ALL_MODULES.$(m).REQUIRED))\

??$(if?$(r),\

????$(if?$(ALL_MODULES.$(m).FOR_2ND_ARCH),\

??????$(eval?r_r?:=?$(call?get-32-bit-modules-if-we-can,$(r))),\

??????$(if?$(filter?EXECUTABLES?SHARED_LIBRARIES,$(ALL_MODULES.$(m).CLASS)),\

????????$(eval?r_r?:=?$(r)),\

????????$(eval?r_r?:=?$(r)?$(call?get-32-bit-modules,$(r)))\

???????)\

?????)\

?????$(eval?ALL_MODULES.$(m).REQUIRED?:=?$(strip?$(r_r)))\

??)\

)

r_r?:=

?

define?add-required-deps

$(1):?|?$(2)

endef

?

?

?

14、根据FULL_BUILD的值,确定product_FILESproduct_MODULES的值

ifdef?FULL_BUILD

??product_MODULES?:=?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)

??#?Filter?out?the?overridden?packages?before?doing?expansion

??product_MODULES?:=?$(filter-out?$(foreach?p,?$(product_MODULES),?\

??????$(PACKAGES.$(p).OVERRIDES)),?$(product_MODULES))

?

??#?Resolve?the?:32?:64?module?name

??modules_32?:=?$(patsubst?%:32,%,$(filter?%:32,?$(product_MODULES)))

??modules_64?:=?$(patsubst?%:64,%,$(filter?%:64,?$(product_MODULES)))

??modules_rest?:=?$(filter-out?%:32?%:64,$(product_MODULES))

??#?Note?for?32-bit?product,?$(modules_32)?and?$(modules_64)?will?be

??#?added?as?their?original?module?names.

??product_MODULES?:=?$(call?get-32-bit-modules-if-we-can,?$(modules_32))

??product_MODULES?+=?$(modules_64)

??#?For?the?rest?we?add?both

??product_MODULES?+=?$(call?get-32-bit-modules,?$(modules_rest))

??product_MODULES?+=?$(modules_rest)

?

??$(call?expand-required-modules,product_MODULES,$(product_MODULES))

?

??product_FILES?:=?$(call?module-installed-files,?$(product_MODULES))

??ifeq?(0,1)

????$(info?product_FILES?for?$(TARGET_DEVICE)?($(INTERNAL_PRODUCT)):)

????$(foreach?p,$(product_FILES),$(info?:???$(p)))

????$(error?done)

??endif

else

??#?We‘re?not?doing?a?full?build,?and?are?probably?only?including

??#?a?subset?of?the?module?makefiles.??Don‘t?try?to?build?any?modules

??#?requested?by?the?product,?because?we?probably?won‘t?have?rules

??#?to?build?them.

??product_FILES?:=

endif

?

<!--[if !supportLists]-->15、<!--[endif]-->检查我们构建的模块是否冗余了

modules_to_check?:=?$(foreach?m,$(ALL_MODULES),$(ALL_MODULES.$(m).CHECKED))

ifneq?($(filter?all,$(MAKECMDGOALS)),)

modules_to_check?+=?$(foreach?m,$(ALL_MODULES),$(ALL_MODULES.$(m).BUILT))

endif

?

#?for?easier?debugging

modules_to_check?:=?$(sort?$(modules_to_check))

?

<!--[if !supportLists]-->16、<!--[endif]-->上面的都是配置操作,接下来就是整个项目的编译操作,确定好要生成的目标并开始编译。make默认执行droiddroid依赖于droidcoredroidcore依赖于files等等,这些依赖关系就控制着整个项目的编译流程。

.PHONY:?files

files:?prebuilt?\

????????$(modules_to_install)?\

????????$(INSTALLED_ANDROID_INFO_TXT_TARGET)

.PHONY:?droidcore

droidcore:?files?\

systemimage?\

$(INSTALLED_CHIPRAM_TARGET)?\

$(INSTALLED_UBOOT_TARGET)?\

$(INSTALLED_BOOTIMAGE_TARGET)?\

$(INSTALLED_RECOVERYIMAGE_TARGET)?\

$(INSTALLED_USERDATAIMAGE_TARGET)?\

$(INSTALLED_CACHEIMAGE_TARGET)?\

$(INSTALLED_PRODNVIMAGE_TARGET)?\

$(INSTALLED_VENDORIMAGE_TARGET)?\

$(INSTALLED_FILES_FILE)

?

?

?

四、加载的其他mk脚本分析

1help.mk的分析

这个脚本功能主要是打印出编译时的一些帮助信息

.PHONY:?help

help:

@echo

@echo?"Common?make?targets:"

@echo?"----------------------------------------------------------------------------------"

@echo?"droid???????????????????Default?target"

@echo?"clean???????????????????(aka?clobber)?equivalent?to?rm?-rf?out/"

@echo?"snod????????????????????Quickly?rebuild?the?system?image?from?built?packages"

@echo?"offline-sdk-docs????????Generate?the?HTML?for?the?developer?SDK?docs"

@echo?"doc-comment-check-docs??Check?HTML?doc?links?&?validity,?without?generating?HTML"

@echo?"libandroid_runtime??????All?the?JNI?framework?stuff"

@echo?"framework???????????????All?the?java?framework?stuff"

@echo?"services????????????????The?system?server?(Java)?and?friends"

@echo?"help????????????????????You‘re?reading?it?right?now"

?

.PHONY:?out

out:

@echo?"I‘m?sure?you‘re?nice?and?all,?but?no?thanks."

?

?

?

?

2config.mk的分析

2.1、定义一些文件路径变量

SRC_DOCS:=?$(TOPDIR)docs

SRC_HEADERS?:=?\

$(TOPDIR)system/core/include?\

$(TOPDIR)hardware/libhardware/include?\

$(TOPDIR)hardware/libhardware_legacy/include?\

$(TOPDIR)hardware/ril/include?\

$(TOPDIR)libnativehelper/include?\

$(TOPDIR)frameworks/native/include?\

$(TOPDIR)frameworks/native/opengl/include?\

$(TOPDIR)frameworks/av/include?\

$(TOPDIR)frameworks/base/include

SRC_HOST_HEADERS:=$(TOPDIR)tools/include

SRC_LIBRARIES:=?$(TOPDIR)libs

SRC_SERVERS:=?$(TOPDIR)servers

SRC_TARGET_DIR?:=?$(TOPDIR)build/target

SRC_API_DIR?:=?$(TOPDIR)prebuilts/sdk/api

SRC_SYSTEM_API_DIR?:=?$(TOPDIR)prebuilts/sdk/system-api

SRC_DROIDDOC_DIR?:=?$(TOPDIR)build/tools/droiddoc

?

2.2、加载pathmap.mk脚本文件,这个文件主要定义了一些绝对路径变量,便于其他脚本调用。

include?$(BUILD_SYSTEM)/pathmap.mk

?

2.3、定义一些重要编译命令

BUILD_COMBOS:=?$(BUILD_SYSTEM)/combo

?

CLEAR_VARS:=?$(BUILD_SYSTEM)/clear_vars.mk

BUILD_HOST_STATIC_LIBRARY:=?$(BUILD_SYSTEM)/host_static_library.mk

BUILD_HOST_SHARED_LIBRARY:=?$(BUILD_SYSTEM)/host_shared_library.mk

BUILD_STATIC_LIBRARY:=?$(BUILD_SYSTEM)/static_library.mk

BUILD_RAW_STATIC_LIBRARY?:=?$(BUILD_SYSTEM)/raw_static_library.mk

BUILD_SHARED_LIBRARY:=?$(BUILD_SYSTEM)/shared_library.mk

BUILD_EXECUTABLE:=?$(BUILD_SYSTEM)/executable.mk

BUILD_RAW_EXECUTABLE:=?$(BUILD_SYSTEM)/raw_executable.mk

BUILD_HOST_EXECUTABLE:=?$(BUILD_SYSTEM)/host_executable.mk

BUILD_PACKAGE:=?$(BUILD_SYSTEM)/package.mk

BUILD_PHONY_PACKAGE:=?$(BUILD_SYSTEM)/phony_package.mk

BUILD_HOST_PREBUILT:=?$(BUILD_SYSTEM)/host_prebuilt.mk

BUILD_PREBUILT:=?$(BUILD_SYSTEM)/prebuilt.mk

BUILD_MULTI_PREBUILT:=?$(BUILD_SYSTEM)/multi_prebuilt.mk

BUILD_JAVA_LIBRARY:=?$(BUILD_SYSTEM)/java_library.mk

BUILD_STATIC_JAVA_LIBRARY:=?$(BUILD_SYSTEM)/static_java_library.mk

BUILD_HOST_JAVA_LIBRARY:=?$(BUILD_SYSTEM)/host_java_library.mk

BUILD_DROIDDOC:=?$(BUILD_SYSTEM)/droiddoc.mk

BUILD_COPY_HEADERS?:=?$(BUILD_SYSTEM)/copy_headers.mk

BUILD_NATIVE_TEST?:=?$(BUILD_SYSTEM)/native_test.mk

BUILD_HOST_NATIVE_TEST?:=?$(BUILD_SYSTEM)/host_native_test.mk

?

BUILD_SHARED_TEST_LIBRARY?:=?$(BUILD_SYSTEM)/shared_test_lib.mk

BUILD_HOST_SHARED_TEST_LIBRARY?:=?$(BUILD_SYSTEM)/host_shared_test_lib.mk

BUILD_STATIC_TEST_LIBRARY?:=?$(BUILD_SYSTEM)/static_test_lib.mk

BUILD_HOST_STATIC_TEST_LIBRARY?:=?$(BUILD_SYSTEM)/host_static_test_lib.mk

?

BUILD_NOTICE_FILE?:=?$(BUILD_SYSTEM)/notice_files.mk

BUILD_HOST_DALVIK_JAVA_LIBRARY?:=?$(BUILD_SYSTEM)/host_dalvik_java_library.mk

BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY?:=?$(BUILD_SYSTEM)/host_dalvik_static_java_library.mk

?

#############?vendor?configs?################

BUILD_THEME_PACKAGE?:=?$(BUILD_SYSTEM_VENDOR)/themepackage.mk

BUILD_ADDON_PACKAGE?:=?$(BUILD_PACKAGE)

APPLY_PRODUCT_REVISION:=?build/vendor/product_config.mk

其中CLEAR_VARS:用来清除之前定义的环境变量

BUILD_SHARED_LIBRARY:用来指定编译动态库过程

?

?

2.4、打包后缀名的设置

COMMON_PACKAGE_SUFFIX?:=?.zip

COMMON_JAVA_PACKAGE_SUFFIX?:=?.jar

COMMON_ANDROID_PACKAGE_SUFFIX?:=?.apk

?

2.5、加载一些其他mk文件

ifndef?ANDROID_BUILDSPEC

ANDROID_BUILDSPEC?:=?$(TOPDIR)buildspec.mk

endif

-include?$(ANDROID_BUILDSPEC)

?

#?---------------------------------------------------------------

#?Define?most?of?the?global?variables.??These?are?the?ones?that

#?are?specific?to?the?user‘s?build?configuration.

include?$(BUILD_SYSTEM)/envsetup.mk

....

include?$(BUILD_SYSTEM)/combo/select.mk

?

2.6、判断支持32位编译还是64位编译

ifeq?(,$(TARGET_CPU_ABI_LIST))

??ifeq?($(TARGET_IS_64_BIT)|$(TARGET_PREFER_32_BIT_APPS),true|true)

????TARGET_CPU_ABI_LIST?:=?$(TARGET_CPU_ABI_LIST_32_BIT)?$(TARGET_CPU_ABI_LIST_64_BIT)

??else

????TARGET_CPU_ABI_LIST?:=?$(TARGET_CPU_ABI_LIST_64_BIT)?$(TARGET_CPU_ABI_LIST_32_BIT)

??endif

endif

?

2.7、加载javac.mk脚本

include?$(BUILD_SYSTEM)/combo/javac.mk

?

2.8、设置一些命令的变量(比如aaptaidl等)

AAPT?:=?$(HOST_OUT_EXECUTABLES)/aapt$(HOST_EXECUTABLE_SUFFIX)

AIDL?:=?$(HOST_OUT_EXECUTABLES)/aidl$(HOST_EXECUTABLE_SUFFIX)

PROTOC?:=?$(HOST_OUT_EXECUTABLES)/aprotoc$(HOST_EXECUTABLE_SUFFIX)

SIGNAPK_JAR?:=?$(HOST_OUT_JAVA_LIBRARIES)/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)

MKBOOTFS?:=?$(HOST_OUT_EXECUTABLES)/mkbootfs$(HOST_EXECUTABLE_SUFFIX)

MINIGZIP?:=?$(HOST_OUT_EXECUTABLES)/minigzip$(HOST_EXECUTABLE_SUFFIX)

ifeq?(,$(strip?$(BOARD_CUSTOM_MKBOOTIMG)))

MKBOOTIMG?:=?$(HOST_OUT_EXECUTABLES)/mkbootimg$(HOST_EXECUTABLE_SUFFIX)

else

MKBOOTIMG?:=?$(BOARD_CUSTOM_MKBOOTIMG)

endif

MKYAFFS2?:=?$(HOST_OUT_EXECUTABLES)/mkyaffs2image$(HOST_EXECUTABLE_SUFFIX)

APICHECK?:=?$(HOST_OUT_EXECUTABLES)/apicheck$(HOST_EXECUTABLE_SUFFIX)

FS_GET_STATS?:=?$(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)

MKEXT2IMG?:=?$(HOST_OUT_EXECUTABLES)/genext2fs$(HOST_EXECUTABLE_SUFFIX)

MAKE_EXT4FS?:=?$(HOST_OUT_EXECUTABLES)/make_ext4fs$(HOST_EXECUTABLE_SUFFIX)

MKEXTUSERIMG?:=?$(HOST_OUT_EXECUTABLES)/mkuserimg.sh

MAKE_F2FS?:=?$(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)

MKF2FSUSERIMG?:=?$(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh

MKEXT2BOOTIMG?:=?external/genext2fs/mkbootimg_ext2.sh

SIMG2IMG?:=?$(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX)

E2FSCK?:=?$(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)

MKTARBALL?:=?build/tools/mktarball.sh

TUNE2FS?:=?$(HOST_OUT_EXECUTABLES)/tune2fs$(HOST_EXECUTABLE_SUFFIX)

E2FSCK?:=?$(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)

JARJAR?:=?$(HOST_OUT_JAVA_LIBRARIES)/jarjar.jar

PROGUARD?:=?external/proguard/bin/proguard.sh

JAVATAGS?:=?build/tools/java-event-log-tags.py

LLVM_RS_CC?:=?$(HOST_OUT_EXECUTABLES)/llvm-rs-cc$(HOST_EXECUTABLE_SUFFIX)

BCC_COMPAT?:=?$(HOST_OUT_EXECUTABLES)/bcc_compat$(HOST_EXECUTABLE_SUFFIX)

LINT?:=?prebuilts/sdk/tools/lint

RMTYPEDEFS?:=?$(HOST_OUT_EXECUTABLES)/rmtypedefs

APPEND2SIMG?:=?$(HOST_OUT_EXECUTABLES)/append2simg

VERITY_SIGNER?:=?$(HOST_OUT_EXECUTABLES)/verity_signer

BUILD_VERITY_TREE?:=?$(HOST_OUT_EXECUTABLES)/build_verity_tree

BOOT_SIGNER?:=?$(HOST_OUT_EXECUTABLES)/boot_signer

?

2.9、执行shell脚本去查找jdktoolsjar,根据系统环境的不同(OS32位和64位)执行不同的java操作

ifeq?($(HOST_OS),darwin)

ifeq?($(LEGACY_USE_JAVA6),)

HOST_JDK_TOOLS_JAR:=?$(shell?$(BUILD_SYSTEM)/find-jdk-tools-jar.sh)

else

#?Deliberately?set?to?blank?for?Java?6?installations?on?MacOS.?These

#?versions?allegedly?use?a?non-standard?directory?structure.

HOST_JDK_TOOLS_JAR?:=

endif

else

HOST_JDK_TOOLS_JAR:=?$(shell?$(BUILD_SYSTEM)/find-jdk-tools-jar.sh)

endif

?

ifneq?($(HOST_JDK_TOOLS_JAR),)

ifeq?($(wildcard?$(HOST_JDK_TOOLS_JAR)),)

$(error?Error:?could?not?find?jdk?tools.jar,?please?check?if?your?JDK?was?installed?correctly)

endif

endif

?

2.10、根据TARGET_BUILD_VARIANTdebuguseruserdebug)的不同,设置不同的签名

ifdef?PRODUCT_DEFAULT_DEV_CERTIFICATE

??DEFAULT_SYSTEM_DEV_CERTIFICATE?:=?$(PRODUCT_DEFAULT_DEV_CERTIFICATE)

else

ifeq?($(strip?$(TARGET_BUILD_VARIANT)),user)

??DEFAULT_SYSTEM_DEV_CERTIFICATE?:=?build/target/product/security/release/releasekey

??BUILD_KEYS?:=?release-keys

else

??DEFAULT_SYSTEM_DEV_CERTIFICATE?:=?build/target/product/security/testkey

endif

endif

?

?

?

2.11DEX2OAT运行的一些变量配置

DEX2OAT_TARGET_ARCH?:=?$(TARGET_ARCH)

DEX2OAT_TARGET_CPU_VARIANT?:=?$(TARGET_CPU_VARIANT)

DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES?:=?default

ifneq?(,$(filter?$(DEX2OAT_TARGET_CPU_VARIANT),cortex-a7?cortex-a15?krait?denver))

??DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES?:=?div

endif

?

ifdef?TARGET_2ND_ARCH

$(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH?:=?$(TARGET_2ND_ARCH)

$(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT?:=?$(TARGET_2ND_CPU_VARIANT)

$(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES?:=?default

ifneq?(,$(filter?$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT),cortex-a7?cortex-a15?krait?denver))

??$(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES?:=?div

endif

endif

?

3envsetup.mk的分析

3.1、加载version_defaults.mk脚本

include?$(BUILD_SYSTEM)/version_defaults.mk

?

3.2、设置一些变量的值

#?---------------------------------------------------------------

#?If?you?update?the?build?system?such?that?the?environment?setup

#?or?buildspec.mk?need?to?be?updated,?increment?this?number,?and

#?people?who?haven‘t?re-run?those?will?have?to?do?so?before?they

#?can?build.??Make?sure?to?also?update?the?corresponding?value?in

#?buildspec.mk.default?and?envsetup.sh.

CORRECT_BUILD_ENV_SEQUENCE_NUMBER?:=?10

?

#?---------------------------------------------------------------

#?The?product?defaults?to?generic?on?hardware

#?NOTE:?This?will?be?overridden?in?product_config.mk?if?make

#?was?invoked?with?a?PRODUCT-xxx-yyy?goal.

ifeq?($(TARGET_PRODUCT),)

TARGET_PRODUCT?:=?full

endif

?

?

#?the?variant?--?the?set?of?files?that?are?included?for?a?build

ifeq?($(strip?$(TARGET_BUILD_VARIANT)),)

TARGET_BUILD_VARIANT?:=?eng

endif

?

3.3、根据shell命令uname?-sm执行结果,也就是当前编译系统的环境,来设置一些变量的值,我这边虚拟机运行的结果是:Linux?x86_64

UNAME?:=?$(shell?uname?-sm)

?

#?HOST_OS

ifneq?(,$(findstring?Linux,$(UNAME)))

??HOST_OS?:=?linux

endif

ifneq?(,$(findstring?Darwin,$(UNAME)))

??HOST_OS?:=?darwin

endif

ifneq?(,$(findstring?Macintosh,$(UNAME)))

??HOST_OS?:=?darwin

endif

ifneq?(,$(findstring?CYGWIN,$(UNAME)))

??HOST_OS?:=?windows

endif

?

#?BUILD_OS?is?the?real?host?doing?the?build.

BUILD_OS?:=?$(HOST_OS)

?

#?Under?Linux,?if?USE_MINGW?is?set,?we?change?HOST_OS?to?Windows?to?build?the

#?Windows?SDK.?Only?a?subset?of?tools?and?SDK?will?manage?to?build?properly.

ifeq?($(HOST_OS),linux)

ifneq?($(USE_MINGW),)

??HOST_OS?:=?windows

endif

endif

?

ifeq?($(HOST_OS),)

$(error?Unable?to?determine?HOST_OS?from?uname?-sm:?$(UNAME)!)

endif

?

#?TODO:?Replace?BUILD_HOST_64bit?with?a?flag?that?forces?32-bit?build,

#?after?we?default?to?64-bit?host?build.

ifeq?(,$(BUILD_HOST_64bit))

#?Default?to?32-bit-by-default?multilib?host?build.

HOST_PREFER_32_BIT?:=?true

endif

?

#?HOST_ARCH

ifneq?(,$(findstring?x86_64,$(UNAME)))

??HOST_ARCH?:=?x86_64

??HOST_2ND_ARCH?:=?x86

??HOST_IS_64_BIT?:=?true

endif

?

ifeq?($(HOST_PREFER_32_BIT),true)

SDK_HOST_ARCH?:=?x86

else

SDK_HOST_ARCH?:=?$(HOST_ARCH)

endif

?

BUILD_ARCH?:=?$(HOST_ARCH)

BUILD_2ND_ARCH?:=?$(HOST_2ND_ARCH)

?

ifeq?($(HOST_ARCH),)

$(error?Unable?to?determine?HOST_ARCH?from?uname?-sm:?$(UNAME)!)

endif

?

#?the?host?build?defaults?to?release,?and?it?must?be?release?or?debug

ifeq?($(HOST_BUILD_TYPE),)

HOST_BUILD_TYPE?:=?release

endif

?

ifneq?($(HOST_BUILD_TYPE),release)

ifneq?($(HOST_BUILD_TYPE),debug)

$(error?HOST_BUILD_TYPE?must?be?either?release?or?debug,?not?‘$(HOST_BUILD_TYPE)‘)

endif

endif

?

#?We?don‘t?want?to?move?all?the?prebuilt?host?tools?to?a?$(HOST_OS)-x86_64?dir.

HOST_PREBUILT_ARCH?:=?x86

#?This?is?the?standard?way?to?name?a?directory?containing?prebuilt?host

#?objects.?E.g.,?prebuilt/$(HOST_PREBUILT_TAG)/cc

ifeq?($(HOST_OS),windows)

??HOST_PREBUILT_TAG?:=?windows

else

??HOST_PREBUILT_TAG?:=?$(HOST_OS)-$(HOST_PREBUILT_ARCH)

endif

?

?

3.4、设置输出目录名称

TARGET_COPY_OUT_SYSTEM?:=?system

TARGET_COPY_OUT_DATA?:=?data

TARGET_COPY_OUT_OEM?:=?oem

TARGET_COPY_OUT_ROOT?:=?root

TARGET_COPY_OUT_RECOVERY?:=?recovery

?

3.5、加载product_config.mk脚本

include?$(BUILD_SYSTEM)/product_config.mk

?

3.6、根据TARGET_DEVICE的值寻找BoardConfig.mk脚本并加载

board_config_mk?:=?\

$(strip?$(wildcard?\

$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk?\

$(shell?test?-d?device?&&?find?device?-maxdepth?4?-path?‘*/$(TARGET_DEVICE)/BoardConfig.mk‘)?\

$(shell?test?-d?vendor?&&?find?vendor?-maxdepth?4?-path?‘*/$(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)

?

3.7、根据系统环境设置输出目录的路径

TARGET_OS?:=?linux

#?TARGET_ARCH?should?be?set?by?BoardConfig.mk?and?will?be?checked?later

ifneq?($(filter?%64,$(TARGET_ARCH)),)

TARGET_IS_64_BIT?:=?true

endif

?

#?the?target?build?type?defaults?to?release

ifneq?($(TARGET_BUILD_TYPE),debug)

TARGET_BUILD_TYPE?:=?release

endif

?

#?---------------------------------------------------------------

#?figure?out?the?output?directories

?

ifeq?(,$(strip?$(OUT_DIR)))

ifeq?(,$(strip?$(OUT_DIR_COMMON_BASE)))

OUT_DIR?:=?$(TOPDIR)out

else

OUT_DIR?:=?$(OUT_DIR_COMMON_BASE)/$(notdir?$(PWD))

endif

endif

?

DEBUG_OUT_DIR?:=?$(OUT_DIR)/debug

?

#?Move?the?host?or?target?under?the?debug/?directory

#?if?necessary.

TARGET_OUT_ROOT_release?:=?$(OUT_DIR)/target

TARGET_OUT_ROOT_debug?:=?$(DEBUG_OUT_DIR)/target

TARGET_OUT_ROOT?:=?$(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))

?

HOST_OUT_ROOT_release?:=?$(OUT_DIR)/host

HOST_OUT_ROOT_debug?:=?$(DEBUG_OUT_DIR)/host

HOST_OUT_ROOT?:=?$(HOST_OUT_ROOT_$(HOST_BUILD_TYPE))

?

<!--[if !supportLists]-->4、<!--[endif]-->product_config.mk分析

4.1、定义函数find-copy-subdir-files,执行shell命令查找子目录下指定文件用于PRODUCT_COPY_FILESPRODUCT_SDK_ADDON_COPY_FILES

###########################################################

##?List?all?of?the?files?in?a?subdirectory?in?a?format

##?suitable?for?PRODUCT_COPY_FILES?and

##?PRODUCT_SDK_ADDON_COPY_FILES

##

##?$(1):?Glob?to?match?file?name

##?$(2):?Source?directory

##?$(3):?Target?base?directory

###########################################################

?

define?find-copy-subdir-files

$(shell?find?$(2)?-name?"$(1)"?|?$(SED_EXTENDED)?"s:($(2)/?(.*)):\\1\\:$(3)/\\2:"?|?sed?"s://:/:g")

endef

?

4.2、确定TARGET_BUILD_VARIANTTARGET_PRODUCT的值

#?These?are?the?valid?values?of?TARGET_BUILD_VARIANT.??Also,?if?anything?else?is?passed

#?as?the?variant?in?the?PRODUCT-$TARGET_BUILD_PRODUCT-$TARGET_BUILD_VARIANT?form,

#?it?will?be?treated?as?a?goal,?and?the?eng?variant?will?be?used.

INTERNAL_VALID_VARIANTS?:=?user?userdebug?eng

?

#?---------------------------------------------------------------

#?Provide?"PRODUCT-<prodname>-<goal>"?targets,?which?lets?you?build

#?a?particular?configuration?without?needing?to?set?up?the?environment.

#

product_goals?:=?$(strip?$(filter?PRODUCT-%,$(MAKECMDGOALS)))

ifdef?product_goals

??#?Scrape?the?product?and?build?names?out?of?the?goal,

??#?which?should?be?of?the?form?PRODUCT-<productname>-<buildname>.

??#

??ifneq?($(words?$(product_goals)),1)

????$(error?Only?one?PRODUCT-*?goal?may?be?specified;?saw?"$(product_goals)")

??endif

??goal_name?:=?$(product_goals)

??product_goals?:=?$(patsubst?PRODUCT-%,%,$(product_goals))

??product_goals?:=?$(subst?-,?,$(product_goals))

??ifneq?($(words?$(product_goals)),2)

????$(error?Bad?PRODUCT-*?goal?"$(goal_name)")

??endif

?

??#?The?product?they?want

??TARGET_PRODUCT?:=?$(word?1,$(product_goals))

?

??#?The?variant?they?want

??TARGET_BUILD_VARIANT?:=?$(word?2,$(product_goals))

??ifeq?($(TARGET_BUILD_VARIANT),tests)

????$(error?"tests"?has?been?deprecated?as?a?build?variant.?Use?it?as?a?build?goal?instead.)

??endif

?

??#?The?build?server?wants?to?do?make?PRODUCT-dream-installclean

??#?which?really?means?TARGET_PRODUCT=dream?make?installclean.

??ifneq?($(filter-out?$(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)

????MAKECMDGOALS?:=?$(MAKECMDGOALS)?$(TARGET_BUILD_VARIANT)

????TARGET_BUILD_VARIANT?:=?eng

????default_goal_substitution?:=

??else

????default_goal_substitution?:=?$(DEFAULT_GOAL)

??endif

?

4.3、加载一些其他的mk脚本

include?$(BUILD_SYSTEM)/node_fns.mk

include?$(BUILD_SYSTEM)/product.mk

include?$(BUILD_SYSTEM)/device.mk

?

4.4、搜索所有的AndroidProducts.mk文件,找到当前产品的配置文件

ifneq?($(strip?$(TARGET_BUILD_APPS)),)

#?An?unbundled?app?build?needs?only?the?core?product?makefiles.

all_product_configs?:=?$(call?get-product-makefiles,\

????$(SRC_TARGET_DIR)/product/AndroidProducts.mk)

else

#?Read?in?all?of?the?product?definitions?specified?by?the?AndroidProducts.mk

#?files?in?the?tree.

all_product_configs?:=?$(get-all-product-makefiles)

endif

?

#?Find?the?product?config?makefile?for?the?current?product.

#?all_product_configs?consists?items?like:

#?<product_name>:<path_to_the_product_makefile>

#?or?just?<path_to_the_product_makefile>?in?case?the?product?name?is?the

#?same?as?the?base?filename?of?the?product?config?makefile.

current_product_makefile?:=

all_product_makefiles?:=

$(foreach?f,?$(all_product_configs),\

????$(eval?_cpm_words?:=?$(subst?:,$(space),$(f)))\

????$(eval?_cpm_word1?:=?$(word?1,$(_cpm_words)))\

????$(eval?_cpm_word2?:=?$(word?2,$(_cpm_words)))\

????$(if?$(_cpm_word2),\

????????$(eval?all_product_makefiles?+=?$(_cpm_word2))\

????????$(if?$(filter?$(TARGET_PRODUCT),$(_cpm_word1)),\

????????????$(eval?current_product_makefile?+=?$(_cpm_word2)),),\

????????$(eval?all_product_makefiles?+=?$(f))\

????????$(if?$(filter?$(TARGET_PRODUCT),$(basename?$(notdir?$(f)))),\

????????????$(eval?current_product_makefile?+=?$(f)),)))

_cpm_words?:=

_cpm_word1?:=

_cpm_word2?:=

current_product_makefile?:=?$(strip?$(current_product_makefile))

all_product_makefiles?:=?$(strip?$(all_product_makefiles))

?

4.5、调用clear-var-list函数去清除一些变量,并设置产品的运行时态product_runtimes

$(call?clear-var-list,?$(_product_var_list))

?

#?Set?PRODUCT_RUNTIMES,?allowing?buildspec?to?override?using?OVERRIDE_RUNTIMES

product_runtimes?:=?$(sort?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RUNTIMES))

ifneq?($(OVERRIDE_RUNTIMES),)

??$(info?Overriding?PRODUCT_RUNTIMES=$(product_runtimes)?with?$(OVERRIDE_RUNTIMES))

??product_runtimes?:=?$(OVERRIDE_RUNTIMES)

endif

$(foreach?runtime,?$(product_runtimes),?$(eval?include?$(SRC_TARGET_DIR)/product/$(runtime).mk))

$(foreach?v,?$(_product_var_list),?$(if?$($(v)),\

????$(eval?PRODUCTS.$(INTERNAL_PRODUCT).$(v)?+=?$(sort?$($(v))))))

?

$(call?clear-var-list,?$(_product_var_list))

#?Now?we?can?assign?to?PRODUCT_RUNTIMES

PRODUCT_RUNTIMES?:=?$(product_runtimes)

product_runtimes?:=

?

PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES?+=?persist.sys.dalvik.vm.lib.2=$(DALVIK_VM_LIB)

?

ifeq?($(words?$(PRODUCT_RUNTIMES)),1)

??#?If?we?only?have?one?runtime,?we?can?strip?classes.dex?by?default?during?dex_preopt

??DEX_PREOPT_DEFAULT?:=?true

else

??#?If?we?have?more?than?one,?we?leave?the?classes.dex?alone?for?post-boot?analysis

??DEX_PREOPT_DEFAULT?:=?nostripping

endif

?

4.6、获取BOOTCLASSPATH中的所有jar文件

#?A?list?of?module?names?of?BOOTCLASSPATH?(jar?files)

PRODUCT_BOOT_JARS?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BOOT_JARS))

PRODUCT_SYSTEM_SERVER_JARS?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_JARS))

?

?

?

?

4.7、设置TARGET_DEVICEPRODUCT_LOCALES的值

#?Find?the?device?that?this?product?maps?to.

TARGET_DEVICE?:=?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)

?

#?Figure?out?which?resoure?configuration?options?to?use?for?this

#?product.

PRODUCT_LOCALES?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOCALES))

#?TODO:?also?keep?track?of?things?like?"port",?"land"?in?product?files.

?

#?If?CUSTOM_LOCALES?contains?any?locales?not?already?included

#?in?PRODUCT_LOCALES,?add?them?to?PRODUCT_LOCALES.

extra_locales?:=?$(filter-out?$(PRODUCT_LOCALES),$(CUSTOM_LOCALES))

ifneq?(,$(extra_locales))

??ifneq?($(CALLED_FROM_SETUP),true)

????#?Don‘t?spam?stdout,?because?envsetup.sh?may?be?scraping?values?from?it.

????$(info?Adding?CUSTOM_LOCALES?[$(extra_locales)]?to?PRODUCT_LOCALES?[$(PRODUCT_LOCALES)])

??endif

??PRODUCT_LOCALES?+=?$(extra_locales)

??extra_locales?:=

endif

?

4.8、配置aapt的相关属性

#?Add?PRODUCT_LOCALES?to?PRODUCT_AAPT_CONFIG

PRODUCT_AAPT_CONFIG?:=?$(strip?$(PRODUCT_LOCALES)?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_CONFIG))

PRODUCT_AAPT_PREF_CONFIG?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREF_CONFIG))

PRODUCT_AAPT_PREBUILT_DPI?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREBUILT_DPI))

?

#?Keep?a?copy?of?the?space-separated?config

PRODUCT_AAPT_CONFIG_SP?:=?$(PRODUCT_AAPT_CONFIG)

?

#?Convert?spaces?to?commas.

PRODUCT_AAPT_CONFIG?:=?\

????$(subst?$(space),$(comma),$(strip?$(PRODUCT_AAPT_CONFIG)))

?

#?product-scoped?aapt?flags

PRODUCT_AAPT_FLAGS?:=

ifneq?($(filter?en_XA?ar_XB,$(PRODUCT_LOCALES)),)

#?Force?generating?resources?for?pseudo-locales.

PRODUCT_AAPT_FLAGS?+=?--pseudo-localize

endif

4.9、设置一些变量的值

PRODUCT_BRAND?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))

?

PRODUCT_MODEL?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))

ifndef?PRODUCT_MODEL

??PRODUCT_MODEL?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))

endif

?

PRODUCT_MANUFACTURER?:=?\

????$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))

ifndef?PRODUCT_MANUFACTURER

??PRODUCT_MANUFACTURER?:=?unknown

endif

?

ifeq?($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS),)

??TARGET_AAPT_CHARACTERISTICS?:=?default

else

??TARGET_AAPT_CHARACTERISTICS?:=?$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS))

endif

?

PRODUCT_DEFAULT_WIFI_CHANNELS?:=?\

????$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))

?

PRODUCT_DEFAULT_DEV_CERTIFICATE?:=?\

????$(strip?$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_DEV_CERTIFICATE))

ifdef?PRODUCT_DEFAULT_DEV_CERTIFICATE

ifneq?(1,$(words?$(PRODUCT_DEFAULT_DEV_CERTIFICATE)))

????$(error?PRODUCT_DEFAULT_DEV_CERTIFICATE=‘$(PRODUCT_DEFAULT_DEV_CERTIFICATE)‘,?\

??????only?1?certificate?is?allowed.)

endif

endif

?

<!--[if !supportLists]-->5、<!--[endif]-->definitions.mk分析

这个脚本主要是定义了很多函数,相当于一个函数库用于编译所需

define?print-vars

$(foreach?var,$(1),?\

??$(info?$(var):)?\

??$(foreach?word,$($(var)),?\

????$(info?$(space)$(space)$(word))?\

???)?\

?)

endef

?

define?true-or-empty

$(filter?true,?$(1))

endef

?

define?my-dir

$(strip?\

??$(eval?LOCAL_MODULE_MAKEFILE?:=?$$(lastword?$$(MAKEFILE_LIST)))?\

??$(if?$(filter?$(BUILD_SYSTEM)/%?$(OUT_DIR)/%,$(LOCAL_MODULE_MAKEFILE)),?\

????$(error?my-dir?must?be?called?before?including?any?other?makefile.)?\

???,?\

????$(patsubst?%/,%,$(dir?$(LOCAL_MODULE_MAKEFILE)))?\

???)?\

?)

endef

?

五、Android.mk分析

Android.mk是用来向编译系统描述你的源代码,也就是告诉编译系统你的源代码需要编译成什么样。你可以在一个Android.mk文件中定义一个或者多个模块,模块的类型包括:

???1)APK程序,一般的Android程序,编译打包生成apk文件
???2)Java库,java类库,编译打包生成jar文件
???3)??C\C++应用程序,可执行的C\C++应用程序
???4)C\C++静态库,编译生成C\C++静态库,并打包成.a文件
???5)C\C++共享库,?编译生成共享库(动态链接库),并打包成.so文件,有且只有共享库才能被安装/复制到您的应用软件(APK)包中。

下面是一个Android.mk的例子:

LOCAL_PATH?:=?$(call?my-dir)

include?$(CLEAR_VARS)

LOCAL_MODULE????????:=?settings_talpa

LOCAL_MODULE_TAGS???:=?optional

LOCAL_MODULE_CLASS??:=?APPS

LOCAL_MODULE_SUFFIX?:=?.apk

LOCAL_SRC_FILES?????:=?Settings.apk

LOCAL_MODULE_PATH???:=?$(TARGET_OUT_APPS_PRIVILEGED)

LOCAL_CERTIFICATE???:=?platform

LOCAL_OVERRIDES_PACKAGES?:=?Settings

include?$(BUILD_PREBUILT)

接下来根据这个例子来解释每一行代码

<!--[if !supportLists]-->1、<!--[endif]-->LOCAL_PATH?:=?$(call?my-dir)

每个Android.mk必须定义LOCAL_PATH这个变量,它用于在开发树中查找源文件。my-dir是一个函数名,由编译系统提供,用于返回当前Android.mk的目录路径。$(call?my-dir)表示的就是去调用my-dir这个函数

?

2、include?$(CLEAR_VARS)

CLEAR_VARS是由编译系统提供的变量,config.mk文件中能找到其定义,前面也提到过,它的值是$(BUILD_SYSTEM)/clear_vars.mk,这句代码表示去加载并执行这个mk脚本,清理掉local_xxx这样的一些变量。

?

<!--[if !supportLists]-->3、<!--[endif]-->LOCAL_MODULE????????:=?settings_talpa

LOCAL_MODULE也是必须定义的变量,表示模块的名字,这个名字必须唯一且不包含空格。编译系统会自动添加适当的前缀和后缀。

?

4、LOCAL_MODULE_TAGS???:=?optional

LOCAL_MODULE_TAGS表示当前模块在哪种模式下编译,模式包含user?eng?tests?optional

user:?指该模块只在user版本下才编译

eng:?指该模块只在eng版本下才编译

tests:?指该模块只在tests版本下才编译

optional:指该模块在所有版本下都编译

?

5、LOCAL_MODULE_CLASS??:=?APPS

LOCAL_MODULE_CLASS?指定模块的文件类型,apk文件用APPS,?并且?会检查?是否是apk文件,动态库so文件用SHARED_LIBRARIES?,bin文件用EXECUTABLES,其他文件?用ETC

?

6、LOCAL_MODULE_SUFFIX?:=?.apk

LOCAL_MODULE_SUFFIX指定模块的后缀

?

<!--[if !supportLists]-->7、<!--[endif]-->LOCAL_SRC_FILES

LOCAL_SRC_FILES指定需要打包进模块的文件

?

<!--[if !supportLists]-->8、<!--[endif]-->LOCAL_MODULE_PATH

LOCAL_MODULE_PATH指定模块的安装路径

$(TARGET_OUT_APPS_PRIVILEGED):system/priv-app/

$(TARGET_OUT_APPS):system/app/

?

9、LOCAL_CERTIFICATE???:=?platform

LOCAL_CERTIFICATE指定模块的签名key值,包含media、shared、platform、PRESIGNED(表示已经签过名,不需要签名)

?

<!--[if !supportLists]-->10、<!--[endif]-->LOCAL_OVERRIDES_PACKAGES?:=?Settings

LOCAL_OVERRIDES_PACKAGES表示当前模块需要覆盖系统原有的哪个模块名

?

11、include?$(BUILD_PREBUILT)

这句代码同样也是加载其他的脚本

BUILD_PACKAGE:指向build/core/package.mk,用来编译APK文件。

?????BUILD_JAVA_LIBRARY:指向build/core/java_library.mk,用来编译Java库文件。

???????BUILD_STATIC_JAVA_LIBRARY:指向build/core/tatic_java_library.mk,用来编译Java静态库文件。

???????BUILD_STATIC_LIBRARY:指向build/core/static_library.mk,用来编译静态库文件。也就是.a文件。

???????BUILD_EXECUTABLE:指向build/core/executable.mk,用来编译可执行文件。

???????BUILD_PREBUILT:指向build/core/prebuilt.mk。用来编译已经预编译好的第三方库文件,实际上是将这些预编译好的第三方库文件拷贝到合适的位置去,以便可以让其它模块引用。

?

?

?

?

?

?

?

?

六、Android源码各级目录分析

我们知道Android平台分为四层架构,分别是应用程序层、应用框架层、运行库层和Linux内核层,这四层架构和Android源码目录的对应关系如下:

<!--[if !supportLists]-->1、<!--[endif]-->应用程序层对应的是packages/apps

<!--[if !supportLists]-->2、<!--[endif]-->应用框架层对应的是frameworks

<!--[if !supportLists]-->3、<!--[endif]-->运行库层对应的是libcore、dalvik

<!--[if !supportLists]-->4、<!--[endif]-->Linux内核层对应的是kernel

下面详细介绍Android源码的目录结构:

Bionic:包含一些C语言库,比如内核层的一些头文件、时区的相关代码等等

Bootable:启动引导的相关代码,包含bootloader、ota、recovery等等

Build:存放系统编译规则以及编译所需的基础包和相关工具

Cts:Android兼容性测试套件标准

Dalvik:dalvik虚拟机的相关代码

Development:应用程序开发所需的一些例子源码和相关工具

External:Android的一些开源模块,比如加密、xml解析、压缩、数据库等等

Frameworks:Android的核心框架(Java和C++语言),比如WiFi、蓝牙、通讯等等

Hardware:部分厂家开源的硬解适配层HAL代码

Packages:Android应用程序包,比如浏览器、计算器、相机、多媒体应用等等

Prebuilt:x86和arm架构下预编译的一些资源

Sdk:Android的SDK和模拟器

System:底层文件系统库、应用及组件

Vendor:厂商定制代码

Kernel:Linux内核相关代码和脚本

Out:系统编译输出目录,包含相关基础包以及相关镜像文件

Device:产品的相关描述文件(与编译系统有关)

?

Android编译系统过程研究

原文:http://yaolinnan.iteye.com/blog/2299491

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!