zoukankan      html  css  js  c++  java
  • [转]Android Make脚本简记

    [转]Android Make脚本简记

    原文地址:

    http://blogold.chinaunix.net/u/8866/showart_2389799.html

    原文作者:

    Email:    zcatt@163.com
    Blog    http://zcatt.cublog.cn

    一、

    1、Build Layers
    Build Layers描述的是产品的硬件配置情况,据此make时选择不同的配置和模块。按照从上到下的顺序,Build Layer分成4层。
    Layer    sample    Note
    Arch    arm, x86    处理器的种类
    Board    -    板子类型的代号
    Device    -    device配置的类型代号
    Product    -    具体产品的代号

    2、添加应用
    2.1、一个例子
    以calculator为例,app代码可以放到packages/apps/目录下边,一个app对应一个目录,此例,pakcages/apps/Calculator/,创建Android.mk,已去除多余的注释行。

    Java代码  收藏代码
    1. LOCAL_PATH := $(call my-dir)  
    2. include $(CLEAR_VARS)  
    3. LOCAL_MODULE_TAGS := optional  
    4. LOCAL_STATIC_JAVA_LIBRARIES := libarity  
    5. LOCAL_SRC_FILES := $(call all-java-files-under, src)  
    6. LOCAL_SDK_VERSION := current  
    7. LOCAL_PACKAGE_NAME := Calculator  
    8. include $(BUILD_PACKAGE)  
    9. include $(CLEAR_VARS)  
    10. LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libarity:arity-2.1.2.jar  
    11. include $(BUILD_MULTI_PREBUILT)  
    12. # Use the folloing include to make our test apk.  
    13. include $(call all-makefiles-under,$(LOCAL_PATH))  

    Android.mk中需要赋值的几个LOCAL_XXX变量,
    LOCAL_PATH,调用my-dir(在defination.mk中定义),得到当前路径,即,<yourSrcPath>/ pakcages/apps/Calculator/;
    LOCAL_MODULE_TAGS,取值范围debug eng tests optional samples shell_ash shell_mksh,注意不能取值user,如果要预装,则应定义core.mk;
    LOCAL_SRC_FILES,app的所有源码,可以调用all-java-files-under得到,如果是java源码的话;
    LOCAL_PACKAGE_NAME,package的名字,这个名字在脚本中将标识这个app或package;
    $(CLEAR_VARS)指的是clear_vars.mk,脚本会清空所有LOCAL_xxx的变量,不影响后面这些变量的使用;
    $(BUILD_PACKAGE)指的是package.mk

    而,最后一句all-makefiles-under将会包含当前目录下所有的.mk脚本文件。

    2.2、LOCAL_XXX的列表
    LOCAL_PATH,当前路径,必须定义;
    LOCAL_PACKAGE_NAME,必须定义,package的名字,这个名字在脚本中将标识app或package;
    LOCAL_MODULE_SUFFIX,不用定义,module的后缀,=.apk。
    LOCAL_MODULE,不用定义,=$(LOCAL_PACKAGE_NAME)。
    LOCAL_JAVA_RESOURCE_DIRS,不用定义。
    LOCAL_JAVA_RESOURCE_FILES,不用定义。
    LOCAL_MODULE_CLASS,不用定义。
    LOCAL_MODULE_TAGS,可选定义。默认optional。取值范围user debug eng tests optional samples shell_ash shell_mksh
    LOCAL_ASSET_DIR,可选定义,推荐不定义。默认$(LOCAL_PATH)/assets
    LOCAL_RESOURCE_DIR,可选定义,推荐不定义。默认product package和device package相应的res路径和$(LOCAL_PATH)/res。
    LOCAL_PROGUARD_ENABLED,可选定义,默认为full,如果是user或userdebug。取值full, disabled, custom。
    full_android_manifest,不用定义,=$(LOCAL_PATH)/AndroidManifest.xml。
    LOCAL_EXPORT_PACKAGE_RESOURCES,可选定义,默认null。如果允许app的资源被其它模块使用,则设置true。
    LOCAL_CERTIFICATE,可选定义,默认为testkey。最终是:private_key := $(LOCAL_CERTIFICATE).pk8 和 certificate := $(LOCAL_CERTIFICATE).x509.pem;

    2.3、mm创建apk时的package.mk中变量分析
    以Calculator为例,
    由LOCAL_PATH,LOCAL_PACKAGE_NAME导出变量LOCAL_MODULE,all_assets,all_assets,all_resources。
    设置LOCAL_MODULE_CLASS=APPS,此值local-intermediates-dir会用到。
    设置中间生成目录路径,中间路径将放置R.stamp文件。
    package_expected_intermediates_COMMON := $(call local-intermediates-dir,COMMON)
    这里COMMON是null,而LOCAL_MODULE_CLASS=APPS,所以
    package_expected_intermediates_COMMON=out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates

    package_expected_intermediates_COMMON=out/target/common/obj/APPS/Calculator_intermediates
    设置
    LOCAL_BUILT_MODULE_STEM := package.apk

    LOCAL_BUILT_MODULE := $(built_module_path)/$(LOCAL_BUILT_MODULE_STEM)    @base_rules.mk
    built_module_path := $(intermediates)        @base_rules.mk
    intermediates := $(call local-intermediates-dir)    @java.mk
    最终
    LOCAL_BUILT_MODULE=out/target/product/<PRODUCT>/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/$(LOCAL_BUILT_MODULE_STEM)

    LOCAL_BUILT_MODULE=out/target/product/generic/obj/APPS/Calculator_intermediates/package.apk

    由LOCAL_CERTIFICATE导出
    private_key := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE).pk8
    certificate := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE).x509.pem
    LOCAL_CERTIFICATE默认为testkey。

    2.4、package.mk中定义的几个PACKAGE.xxx变量
    PACKAGES.$(LOCAL_PACKAGE_NAME).PRIVATE_KEY := $(private_key)
    PACKAGES.$(LOCAL_PACKAGE_NAME).CERTIFICATE := $(certificate)
    PACKAGES.$(LOCAL_PACKAGE_NAME).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
    PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources)

    PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME)
    全编译时,PACKAGES变量将会记录遍历到的packages。

    二、

    1、java.mk分析

    选取APPS场景,以Calculator为例说明。
    LOCAL_JAVA_LIBRARIES=true时,Android.mk中不能定义LOCAL_SDK_VERSION。
    当LOCAL_SDK_VERSION=current时,LOCAL_JAVA_LIBRARIES=android_stubs_current。

    package.mk中定义LOCAL_BUILT_MODULE_STEM=package.apk。
    两个中间目录的路径,即对应的obj目录下APPS/<LOCAL_MODULE>_intermediates/。
    intermediates=out/target/product/generic/obj/APPS/Calculator_intermediates
    intermediates.COMMON=out/target/common/obj/APPS/Calculator_intermediates

    LOCAL_INTERMEDIATE_TARGETS先前package.mk中已经定义了R.stamp,java.mk有增添了7个。
    LOCAL_INTERMEDIATE_TARGETS += \
        $(full_classes_jar) \
        $(full_classes_compiled_jar) \
        $(full_classes_emma_jar) \
        $(full_classes_full_names_jar) \
        $(full_classes_stubs_jar) \
        $(full_classes_jarjar_jar) \
        $(built_dex)
    此例中,具体值是
    LOCAL_INTERMEDIATE_TARGETS=
        out/target/common/obj/APPS/Calculator_intermediates/src/R.stamp            @defined in package.mk
        out/target/common/obj/APPS/Calculator_intermediates/classes.jar            @full_classes_jar
        out/target/common/obj/APPS/Calculator_intermediates/classes-full-debug.jar        @full_classes_compiled_jar
        out/target/common/obj/APPS/Calculator_intermediates/emma_out/lib/classes-full-debug.jar    @full_classes_emma_jar
        out/target/common/obj/APPS/Calculator_intermediates/classes-full-names.jar @full_classes_full_names_jar
        out/target/common/obj/APPS/Calculator_intermediates/stubs.jar @full_classes_stubs_jar
        out/target/common/obj/APPS/Calculator_intermediates/classes-jarjar.jar    @full_classes_jarjar_jar
        out/target/common/obj/APPS/Calculator_intermediates/classes.dex    @built_dex

    java.mk随后include base_rules.mk

    后面处理了EMMA,PROGUARD在enable/disable情况下的动作

    最后定义的target, $(LOCAL_MODULE)-findbugs因为prebuilt/common下还没有findbugs,目前不可用。

    java.mk还定义了几个特别的变量,
    ALL_MODULES.$(LOCAL_MODULE).PROGUARD_ENABLED:=$(LOCAL_PROGUARD_ENABLED)
    ALL_MODULES.$(LOCAL_MODULE).CHECKED := $(full_classes_compiled_jar)
    ALL_MODULES.$(LOCAL_MODULE).STUBS := $(full_classes_stubs_jar)

    2、base_rules.mk的分析
    续1(Java.mk)的场景。
    提取变量my_prefix:=TARGET_
    LOCAL_MODULE_TAGS在Android.mk或package.mk中已经设定,默认是optional。
    确认LOCAL_MODULE_PATH,默认$($(my_prefix)OUT$(use_data)_$(LOCAL_MODULE_CLASS)),此例中是out/target/product/generic/system/app
    设定module_id := MODULE.$(TARGET).$(LOCAL_MODULE_CLASS).$(LOCAL_MODULE),此例MODULE.TARGET.APPS.Calculator。
    设定中间目录路径intermediates,intermediates.COMMON,参见1.

    设定LOCAL_MODULE_STEM=$(LOCAL_MODULE),此例,Calculator。LOCAL_INSTALLED_MODULE_STEM=Calculator.apk。

    LOCAL_INTERMEDIATE_TARGETS追加上package.apk,参见1.

    处理aidl,转为java,放在intermediates.COMMON下的目录中。

    处理logtag,转为java,放在intermediates.COMMON下的目录中。

    确定java_sources,这包括android.mk中包含的,aidl和logtag生成的。

    处理java_resource_files

    处理了java lib相关

    定义clean-$(LOCAL_MODULE) target, 可以删除app/package的生成文件,包括$(PRIVATE_CLEAN_FILES),$(LOCAL_BUILT_MODULE),$(LOCAL_INSTALLED_MODULE),$(intermediates),$(intermediates.COMMON)


    还定义了$(LOCAL_MODULE) target, 几个变量的值
    LOCAL_MODULE=Calculator
    LOCAL_BUILT_MODULE=out/target/product/generic/obj/APPS/Calculator_intermediates/package.apk
    LOCAL_INSTALLED_MODULE=out/target/product/generic/system/app/Calculator.apk

    最后定义了几个ALL_MODULES变量。
    ALL_MODULES.$(LOCAL_MODULE).CLASS
    ALL_MODULES.$(LOCAL_MODULE).PATH
    ALL_MODULES.$(LOCAL_MODULE).TAGS
    ALL_MODULES.$(LOCAL_MODULE).CHECKED
    ALL_MODULES.$(LOCAL_MODULE).BUILT
    ALL_MODULES.$(LOCAL_MODULE).INSTALLED
    ALL_MODULES.$(LOCAL_MODULE).REQUIRED
    ALL_MODULES.$(LOCAL_MODULE).EVENT_LOG_TAGS

    3、multi_prebuilt.mk的分析

    续1的场景。
    mulit_prebuilt.mk顾名思义就是多次调用prebuilt.mk,对几种明确的prebuilt library完成需要的copy操作。

    multi_prebuilt.mk定义了命令auto-prebuilt-boilerplate。入口有6个参数
    # $(1): file list, "<modulename>:<filename>"
    # $(2): IS_HOST_MODULE
    # $(3): MODULE_CLASS
    # $(4): OVERRIDE_BUILT_MODULE_PATH
    # $(5): UNINSTALLABLE_MODULE
    # $(6): BUILT_MODULE_STEM
    根据这6个参数,命令确定
    LOCAL_IS_HOST_MODULE
    LOCAL_MODULE_CLASS
    OVERRIDE_BUILT_MODULE_PATH
    LOCAL_UNINSTALLABLE_MODULE
    LOCAL_MODULE
    LOCAL_SRC_FILES
    LOCAL_BUILT_MODULE_STEM
    LOCAL_MODULE_SUFFIX
    并调用prebuilt.mk

    multi_prebuilt.mk中分别对下面5中lib调用了auto-prebuilt-boilerplate。

    prebuilt_static_libs := $(filter %.a,$(LOCAL_PREBUILT_LIBS))
    prebuilt_shared_libs := $(filter-out %.a,$(LOCAL_PREBUILT_LIBS))
    prebuilt_executables := $(LOCAL_PREBUILT_EXECUTABLES)
    prebuilt_java_libraries := $(LOCAL_PREBUILT_JAVA_LIBRARIES)
    prebuilt_static_java_libraries := $(LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES)

    4、prebuilt.mk的分析

    续1的场景。

    首先,include base_rules.mk

    定义
    PACKAGES.$(LOCAL_MODULE).OVERRIDES

    第二步,如果是APPS类型,则zipalign,并拷贝到中间路径$(intermediates)。不是APPS,则不做zipalign。
    本例是JAVA_LIBRARY类型,目的路径out/target/common/obj/JAVA_LIBRARIES/libarity_intermediates/javalib.jar,注意其中的libarity和javalib.jar。


    最后检查 signed情况。

    三、

    1.findleaves.py的分析
    main.mk中调用了findleaves.py,得到所有子目录下Android.mk文件的路径。
    subdir_makefiles := \
        $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)
    $(subdirs)一般编译中取值$(TOP)。

    使用方法,
    Usage: %(progName)s [<options>] <dirlist> <filename>
    Options:
       --mindepth=<mindepth>
           Both behave in the same way as their find(1) equivalents.
       --prune=<dirname>
           Avoids returning results from inside any directory called <dirname>
           (e.g., "*/out/*"). May be used multiple times.

    程序首先依次选取dirlist中的目录,然后遍历所有子目录查找Android.mk文件,如果有,则加入到返回列表中。

    2. pathmap.mk的分析
    pathmap.mk中定义了一个列表pathmap_INCL,列表中每项是"短名:路径"对。命令include-path-for使用这个pathmap_INCL列表,输入短名,得到路径。你可以在这个列表中添加自己的对。使用$(call include-path-for, <短名>)就可以得到路径。
    另外,定义了FRAMEWORKS_BASE_JAVA_SRC_DIRS,含有frameworks/base目录下含java文件的所有目录。

    3. config.mk的分析
    首先,包含pathmap.mk, 其次,定义了一些变量,例如通用的编译参数,package的后缀名等。
    随后包含buildspec.mk。
    接着包含envsetup.mk。
    然后包含$(board_config_mk)。$(board_config_mk)是位于build/target/board/$(TARGET_DEVICE)/,device/*/$(TARGET_DEVICE)/,或vendor/*/$(TARGET_DEVICE)/目录下的BoardConfig.mk文件。

    -------TODO

    4. buildspec.mk的分析
    buildspec.mk是用户应当配置的脚本文件,模板可以使用buildspec.mk.default,放到$(TOP)下。
    在buildspec.mk中,用户应该配置好主要的参数,例如 TARGET_PRODUCT, TARGET_BUILD_VARIANT, CUSTOM_MODULES,  TARGET_SIMULATOR, TARGET_BUILD_TYPE, CUSTOM_LOCALES, 和BUILD_ENV_SEQUENCE_NUMBER等。
    如果不使用buildspec.mk配置参数,也可以使用环境变量的形式。若不配置参数,那么android会使用默认的参数。

    5. envsetup.mk的分析
    首先包含进version_defaults.mk,定义好一些版本相关的变量。参见version_defaults.mk。

    定义CORRECT_BUILD_ENV_SEQUENCE_NUMBER,这个数字用于buildspec.mk更新时的提醒,应该同buildspec.mk中的或环境变量中的BUILD_ENV_SEQUENCE_NUMBER相等。一般不用关注。

    随后检查TARGET_PRODUCT,若为空,则置generic。TARGET_PRODUCT应当在buildspec.mk或环境变量中已经定义好。

    再检查TARGET_BUILD_VARIANT,若为空,则置eng。TARGET_BUILD_VARIANT应当在buildspec.mk或环境变量中已经定义好。

    然后包含进product_config.mk。

    接着,检查$(TARGET_BUILD_VARIANT),取值范围是eng user userdebug tests。

    随后判定HOST_OS(linux),HOST_ARCH(x86)

    接着,确定TARGET_ARCH和TARGET_OS,若没有定义,则取默认值。
    TARGET_ARCH := arm
    TARGET_OS := linux

    接着,确定TARGET_BUILD_TYPE,若没有定义,则取默认值。
    TARGET_BUILD_TYPE := release

    接着,确定OUT_DIR。OUT_DIR是存放中间文件和最终结果的地方。若没有定义,则取默认值。
    OUT_DIR := $(TOPDIR)out

    随后,定义了一些列的路径变量
    DEBUG_OUT_DIR,TARGET_OUT_ROOT_release,TARGET_OUT_ROOT_debug,TARGET_OUT_ROOT,BUILD_OUT,PRODUCT_OUT,TARGET_COMMON_OUT_ROOT,等等。

    6、version_defaults.mk的分析
    version_defaults.mk是检查一些跟版本相关的变量是否定义,如果未定义,则使用默认值。这些变量包括
    PLATFORM_VERSION,默认AOSP
    PLATFORM_SDK_VERSION,默认8
    PLATFORM_VERSION_CODENAME,默认AOSP
    DEFAULT_APP_TARGET_SDK,默认AOSP
    BUILD_ID,默认UNKNOWN
    BUILD_NUMBER,默认eng.$(USER).$(shell date +%Y%m%d.%H%M%S)的形式。


    version_defaults.mk首先包含进build_id.mk。用户应当配置build_id.mk,而不应该改动version_defaults.mk文件。
    然后检查上述变量,如未定义则赋值默认值。

    7. build_id.mk的分析
    用户可以在build_id.mk中定义这样几个参数,
    PLATFORM_VERSION
    PLATFORM_SDK_VERSION
    PLATFORM_VERSION_CODENAME
    DEFAULT_APP_TARGET_SDK
    BUILD_ID
    BUILD_NUMBER
    这些参数最终将出现build.prop中。

    Froyo的build_id.mk中定义了2个变量,
    BUILD_ID,通常用于说明分支branch的,默认的是OPENMASTER,用户应该配置这个参数。
    DISPLAY_BUILD_NUMBER,在TARGET_BUILD_VARIANT=user的版本中,build.prop中是ro.build.id是显示成$(BUILD_ID).$(BUILD_NUMBER),还是显示成$(BUILD_ID)形式。设成true,则显示前者。


    8. product_config.mk的分析
    make PRODUCT-<prodname>-<goal>  <other>

    如果使用上述形式的make命令,那么将等同于

    TARGET_PRODUCT:=<prodname>
    TARGET_BUILD_VARIANT:=<goal>
    goal_name:=PRODUCT-<prodname>-<goal>
    MAKECMDGOALS:=droid <other>

    .PHONY: $(goal_name)
    $(goal_name): $(MAKECMDGOALS)
    endif

    注意,goal的取值范围是user userdebug eng tests,如果不属于上述范围,则将算入MAKECMDGOALS中,此时, TARGET_BUILD_VARIANT := eng。例如
    make PRODUCT-dream-installclean
    等同于
    TARGET_PRODUCT=dream make installclean

    使用make PRODUCT-<prodname>-<goal>这种形式,可以方便的指定TARGET_PRODUCT,和TARGET_BUILD_VARIANT。


    make APP-<appname>  <other>

    如果使用上述形式的make命令,那么将等同于
    TARGET_BUILD_APPS:=<appname>
    unbundled_goals:=APP-<appname>
    MAKECMDGOALS:=droid <other>

    .PHONY: $(unbundled_goals)
    $(unbundled_goals): $(MAKECMDGOALS)

    使用make APP-<appname>这种形式,可以方便的指定TARGET_BUILD_APPS。


    注意,PRODUCT-<prodname>-<goal>和APP-<appname>可以一块使用。

    处理完PRODUCT-<prodname>-<goal>和APP-<appname>,product_config.mk会包含下面3个文件
    node_fns.mk
    product.mk
    device.mk

    上面的3个mk文件定义了一些命令,用于搜寻product, device对应的目录,生成相应的PRODUCT.XXX,和DEVICE.XXX变量。

    接着,使用$(call import-products, $(get-all-product-makefiles))遍历Prodcut相关的AndroidProducts.mk文件,读入PRODCUTS.xxx变量。可以去掉文件中下面两句话的注释符,查看。
    #$(dump-products)
    #$(error done)

    随后,使用PRODCUT.xxx和TARGET_PRODUCT,得到INTERNAL_PRODUCT信息,即指定product的路径。

    再由INTERNAL_PRODUCT得到TARGET_DEVICE, PRODUCT_LOCALES, PRODUCT_BRAND, PRODUCT_MODEL, PRODUCT_MANUFACTURER, PRODUCT_DEFAULT_WIFI_CHANNELS, PRODUCT_POLICY, PRODUCT_COPY_FILES, PRODUCT_PROPERTY_OVERRIDES, PRODUCT_PACKAGE_OVERLAYS, DEVICE_PACKAGE_OVERLAYS, PRODUCT_TAGS, PRODUCT_OTA_PUBLIC_KEYS。
    由PRODUCT_LOCALES导出PRODUCT_AAPT_CONFIG。
    ADDITIONAL_BUILD_PROPERTIES中追加PRODUCT_PROPERTY_OVERRIDES中的值。
    上面所说的这些值,实际上都是在product的mk文件中定义。


    9. node_fns.mk的分析
    定义了一些命令。这些命令在product.mk,device.mk,和product_config.mk中会使用。这里重点说明import-nodes。

    import-nodes需要3个入口参数:
    $(1)是一个字串,是输出变量的主干名。例如”PRODUCTS"和”DEVICES“。
    $(2)是一个makefile文件列表,这些文件中应该含有对$(3)中变量的定义。
    $(3)是一个变量列表。

    import-nodes会创建这样形式的变量,以$(1)="PRODUCTS", $(2)中含有"build/target/product/core.mk", $(3)中含有"PRODUCT_NAME", 而且core.mk中定义了PRODUCT_NAME:=core为例,
    PRODUCT.build/target/product/core.mk.PRODUCT_NAME:=core

    import-nodes中还考虑了inherit的问题,如果某个PRODUCTS.XXX变量的值中有‘@inherit:<mk文件>’标识后面跟着mk文件名的字串,则会把那个mk文件中相应的变量的属性添加到PRODUCTS.XXX中。'@inherit:<mk文件>'是inherit-product命令添加的。参见product.mk。

    在product_config.mk中会说明$(2)中的mk文件列表是AndroidProducts.mk中的PRODUCT_MAKEFILES定义的。

    node_fns.mk的代码真的很杀伤脑细胞...


    10. product.mk的分析
    product.mk构造了一些命令,供product_config.mk中使用。

    _find-android-products-files这个命令会得到device/和vendor/, 包括子目录,以及build/target/product/下的AndroidProducts.mk文件列表。

    get-all-product-makefiles这个命令会得到所有$(_find-android-products-files)的AndroidProducts.mk文件中PRODUCT_MAKEFILES变量定义的mk文件。

    _product_var_list对应的是import-nodes命令的$(3), 定义了会生成那些PRODUCT属性名的变量。这些变量实际也是在product的mk文件中要考虑定义的。
    _product_var_list := \
        PRODUCT_NAME \
        PRODUCT_MODEL \
        PRODUCT_LOCALES \
        PRODUCT_PACKAGES \
        PRODUCT_DEVICE \
        PRODUCT_MANUFACTURER \
        PRODUCT_BRAND \
        PRODUCT_PROPERTY_OVERRIDES \
        PRODUCT_COPY_FILES \
        PRODUCT_OTA_PUBLIC_KEYS \
        PRODUCT_POLICY \
        PRODUCT_PACKAGE_OVERLAYS \
        DEVICE_PACKAGE_OVERLAYS \
        PRODUCT_CONTRIBUTORS_FILE \
        PRODUCT_TAGS \
        PRODUCT_SDK_ADDON_NAME \
        PRODUCT_SDK_ADDON_COPY_FILES \
        PRODUCT_SDK_ADDON_COPY_MODULES \
        PRODUCT_SDK_ADDON_DOC_MODULE \
        PRODUCT_DEFAULT_WIFI_CHANNELS

    import-products会调用import-nodes。product_config.mk中用到。
    define import-products
    $(call import-nodes,PRODUCTS,$(1),$(_product_var_list))
    endef

    inherit-product命令则将在所有的PRODUCT.xxx变量值中后缀上'@inherit:<mk文件>',当import-nodes处理时,会替换成继承的属性。

    check-all-products命令借助$(PRODUCTS)诸变量,会对product进行唯一性检查和PRODUCT_NAME,PRODUCT_BRAND,PRODCUT_COPY_FILES的简单检查。

    resolve-short-product-name命令,给定Product的短名,返回对应mk的路径。


    11. device.mk的分析
    同product.mk类似,device.mk构造了一些命令。有resolve-short-device-name,和import-devices。

    四、
    1. config.mk的分析
    首先,包含pathmap.mk, 其次,定义了一些变量,例如通用的编译参数,package的后缀名等。

    随后包含buildspec.mk。

    接着包含envsetup.mk。envsetup.mk中会遍历所有product相关的路径,载入所有支持的product的信息到变量集PRODUCT.<productMkPath>.<attribute>中,一个product对应一个<productMkPath>。最后根据TARGET_PRODUCT的值,定义各种跟product相关的变量,包括TARGET_DEVICE变量。

    然后包含$(board_config_mk)。$(board_config_mk)是位于build/target/board/$(TARGET_DEVICE)/,device/*/$(TARGET_DEVICE)/,或vendor/*/$(TARGET_DEVICE)/目录下的BoardConfig.mk文件。 $(TARGET_DEVICE)已经在product_config.mk中定义了。在包含$(board_config_mk)之前,会做检查,多个$(board_config_mk)存在则报错。

    定义TARGET_DEVICE_DIR,TARGET_BOOTLOADER_BOARD_NAME,TARGET_CPU_ABI等跟board相关的变量。

    接着,依次以HOST_和TARGET_条件包含select.mk。这里说明TARGET_的select.mk。先定义combo_os_arch,通常是linux-arm,然后定义各种跟编译链接相关的一些变量,最后再包含进build/core/combo/TARGET_linux-arm.mk。

    再包含javac.mk,定义javac的命令和通用参数。

    随后,定义一些变量,指向通用工具,其中一些是os提供的,例如YACC;一些是froyo编译生成,放在out/host/linux-x86/bin/下,一些是预定义的脚本和工具,例如MKTARBALL。

    最后定义了一些编译链接变量,这里专门列出,
    HOST_GLOBAL_CFLAGS += $(COMMON_GLOBAL_CFLAGS)
    HOST_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)

    HOST_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
    HOST_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)

    TARGET_GLOBAL_CFLAGS += $(COMMON_GLOBAL_CFLAGS)
    TARGET_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)

    TARGET_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
    TARGET_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)

    HOST_GLOBAL_LD_DIRS += -L$(HOST_OUT_INTERMEDIATE_LIBRARIES)
    TARGET_GLOBAL_LD_DIRS += -L$(TARGET_OUT_INTERMEDIATE_LIBRARIES)

    HOST_PROJECT_INCLUDES:= $(SRC_HEADERS) $(SRC_HOST_HEADERS) $(HOST_OUT_HEADERS)
    TARGET_PROJECT_INCLUDES:= $(SRC_HEADERS) $(TARGET_OUT_HEADERS)

    ifneq ($(TARGET_SIMULATOR),true)
    TARGET_GLOBAL_CFLAGS += $(TARGET_ERROR_FLAGS)
    TARGET_GLOBAL_CPPFLAGS += $(TARGET_ERROR_FLAGS)
    endif

    HOST_GLOBAL_CFLAGS += $(HOST_RELEASE_CFLAGS)
    HOST_GLOBAL_CPPFLAGS += $(HOST_RELEASE_CPPFLAGS)

    TARGET_GLOBAL_CFLAGS += $(TARGET_RELEASE_CFLAGS)
    TARGET_GLOBAL_CPPFLAGS += $(TARGET_RELEASE_CPPFLAGS)

    其中的TARGET_PROJECT_INCLUDES包含了SRC_HEADERS,添加头文件路径的话,可以改动SRC_HEADERS。

    最后包含进dumpvar.mk


    2. javac.mk的分析
    javac.mk中会定义javac的编译命令和通用参数。
    CUSTOM_JAVA_COMPILER做为javac.mk的入口参数,可以考虑openjdk,eclipse。不定义时则使用默认的javac。另外定义为openjdk时,因为prebuilt/对应目录下没有相应的工具,所以还不可用。
    依次一般忽略定义CUSTOM_JAVA_COMPILER,只要直接配置自己编译环境的path,指向使用的javac就可以了。

    javac在linux平台的定义是
    javac -J-Xmx512M -target 1.5 -Xmaxerrs 9999999

    -J-Xmx512M,传递给vm launcher参数-Xmx512M,告知起始空间设定为512M。
    -target 1.5,编译的结果适用1.5版本。
    -Xmaxerrs 9999999,最大输出的错误数是9999999。

    3. dumpvar.mk的分析
    dumpvar.mk支持两种target: dumpvar-<varName>,和dumpvar-abs-<varName>。envsetup.sh中的get_build_var和get_abs_build_var就使用了这些target。

    使用方法:假设位于$(TOPDIR)路径,

    CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make -f build/core/config.mk dumpvar-<varName>

    CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make -f build/core/config.mk dumpvar-abs-<varName>

    第一种形式,返回varName的值。第二种形式,返回varName的值,前缀上路径。考虑到android脚本中广泛使用':=’的变量定义方法,因此,基本上只能显示dumpvar.mk之前定义的变量值。LOCAL_xxxx的变量也不适用。

    4. cleanbuild.mk的分析
    main.mk在包含了config.mk后,会包含进cleanbuild.mk。

    定义了add-clean-step命令。有一个入口参数
    $(1),执行删除操作的具体shell命令。
    一般add-clean-step应当在%/cleanspec.mk脚本中使用,命令会为$(1)定义一个变量保存,变量的名字是INTERNAL_STEP.$(_acs_id),所有的$(_acs_id)保存在INTERNAL_STEPS中。$(_acs_id)的值分成3个部分构造
    第一部分是有cleanspec.mk的路径转化而来,用'_'替代'/','-'替代'.',后缀_acs。第二部分是$(INTERNAL_CLEAN_BUILD_VERSION),默认是4,第三部分是有'@'组成,cleanspec.mk中的第几个add-clean-step就用几个@。
    例如,packages/apps/Camera/cleanspec.mk中定义了两个删除动作
    $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/Camera*)
    $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Camera*)
    那么,对应的有
    INTERNAL_STEP.packages_apps_Camera_CleanSpec-mk_acs4@ := rm -rf $(PRODUCT_OUT)/obj/APPS/Camera*
    INTERNAL_STEP.packages_apps_Camera_CleanSpec-mk_acs4@@ := rm -rf $(OUT_DIR)/target/common/obj/APPS/Camera*

    接着,包扩进cleanspec.mk

    包含进$(PRODUCT_OUT)/clean_steps.mk,

    接下来,检查CURRENT_CLEAN_BUILD_VERSION是否与INTERNAL_CLEAN_BUILD_VERSION相同,默认是4
        如果相同,
            执行所有在INTERNAL_STEPS中登记的删除操作。
        否则,
            删除 $(OUT_DIR)

    然后,重新生成$(PRODUCT_OUT)/clean_steps.mk,写入"CURRENT_CLEAN_BUILD_VERSION := $(INTERNAL_CLEAN_BUILD_VERSION)"和"CURRENT_CLEAN_STEPS := $(INTERNAL_CLEAN_STEPS)"。

    随后,读入$(PRODUCT_OUT)/previous_build_config.mk,看是否与当前的编译选项一致,不一致则标明上次的中间文件不可用,则删除相应的中间目录,或提示用户。接着重新将当前的信息写入$(PRODUCT_OUT)/previous_build_config.mk,格式是,
    current_build_config := \
        $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)$(building_sdk)-{$(locale_list)}

     echo "PREVIOUS_BUILD_CONFIG := $(current_build_config)" > \
          $(previous_build_config_file)

    最后,定义了两个target, installclean和dataclean。
    dataclean删除的主要是./$(PRODUCT_OUT)/data/*,
    installclean的删除包括dataclean。installclean的本意是用于不同build_type编译时删除前次的中间文件。


    总结cleanbuild.mk的内容,就3件事,一是载入所有的CleanSpec.mk,二是检查更新clean_steps.mk和previous_build_config.mk,避免不同编译间的互相干扰。最后是,定义installclean和dataclean。


    5. cleanspec.mk的分析
    首先定义
    INTERNAL_CLEAN_BUILD_VERSION := 4

    接着使用findleaves.py遍历所有子目录,找到CleanSpec.mk,并包含进。用户可以在CleanSpec.mk中定义自己需要的删除操作。实际上还可以包含不仅仅是删除的操作。

    至此,INTERNAL_STEP.XXXX包含了所有CleanSpec.mk定义的clean动作。


    6. version_checked.mk的分析
    main.mk在cleanbuild.mk后,会借助$(OUT_DIR)/version_checked.mk检查版本,如果版本不一致,则重新检查系统文件系统大小写敏感问题,路径上是否含有空格,java和javac的版本,没有问题,则更新version_checked.mk。

    version_checked.mk中就定义了
    VERSIONS_CHECKED := $(VERSION_CHECK_SEQUENCE_NUMBER)

    7. showcommands和checkbuild的说明
    checkbuild貌似并未使用。
    showcommands必须同其它target一同使用,showcommands会详细打印出执行的具体命令内容。

    8. definations.mk的说明
    definations.mk中定义了大量的命令,其它的mk文件将使用。这其中包括执行编译链接的命令,通常是transform-XXX-to-XXX的形式,例如,transform-cpp-to-o。

    其中的inherit-package命令有待研究...

    五、
    1. Makefile的分析
    首先定义target, 用于生成$(OUT_DOCS)/index.html
    再定义target, 用于生成$(TARGET_ROOT_OUT)/default.prop
    再定义target, 用于生成$(TARGET_OUT)/build.prop。build.prop文件记录了一系列属性值。它的内容分成两部分,第一部分是一些关于product,device,build的一般性属性值,第二部分的属性值源自ADDITIONAL_BUILD_PROPERTIES。product配置mk文件中定义的PRODUCT_PROPERTY_OVERRIDES会加入到ADDITIONAL_BUILD_PROPERTIES,建议增加property时,直接修改PRODUCT_PROPERTY_OVERRIDES。
    再定义target, 用于生成$(PRODUCT_OUT)/sdk/sdk-build.prop
    再定义target,package-stats,用于生成$(PRODUCT_OUT)/package-stats.txt,这个文件包含了.jar,.apk后缀文件的信息。
    再定义target,apkcerts-list,用于生成$(name)-apkcerts-$(FILE_NAME_TAG),描述各module的certificate和private_key文件信息。
    接着,如果定义了CREATE_MODULE_INFO_FILE,则生成$(PRODUCT_OUT)/module-info.txt,其中包含了描述所有module的信息。
    再定义target,event-log-tags。
    接着,处理ramdisk.img
    再处理boot.img,如果TARGET_NO_KERNEL不是true,则将kernel和ramdisk.img组装成boot.img。
    接着,定影命令combine-notice-files,用于生成target,notice_files。notice_files会抽取生成相应的声明文件。
    随后,建立target,otacert,用于将.x509.pem后缀的认证文件打包存放到$(TARGET_OUT_ETC)/security/otacerts.zip。
    接着,建立target,recoveryimage,处理recovery img
    还有下面的target,

    systemimage-nodeps, snod
    systemtarball-nodeps,stnod
    boottarball-nodeps,btnod
    userdataimage-nodeps
    userdatatarball-nodeps
    otatools
    target-files-package
    otapackage
    installed-file-list
    tests-zip-package
    dalvikfiles
    updatepackage

    最后包含进 build/core/task/下的mk文件。

  • 相关阅读:
    20150119--无限级分类+商品分类-02
    20150119--无限级分类+商品分类 01
    20150117--SQL注入+验证码类-02
    20150117--SQL注入+验证码类
    20150116--Cookie+Session-02
    20150116--Cookie+Session
    20150115--SHOP项目架构+后台权限管理-02
    20150115--SHOP项目架构+后台权限管理
    20150113--PDO增删改查+封装PDO类-02
    20150113--PDO增删改查+封装PDO类
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124271.html
Copyright © 2011-2022 走看看