热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Androidmake脚本简记

Android Make脚本的简记(1)   内容提要 文档简要整理Android的make脚本的内容。以供备忘和参考。     1.    Build Layers Build Layers描述的

Android Make脚本的简记(1)

 
内容提要
文档简要整理Android的make脚本的内容。以供备忘和参考。
 
 
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,已去除多余的注释行。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := libarity
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Calculator
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libarity:arity-2.1.2.jar
include $(BUILD_MULTI_PREBUILT)
# Use the folloing include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))

至少有一个子目录,src下放源码。

Android.mk中需要赋值的几个LOCAL_XXX变量,
LOCAL_PATH,调用my-dir(在defination.mk中定义),得到当前路径,即,/ 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的列表

说明:
    必须定义, 在app或package的Android.mk中必须给定值。
    可选定义,在app或package的Android.mk中可以也可以不给定值。
    不用定义,在app或package的Android.mk中不要给定值,脚本自动指定值。

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//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。

Android Make脚本的简记(2)


 
内容提要
文档简要整理Android的make脚本的内容。以供备忘和参考。

 
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/_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的场景。
提取变量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, ":"
# $(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情况。
Android101110: Android Make脚本的简记(3)

 
内容提要
文档简要整理Android的make脚本的内容。以供备忘和参考。

 
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:
   --mindepth=
       Both behave in the same way as their find(1) equivalents.
   --prune=
       Avoids returning results from inside any directory called
       (e.g., "*/out/*"). May be used multiple times.

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


2. pathmap.mk的分析

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


3. config.mk的分析

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

-------TODO

4. buildspec.mk的分析

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


5. envsetup.mk的分析

首先包含进version_defaults.mk&#xff0c;定义好一些版本相关的变量。参见version_defaults.mk。

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

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

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

然后包含进product_config.mk。

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

随后判定HOST_OS(linux)&#xff0c;HOST_ARCH(x86)

接着&#xff0c;确定TARGET_ARCH和TARGET_OS&#xff0c;若没有定义&#xff0c;则取默认值。
TARGET_ARCH :&#61; arm
TARGET_OS :&#61; linux

接着&#xff0c;确定TARGET_BUILD_TYPE&#xff0c;若没有定义&#xff0c;则取默认值。
TARGET_BUILD_TYPE :&#61; release

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

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


6. version_defaults.mk的分析

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


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


7. build_id.mk的分析

用户可以在build_id.mk中定义这样几个参数&#xff0c;
PLATFORM_VERSION
PLATFORM_SDK_VERSION
PLATFORM_VERSION_CODENAME
DEFAULT_APP_TARGET_SDK
BUILD_ID
BUILD_NUMBER
这些参数最终将出现build.prop中。

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


8. product_config.mk的分析

make PRODUCT-- 

如果使用上述形式的make命令&#xff0c;那么将等同于

TARGET_PRODUCT:&#61;
TARGET_BUILD_VARIANT:&#61;
goal_name:&#61;PRODUCT--
MAKECMDGOALS:&#61;droid

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

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

使用make PRODUCT--这种形式&#xff0c;可以方便的指定TARGET_PRODUCT&#xff0c;和TARGET_BUILD_VARIANT。


make APP- 

如果使用上述形式的make命令&#xff0c;那么将等同于
TARGET_BUILD_APPS:&#61;
unbundled_goals:&#61;APP-
MAKECMDGOALS:&#61;droid

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

使用make APP-这种形式&#xff0c;可以方便的指定TARGET_BUILD_APPS。


注意&#xff0c;PRODUCT--和APP-可以一块使用。

处理完PRODUCT--和APP-&#xff0c;product_config.mk会包含下面3个文件
node_fns.mk
product.mk
device.mk

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

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

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

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


9. node_fns.mk的分析

定义了一些命令。这些命令在product.mk&#xff0c;device.mk&#xff0c;和product_config.mk中会使用。这里重点说明import-nodes。

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

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

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

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

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


10. product.mk的分析

product.mk构造了一些命令&#xff0c;供product_config.mk中使用。

_find-android-products-files这个命令会得到device/和vendor/, 包括子目录&#xff0c;以及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 :&#61; /
    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变量值中后缀上&#39;&#64;inherit:&#39;&#xff0c;当import-nodes处理时&#xff0c;会替换成继承的属性。

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

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


11. device.mk的分析

