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的所有源碼,如果是java源碼的話,可以調用all-java-files-under
得到。
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_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的場景。
提取變量
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情況。
Android Make腳本的簡記(3)
1. main.mk
1.檢查版本號,設置環境變量(BUILD_SYSTEM)和 缺省的目標BUILD_SYSTEM= build/core
2.包含文件BUILD_SYSTEM/config.mk。根據配置信息和主機目標機信息,設置一些變量。
3.包含文件BUILD_SYSTEM/cleanbuild.mk。如果當前配置改變,強制刪除上次的編譯結果
4.包含文件
OUT_DIR/version_check.mk
。就設置了VERSIONS_CHECKED
。如果版本序號改變,即VERSION_CHECK_SEQUENCE_NUMBER!=VERSIONS_CHECKED
,檢查文件系統是否大小寫不敏感。文件路徑上是否沒有空格。JAVA,JAVAC的版本是否是1.6。5.包含文件
BUILD_SYSTEM/definitions.mk
。定義了很多函數供makefile文件系統使用。
主要的是transform-xxx-to-xxx
的形式,比如transform-cpp-to-o
。並定義了一個make目標dist,額外的拷貝一些重要的文件到目標文件夾。
6.檢查
MAKECMDGOALS
和TARGE_BUILD_VARIANT
.根據MAKECMDGOALS
設置標量is_sdk_build
,是否編譯SDK。7.根據
TARGE_BUILD_VARIANT
,設置
tags_to_install,ADDITIONAL_DEFAULT_PROPERTIES
TARGE_BUILD_VARIANT tags_to_install ADDITIONAL_DEFAULT_PROPERTIES
user user ro.secure=1 ro.allow.mock.location=0
eng user debug eng ro.setupwizard.mode=OPTIONAL
tests user debug eng
sdk user debug eng xmpp.auto-presence=true ro.config.nocheckin=yes
user debug user debug ro.sercure=1 dalvik.vm.lockprof.threshold=500
ro.allow.mock.location=0
ro.debuggable=1 persist.service.adb=1
8.檢查
PARDUCT_TAG
是否包含dalvik.gc.type-precise
,如果包含設置ADDITIONAL_DEFAULT_PROPERTIES+=dalvik.vm.dexopt-flags=m=y
9.判斷PRODUCT_COPY_FILES。爲空就安裝apns-conf.xml文件
PRODUCT_COPY_FILE=development/data/etc/apns-conf_sdk.xml:system/etc/apns-conf.xml
如果TARGE_BUILD_VARIANT
包含eng,tests
但不包含sdk
,且vendor/google/etc/apns-conf.xml
文件存在,則PRODUCT_COPY_FILE=vendor/google/etc/apns-conf.xml:system/etc/apns-conf.xml
- 10.設置
ADDITIONAL_BUILD_PROPERTIES+= net.bt.name=Android
dalvik.vm.stack-trace-file=/data/anr/traces.txt
11.如果
MAKECMDGOALS
僅包含showcommands
或checkbuild
,設置make目標爲DEFAULT_GOALS
12.如果
MAKECMDGOALS
不包含clean,clobber,dataclean,installclean
,根據不同的主機平臺和處理器品平臺,包含進要編譯的模塊,設置subdirs
。13.通過
build/tools/findleaves.py
,把subdirs
目錄下的Android.mk存在subdirs_makefiles。幷包含這些文件。如果使用mm命令,只包含當前目錄下的Android.mk。14.若是全部編譯,包含
frameworks/policies/base/PolicyConfig.mk
。生成android.policy模塊,並定義了自己的make刪除操作policy_installclean
。15.根據
tags_to_install
和is_sdk_build
,設置哪些模塊需要安裝,並存入modules_to_install
.
這裏主要有兩個函數要說明一下:
get-tagged-modules $1 $2
這兩個參數一般都是ALL_MODULE_TAGS=debug eng gnuoptional samples testsuser
裏面的值,取得$1
中不包括$2
的列表,比如tests user
,返回$(ALL_MODULE_TAGS.user)$(ALL_MODULE_TAGS.tests)
即帶有user
或tests
標記模塊的目標文件路徑列表。
Module-installed-files $1 $1
一般的是一個短的模塊名,比如framework
,Browers
,返回這個模塊的目標文件路徑
16.包含:
$(BUILD_SYSTEM)/Makefile
。主要是定義了一些僞目標。17.定義modules_to_check,文件路徑列表,若模塊沒有定義LOCAL_DONT_CHECK_MODULE,會把生成目標的規則加入到這個變量,以便在modules_to_install後檢查目標是否生成成功,目標不存在的話再次生成目標。
18.定義一些
make target
target 說明
.PHONY:checkbuilt
checkbuilt: $(modules-to-check)
生成沒有定義LOCAL_DONT_CHECK_MODULE的模塊並拷貝到系統目錄
.PHONY:prebuilt
prebuit: $(ALL_PREBUILT)
拷貝預遍野的文件(比如用include prebuild.mk編譯的)到系統目錄
.PHONY: files
files: prebuilt checkbuilt moduls-to-install $(INSTALLED_ANDROID_INFO_TXT_TARGET)
生成所有目標文件(包括:prebuile,modules-to-install,modules-to-check,INSTALLED_ANDROID_INFO_TXT_TARGET)並拷貝到系統目錄。INSTALLED_ANDROID_INFO_TXT_TARGET在build/target/board/Android.mk定義=out/target/product/**/android-info.txt
.PHONY: ramdisk
ramdisk: $(INSTALL_RAMDISK_TARGET)
生成ramdisk.img
$(HOST_OUT_EXECUTABLES)/mkbootfs $(PRODUCT_OUT)/root|$(HOST_OUT_EXECUTABLES)/minizip > $(PRODUCT_OUT)/ramdisk.img
.PHONY: systemimage
systemimage: $(INSTALL_SYSTEMIMAGE)
生成system.img
$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE)
$(HOST_OUT_EXECUTABLES)/mkyaffs2image$(PRODUCT_OUT)/system$(PRODUCT_OUT)/obj/PACKING/systemimage_unopt_intermediates/system.img
cp **/system.img (PRODUCT_OUT)/system.img
.PHONY: userdataimage
userdataimage:$(INSTALL_USERDATAIMAGE_TARGET)
生成data.img
$(HOST_OUT_EXECUTABLES)/mkyaffs2image $(PRODUCT_OUT)/data $(PRODUCT_OUT)/data.img
.PHONY: bootimage
bootimage: $(INSTALL_BOOTIMAGE_TARGET)
生成boot.img
if(TARGET_NO_KERNEL=true), INSTALL_BOOTIMAGE_TARGET=$(PRODUCT_OUT)/boot.img else $(PRODUCT_OUT)/boot.img=.
參數:
INTERNAL_BOOTIMAGE_ARGS := \
$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
--kernel $(INSTALLED_KERNEL_TARGET) \
--ramdisk $(INSTALLED_RAMDISK_TARGET)
$(HOST_OUT_EXECUTABLES)/mkbootimg --kernel $(PRODUCT_OUT)/kernel –ramdisk $(PRODUCT_OUT)/ramdisk.img >$(PRODUCT_OUT)/boot.img
.PHONY: recoveryimage
recoveryimage:$(INSTALL_RECOVERYIMAGE_TARGET)
生成ramdisk-recovery.img recovery.img
目錄$(PRODUCT_OUT)
rm -rf recovery
mkdir -p recovery
mkdir -p recovery/root
mkdir -p recovery/root/etc
mkdir -p recovery/root/tmp
cp -R root recovery/root
cp -f /bootable/recovery/init.rc recovery/root/
cp -f obj/EXECUTABLES/recovery_intermediates/recovery recovery/root/sbin/
cp -rf /bootable/recovery/res recovery/root/
$(foreach item,/build/target/product/**/recovery/res
cp -rf $(item) recovery/root/)
cp /obj/PACKAGING/ota_keys_ intermediates/keys recovery/res/keys
cat root/default.prop system/build.prop > recovery/root/default.prop
$(HOST_OUT_EXECUTABLES)/mkbootfs$(PRODUCT_OUT)/recovery/root|$(HOST_OUT_EXECUTABLES)/minizip > $(PRODUCT_OUT)/ramdisk-recovery.img
$(HOST_OUT_EXECUTABLES)/mkbootimg --kernel $(PRODUCT_OUT)/kernel –ramdisk$(PRODUCT_OUT)/ramdisk-recovery.img > $(PRODUCT_OUT)/recovery.img
.PHONY: droidcore
droidcore: files \
systemimage \
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_RECOVERYIMAGE_TARGET) \
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_FILES_FILE)
生成整個系統
system.img ramdisk.img/boot.img ramdisk-recovery.img recovery.img userdata.img installed-files.txt
.PHONY: apps_only
生成TARGET_BUILD_APPS指定的APPS模塊.
若TARGET_BUILD_APPS包含all就編譯全部APPS模塊
droid
默認target。
ifneq ($(TARGET_BUILD_APPS),)
droid: apps_only
else
droid:droidcore
.PHONY: sdk
生成sdk
.PHONY: clean
.PHONY: clobber
刪除生成文件
.PHONY: modules
顯示所有模塊名
.PHONY: showcommands
顯示命令
2. 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文件。
- 1.設置一些原文件路徑,以SRC_開頭
2.包含文件
$(BUILD_SYSTEM)/pathmap.mk
,定義了一些短名到長路徑名的影射,
存放在pathmap_INCL
,通過include-path-for $1
根據短名獲取到長路徑名FRAMEWORKS_BASE_JAVA_SRC_DIRS
保存了所有要編進Android.jar的framework/base
下的文件路徑。3.設置編譯目標,.jar,.bin,.so,.a,.apk,…。以BUILD_開頭,指向具體的mk文件。比如
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
4.設置一般編譯選項和不同類型的文件後綴名。以
COMMON_
開頭。COMMON_GLOBAL_CFLAGS,COMMON_RELEASE_CFLAGS。COMMON_PACKAGE_SUFFIX:=.zip
5.包含
include$(TOPDIR)buildspec.mk
。設置一些主要的變量,比如目標產品名稱。這些都要我們在make之前設置。這個文件有個模版是build/buildspec.mk.default。
6.包含
include$(BUILD_SYSTEM)/envsetup.mk
。設置一些跟product相關的變量。7.包含
$(board_config_mk)
,在build/target/board/$(TARGET_DEVICE)/BroadConfig.mk
,device/*/$(TARGET_DEVICE)/BroadConfig.mk
,veror/*/$(TARGET_DEVICE)/BroadConfig.mk
這三個路徑下,查找product的目標設備的BroadConfig.mk文件。幷包含進來。BroadConfig.mk設置了每個設備的自己的一些變量值,來區別編譯時的行爲。TARGET_CPU_ABI
必須要設置。這些設備是被product.mk中TARGET_DEVICE
指定,一個設備信息可以被很多個product使用。8.設置
combo_target := HOST_
,包含include $(BUILD_SYSTEM)/combo/select.mk。
根據操作系統和CPU類型設置以HOST_開頭的變量,幷包含include$(BUILD_SYSTEM)/combo/HOST_$(HOST_OS)_$(HOST_ARCH).mk
,其中HOST_OS
是主機操作系統,HOST_ARCH
是主機CPU類型,比如HOST_linux_x86.mk
.在這個文件裏修改以HOST_開頭的變量,主要是向HOST_GLOBAL_CFLAGS
添加標誌。
- 9.設置
combo_target := TARGET_
,包含include $(BUILD_SYSTEM)/combo/select.mk
。
根據操作系統和CPU類型設置以TARGET_
開頭的變量,幷包含include$(BUILD_SYSTEM)/combo/TARGET_$(TARGET_OS)_$(TARGET_ARCH).mk
,其中TARGET_OS
是目標操作系統,TARGET_ARCH
是目標CPU類型,比如TARGET_linux_arm.mk
.在這個文件裏修改以TARGET_開頭的變量,主要是設置交叉編譯工具和參數和基本的系統頭文件。定義了transform-o-to-shared-lib-inner,transform-o-to-executable-inner,transform-o-to-static-executable-inner三個函數,把.o文件分別轉化成共享庫文件,可執行文件,靜態庫文件。
- 10.包含
include$(BUILD_SYSTEM)/combo/javac.mk
。得到一個JAVAC編譯器
CUSTOM_JAVA_COMPILER
COMMON_JAVAC
eclipse
=java -Xmx256m -jar prebuilt/common/ecj/ecj.jar -5 \ -maxProblems 9999999 -nowarn
openjdk
= prebuilt/common/openjdk/bin/javac -target 1.5 \ -Xmaxerrs 9999999
others
Windows: = development/host/windows/prebuilt/javawrap.exe -J-Xmx256m \ -target 1.5 -Xmaxerrs 9999999
Other:=javac -J-Xmx512M -target 1.5 -Xmaxerrs 9999999
11.檢查
BUILD_ENV_SEQUENCE_NUMBER
,這個是在前面的buildspec.mk設置或者通過envsetup.sh腳本設置。12.設置主機通用工具變量。其中一些是主機自帶的
LEX:= flex
YACC:=bison -d DOXYGEN:= doxygen
,還有一些是在/out/target/$($(HOST_OS)-$(HOST_ARCH))/bin
下的程序,MKBOOTIMG:=$(HOST_OUT_EXECUTABLES)/mkbootimg。
- 13.設置最終的編譯連接參數。有如下參數變量:
HOST_GLOBAL_CFLAGS, HOST_RELEASE_CFLAGS, HOST_GLOBAL_CPPFLAGS,
HOST_RELEASE_CPPFLAGS, TARGET_GLOBAL_CFLAGS, TARGET_RELEASE_CFLAGS,
TARGET_GLOBAL_CPPFLAGS,TARGET_RELEASE_CPPFLAGS, HOST_GLOBAL_LD_DIRS,
TARGET_GLOBAL_LD_DIRS, HOST_PROJECT_INCLUDES, TARGET_PROJECT_INCLUDES,
- 13.獲得sdk和ndk的版本號列表。
TARGET_AVAILABLE_SDK_VERSIONS
和TARGET_AVAILABLE_NDK_VERSIONS
3 envsetup.mk
- 1.包含:
include$(BUILD_SYSTEM)/version_defaults.mk
,設置那些我們需要設置的變量的缺省值。這個文件我們不因該改動,改動應該在build_id.mk裏。
PLATFORM_VERSION
2.2.1
PLATFORM_SDK_VERSION
8
PLATFORM_VERSION_CODENAME
REL
DEFAULT_APP_TARGET_SDK
PLATFORM_SDK_VERSION
BUILD_ID
MASTER
BUILD_NUMBER
eng.$(USER).$(date)
- 2.設置在文件buildspec.mk裏或通過envsetup.sh設置的變量的缺省值。
TARGET_PRODUCT
generic(TARGET_SIMULATOR := false)
sim(TARGET_SIMULATOR:=false)
TARGET_BUILD_VARIANT
eng
HOST_OS
windows/Linux/darwin
HOST_ARCH
x86/ppc
HOST_BUILD_TYPE
release
TARGET_OS
linux
TARGET_ARCH
arm
TARGET_BUILD_TYPE
release
3.包含:
include$(BUILD_SYSTEM)/product_config.mk
。定義了兩種MAKECMDGOALS
參數形式,根據product和device目錄下的mk文件生成相應的PRODUCTS_xxx_xxx
和DEVICES_xxx_xxx
變量。中間的是文件的路徑,後面的是文件裏定義的變量。4.設置一些列路徑變量。主機路徑以
HOST_OUT_*
或HOST_*_OUT_*
形式,目標機路徑以TARGET_OUT_*
或TARGET_*_OUT_*
形式。5.根據
MAKECMDGOALS
,若其中包含dumpvar-%
或dumpvar-abs-%
,就生成一個以dumpvar-%
或dumpvar-abs-%
命名的make目標。實現是打印出%所表示的變量的值。這個變量必須要在這之前已經定義了,後一種在前面還打印出當前的路徑。這兩種情況必須要先設置CALLED_FROM_SETUP=true
。envsetup.sh的get_build_var
和get_abs_build_var(
)函數就是運用的這個原理打印變量的值。
view plain
# Get the exact value of a buildvariable.
function get_build_var()
{
T=$(gettop)
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP." >&2
return
fi
CALLED_FROM_SETUP=trueBUILD_SYSTEM=build/core \
make--no-print-directory -C "$T" -f build/core/config.mk dumpvar-$1
}
# Get the value of a build variable asan absolute path.
function get_abs_build_var()
{
T=$(gettop)
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP.">&2
return
fi
CALLED_FROM_SETUP=trueBUILD_SYSTEM=build/core \
make --no-print-directory -C "$T"-f build/core/config.mk dumpvar-abs-$1
}
4. product_config.mk
- 1.定義兩種命令形式:
makePRODUCT-<prodname>-<goal>
TARGET_PRODUCT := prodname TARGET_BUILD_VARIANT := goal
make APP-<appnames>
TARGET_BUILD_APPS := appnames
- 2.包含:
include$(BUILD_SYSTEM)/node_fns.mk
include $(BUILD_SYSTEM)/product.mk
include $(BUILD_SYSTEM)/device.mk
這三個文件主要是定義了一些函數來相互調用或供product_config.mk文件調用
函數名
說明
node_fns.mk Import- nodes $(1) $(2) $(3)
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的問題,如果某個PRODUCT.xxx.xxx變量的值中有@inherit:<mk文件>
標識後面跟的是mk文件名,則會把那個mk文件中相應的變量的屬性添加到PRODUCT.xxx.xxx
中。@inherit:<mk文件>
是inherit-product
命令添加的。這個函數在product.mk。
product.mk
_find-android-products-files
得到device/和vendor/, 包括子目錄,以及build/target/product/下的AndroidProducts.mk文件列表
product.mk
get-all-product-makefiles
得到所有AndroidProducts.mk文件中 PRODUCT_MAKEFILES變量定義的mk文件列表
product.mk
import-products
調用import-nodes(node_fns.mk),設置$1=PRODUCTS,
設置$3=$(_product_var_list)
,_product_var_list
是以PRODUCT_
開頭的變量名。
product.mk
inherit-product
將在所有的PRODUCT_xxx
變量值後綴加上@inherit:<mk文件>
product.mk
check-all-products
檢查PRODUCT_NAME,PRODUCT_BRAND,PRODUCT_COPY_FILES
定義的是否正確
product.mk
resolve-short-product-name
根據product的名字,得到定義它的mk文件路徑
(resolve-short-product-name generic → /build/target/product/generic.mk)
device.mk
import-devices
調用import-nodes(node_fns.mk)
,設置$1=DEVICES,
設置$3=$(_device_var_list),_device_var_list
是以DEVICE_
開頭的變量名。
device.mk
inherit-device
將在所有的DEVICE_變量值後綴加上’@inherit:
device.mk
resolve-short-device-name
根據device的名字,得到定義它的mk文件路徑
- 3.調用import-products函數,判斷
TARGET_BUILD_APPS
是否爲空,若爲空,只導入
$(SRC_TARGET_DIR)/product/AndroidProducts.mk
裏的mk文件。否則調用get-all-product-makefiles
,導入全部mk文件。再調用check-all-products檢查變量設置的正確性。
- 4.根據要編譯的目標
TARGET_PRODUCT
,通過調用resolve-short-product-name
得到mk文件,結果存放在INTERNAL_PRODUCT
變量裏。再將PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_xxx
的值賦值給PRODUCT_xxx。ADDITIONAL_BUILD_PROPERTIES
追加PRODUCT_PROPERTY_OVERRIDES
。這些PRODUCT_
變量都在product
下的mk文件裏定義。如下:
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
5. 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*
INTERNAL_CLEAN_STEPS+=packages_apps_Camera_CleanSpec-mk_acs4@:
INTERNAL_CLEAN_STEPS+packages_apps_Camera_CleanSpec-mk_acs4@@:
2.包含:
$(BUILD_SYSTEM)/cleanspec.mk
。設置INTERNAL_CLEAN_BUILD_VERSION :=3
,並通過add-clean-step
函數,加進一些默認的刪除操作,在通過build/tools/findleaves.py
枚舉所有的CleanSpec.mk
文件,並把它們包含進來。在這些文件里根據具體的模塊加刪除操作。3.包含:
$(PRODUCT_OUT)/clean_steps.mk
。這個文件是自動生成的,設置CURRENT_CLEAN_BUILD_VERSION:=INTERNAL_CLEAN_BUILD_VERSION
4.比較
CURRENT_CLEAN_BUILD_VERSION
和INTERNAL_CLEAN_BUILD_VERSION
若相等執行INTERNAL_CLEAN_STEPS
裏的命令,否則表示我們修改過cleanspec.mk, 刪除整個$(OUT_DIR)
。5.包含:
$(PRODUCT_OUT)/previous_build_config.mk
。這個文件也是自動生成的,查看PREVIOUS_BUILD_CONFIG
是否於當前的編譯選項一致。不相同就強制刪除中間文件,並將當前的編譯選項寫入文件。刪除的文件是由installclean_files,dataclean_files
定義。PREVIOUS_BUILD_CONFIG
的格式是$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)$(building_sdk)-{$(locale_list)}
。6.定義兩個make目標
installclean
和dataclean
。分別用來刪除安裝文件和數據文件。
6. Makefile
1.生成一些記錄文件
(1).生成
$(OUT_DOCS)/index.html
文件,將frameworks/base/docs/docs-redirect-index.html
文件內容拷貝進去。(2).生成
$(TARGET_ROOT_OUT)/default.prop
文件,將ADDITIONAL_DEFAULT_PROPERTIES
的值寫入文件。生成$(TARGET_OUT)/build.prop
文件,主要存放的是build.properties,
主要來自於三個方面:
1,通過執行build/tools/buildinfo.sh
根據PRODUCT_NAME
變量值…獲得
2.文件$(TARGET_DEVICE_DIR)/system.prop
3.ADDITIONAL_BUILD_PROPERTIES
變量值(3).生成文件
$(PRODUCT_OUT)/sdk/sdk-build.prop
,拷貝$(TARGET_OUT)/build.prop
內容,並修改sdk_build_prop_remove
定義的屬性列表值都爲generic
。(4).生成文件
$(PRODUCT_OUT)/module-info.txt
,列出全部模塊的信息,需聲明CREATE_MODULE_INFO_FILE
。
2.定義一些
make target
3.包含
$(BUILD_SYSTEM)/tasks
目錄下的所有.mk文件。
3.build/core/pathmap.mk的分析
pathmap.mk 中定義了一個列表pathmap_INCL
,列表中每項是”短名:路徑”對。命令include-path-for
使用這個pathmap_INCL
列表,輸入短名,得到路徑。你可以在這個列表中添加自己的對。使用$(call include-path-for, <短名>)
就可以得到路徑。
另外,定義了FRAMEWORKS_BASE_JAVA_SRC_DIRS
,含有frameworks/base目錄下含java文件的所有目錄。
4. buildspec.mk的分析
buildspec.mk是用戶應當配置的腳本文件,模板可以使用build/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.build/core/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. build/core/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/core/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. build/core/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
變量的值中有文件>’標識後面跟着 mk文件名的字串,則會把那個mk文件中相應的變量的屬性添加到PRODUCTS.XXX
中。文件>’是 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變量值中後綴上文件>’,當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..中,一個product對應一個。最後根據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。
- dumpvar.mk的分析
dumpvar.mk 支持兩種target: dumpvar-,和dumpvar-abs-。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會詳細打印出執行的具體命令內容。
- 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