Android make指令碼簡記

jackie_gnu發表於2011-08-27

 http://quanminchaoren.iteye.com/blog/840918

內容提要
文件簡要整理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中定義),得到當前路徑,即,<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的列表

說明:
    必須定義, 在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/<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/<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的場景。
提取變數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情況。
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>] <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。

Android Make指令碼的簡記(4)

 
內容提要
文件簡要整理Android的make指令碼的內容。以供備忘和參考。

 
 
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命令有待研究...
Android101112: Android Make指令碼的簡記(5)

 
內容提要
文件簡要整理Android的make指令碼的內容。以供備忘和參考。



宣告
僅限學習交流,禁止商業用途。轉載需註明出處。

 
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檔案。

相關文章