同product.mk类似&#xff0c;device.mk构造了一些命令。有resolve-short-device-name&#xff0c;和import-devices。

Android Make脚本的简记(4)

 
内容提要
文档简要整理Android的make脚本的内容。以供备忘和参考。

 
 
1. config.mk的分析

首先&#xff0c;包含pathmap.mk&#xff0c; 其次&#xff0c;定义了一些变量&#xff0c;例如通用的编译参数&#xff0c;package的后缀名等。

随后包含buildspec.mk。

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

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

定义TARGET_DEVICE_DIR&#xff0c;TARGET_BOOTLOADER_BOARD_NAME&#xff0c;TARGET_CPU_ABI等跟board相关的变量。

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

再包含javac.mk&#xff0c;定义javac的命令和通用参数。

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

最后定义了一些编译链接变量&#xff0c;这里专门列出&#xff0c;
HOST_GLOBAL_CFLAGS &#43;&#61; $(COMMON_GLOBAL_CFLAGS)
HOST_RELEASE_CFLAGS &#43;&#61; $(COMMON_RELEASE_CFLAGS)

HOST_GLOBAL_CPPFLAGS &#43;&#61; $(COMMON_GLOBAL_CPPFLAGS)
HOST_RELEASE_CPPFLAGS &#43;&#61; $(COMMON_RELEASE_CPPFLAGS)

TARGET_GLOBAL_CFLAGS &#43;&#61; $(COMMON_GLOBAL_CFLAGS)
TARGET_RELEASE_CFLAGS &#43;&#61; $(COMMON_RELEASE_CFLAGS)

TARGET_GLOBAL_CPPFLAGS &#43;&#61; $(COMMON_GLOBAL_CPPFLAGS)
TARGET_RELEASE_CPPFLAGS &#43;&#61; $(COMMON_RELEASE_CPPFLAGS)

HOST_GLOBAL_LD_DIRS &#43;&#61; -L$(HOST_OUT_INTERMEDIATE_LIBRARIES)
TARGET_GLOBAL_LD_DIRS &#43;&#61; -L$(TARGET_OUT_INTERMEDIATE_LIBRARIES)

HOST_PROJECT_INCLUDES:&#61; $(SRC_HEADERS) $(SRC_HOST_HEADERS) $(HOST_OUT_HEADERS)
TARGET_PROJECT_INCLUDES:&#61; $(SRC_HEADERS) $(TARGET_OUT_HEADERS)

ifneq ($(TARGET_SIMULATOR),true)
TARGET_GLOBAL_CFLAGS &#43;&#61; $(TARGET_ERROR_FLAGS)
TARGET_GLOBAL_CPPFLAGS &#43;&#61; $(TARGET_ERROR_FLAGS)
endif

HOST_GLOBAL_CFLAGS &#43;&#61; $(HOST_RELEASE_CFLAGS)
HOST_GLOBAL_CPPFLAGS &#43;&#61; $(HOST_RELEASE_CPPFLAGS)

TARGET_GLOBAL_CFLAGS &#43;&#61; $(TARGET_RELEASE_CFLAGS)
TARGET_GLOBAL_CPPFLAGS &#43;&#61; $(TARGET_RELEASE_CPPFLAGS)

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

最后包含进dumpvar.mk


2. javac.mk的分析

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

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

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

3. dumpvar.mk的分析

dumpvar.mk 支持两种target: dumpvar-&#xff0c;和dumpvar-abs-。envsetup.sh中的 get_build_var和get_abs_build_var就使用了这些target。

使用方法&#xff1a;假设位于$(TOPDIR)路径&#xff0c;

CALLED_FROM_SETUP&#61;true BUILD_SYSTEM&#61;build/core make -f build/core/config.mk dumpvar-

CALLED_FROM_SETUP&#61;true BUILD_SYSTEM&#61;build/core make -f build/core/config.mk dumpvar-abs-

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

4. cleanbuild.mk的分析

main.mk在包含了config.mk后&#xff0c;会包含进cleanbuild.mk。

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

接着&#xff0c;包扩进cleanspec.mk

包含进$(PRODUCT_OUT)/clean_steps.mk&#xff0c;

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

然后&#xff0c;重新生成$(PRODUCT_OUT)/clean_steps.mk&#xff0c;写入"CURRENT_CLEAN_BUILD_VERSION :&#61; $(INTERNAL_CLEAN_BUILD_VERSION)"和"CURRENT_CLEAN_STEPS :&#61; $(INTERNAL_CLEAN_STEPS)"。

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

 echo "PREVIOUS_BUILD_CONFIG :&#61; $(current_build_config)" > /
      $(previous_build_config_file)

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


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


5. cleanspec.mk的分析

首先定义
INTERNAL_CLEAN_BUILD_VERSION :&#61; 4

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

至此&#xff0c;INTERNAL_STEP.XXXX包含了所有CleanSpec.mk定义的clean动作。


6. version_checked.mk的分析

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

version_checked.mk中就定义了
VERSIONS_CHECKED :&#61; $(VERSION_CHECK_SEQUENCE_NUMBER)

7. showcommands和checkbuild的说明

checkbuild貌似并未使用。

showcommands必须同其它target一同使用&#xff0c;showcommands会详细打印出执行的具体命令内容。

8. definations.mk的说明

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

其中的inherit-package命令有待研究...
Android101112: Android Make脚本的简记(5)

 
内容提要
文档简要整理Android的make脚本的内容。以供备忘和参考。



声明
仅限学习交流&#xff0c;禁止商业用途。转载需注明出处。

 
1. Makefile的分析

首先定义target&#xff0c; 用于生成$(OUT_DOCS)/index.html

再定义target&#xff0c; 用于生成$(TARGET_ROOT_OUT)/default.prop

再定义target&#xff0c; 用于生成$(TARGET_OUT)/build.prop。build.prop文件记录了一系列属性值。它的内容分成两部分&#xff0c;第一部分是一些关于 product,device,build的一般性属性值&#xff0c;第二部分的属性值源自ADDITIONAL_BUILD_PROPERTIES。 product配置mk文件中定义的PRODUCT_PROPERTY_OVERRIDES会加入到 ADDITIONAL_BUILD_PROPERTIES&#xff0c;建议增加property时&#xff0c;直接修改 PRODUCT_PROPERTY_OVERRIDES。

再定义target&#xff0c; 用于生成$(PRODUCT_OUT)/sdk/sdk-build.prop

再定义target&#xff0c;package-stats&#xff0c;用于生成$(PRODUCT_OUT)/package-stats.txt&#xff0c;这个文件包含了.jar,.apk后缀文件的信息。

再定义target&#xff0c;apkcerts-list&#xff0c;用于生成$(name)-apkcerts-$(FILE_NAME_TAG)&#xff0c;描述各module的certificate和private_key文件信息。

接着&#xff0c;如果定义了CREATE_MODULE_INFO_FILE&#xff0c;则生成$(PRODUCT_OUT)/module-info.txt&#xff0c;其中包含了描述所有module的信息。

再定义target&#xff0c;event-log-tags。

接着&#xff0c;处理ramdisk.img

再处理boot.img&#xff0c;如果TARGET_NO_KERNEL不是true&#xff0c;则将kernel和ramdisk.img组装成boot.img。

接着&#xff0c;定影命令combine-notice-files&#xff0c;用于生成target&#xff0c;notice_files。notice_files会抽取生成相应的声明文件。

随后&#xff0c;建立target&#xff0c;otacert&#xff0c;用于将.x509.pem后缀的认证文件打包存放到$(TARGET_OUT_ETC)/security/otacerts.zip。

接着&#xff0c;建立target&#xff0c;recoveryimage&#xff0c;处理recovery img

还有下面的target,

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

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


推荐阅读
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • intellij idea的安装与使用(保姆级教程)
    intellijidea的安装与使用(保姆级教程)IntelliJ在业界被公认为最好的java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(gi ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文详细介绍了在Centos7上部署安装zabbix5.0的步骤和注意事项,包括准备工作、获取所需的yum源、关闭防火墙和SELINUX等。提供了一步一步的操作指南,帮助读者顺利完成安装过程。 ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
  • PHP中的单例模式与静态变量的区别及使用方法
    本文介绍了PHP中的单例模式与静态变量的区别及使用方法。在PHP中,静态变量的存活周期仅仅是每次PHP的会话周期,与Java、C++不同。静态变量在PHP中的作用域仅限于当前文件内,在函数或类中可以传递变量。本文还通过示例代码解释了静态变量在函数和类中的使用方法,并说明了静态变量的生命周期与结构体的生命周期相关联。同时,本文还介绍了静态变量在类中的使用方法,并通过示例代码展示了如何在类中使用静态变量。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
author-avatar
农大军乐团_697
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有