Android.mk 組織結構
下面是main.mk文件包含關係,本文檔主要說明的就是這些文件裡到底做了什麼。(這個文件被根目錄下的makefile文件包含)
一. main.mk
1.檢查版本號,設置環境變量(BUILD_SYSTEM)和缺省的目標。$(MAKE_VERSION) >= 3.81,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/otakeys 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
顯示命令
二. config.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.在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.設置combotarget := HOST,包含include $(BUILD_SYSTEM)/combo/select.mk。
根據操作系統和CPU類型設置以HOST開頭的變量,幷包含include$(BUILD_SYSTEM)/combo/HOST$(HOSTOS)$(HOSTARCH).mk,其中HOST_OS是主機操作系統,HOST_ARCH是主機CPU類型,比如HOST_linux_x86.mk.在這個文件裡修改以HOST開頭的變量,主要是向HOST_GLOBAL_CFLAGS添加標誌。
9.設置combotarget := TARGET,包含include $(BUILD_SYSTEM)/combo/select.mk。
根據操作系統和CPU類型設置以TARGET開頭的變量,幷包含include$(BUILD_SYSTEM)/combo/TARGET$(TARGETOS)$(TARGETARCH).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
三. 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.設置一些列路徑變量。主機路徑以HOSTOUT 或HOST_OUT形式,目標機路徑以TARGETOUT 或TARGET*_OUT*形式。
5.根據MAKECMDGOALS,若其中包含dumpvar-%或dumpvar-abs-%,就生成一個以dumpvar-%或dumpvar-abs-%命名的make目標。實現是打印出%所表示的變量的值。這個變量必須要在這之前已經定義了,後一種在前面還打印出當前的路徑。這兩種情況必須要先設置CALLED_FROM_SETUP=true。envsetup.sh的get_build_var和get_abs_build_var()函數就是運用的這個原理打印變量的值。
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=true BUILD_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=true BUILD_SYSTEM=build/core \ make --no-print-directory -C "$T"-f build/core/config.mk dumpvar-abs-$1 }
四. 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:
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(nodefns.mk),設置$1=PRODUCTS,設置$3=$(_product_var_list),_product_var_list是以PRODUCT開頭的變量名。
product.mk inherit-product
將在所有的PRODUCT_xxx變量值後綴加上'@inherit:
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(nodefns.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
五. cleanbuild.mk
1. 定義了add-clean-step函數。有一個入口參數$(1),執行刪除操作的具體shell命令。
一般add-clean-step應當在%/cleanspec.mk腳本中使用,命令會為$(1)定義一個變量保存,變量的名字是INTERNALSTEP.$(_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。分別用來刪除安裝文件和數據文件。
六. 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.prop3.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文件。
七. 模塊下的Android.mk的說明
以camera為例:
LOCAL_PATH:= $(call my-dir)
ifeq ($(USE_CAMERA_STUB),)
USE_CAMERA_STUB:=false
ifneq ($(filter sooner genericsim,$(TARGET_DEVICE)),)
USE_CAMERA_STUB:=true
endif #libcamerastub
endif
ifeq ($(USE_CAMERA_STUB),true)
#
libcamerastub
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
CameraHardwareStub.cpp \
FakeCamera.cpp
LOCAL_MODULE:= libcamerastub
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_CFLAGS += -DSINGLE_PROCESS
endif
LOCAL_SHARED_LIBRARIES:= libui
include $(BUILD_STATIC_LIBRARY)
endif # USE_CAMERA_STUB
#
libcameraservice
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
CameraService.cpp
LOCAL_SHARED_LIBRARIES:= \
libui \
libutils \
libbinder \
libcutils \
libmedia \
libcamera_client \
libsurfaceflinger_client
LOCAL_MODULE:= libcameraservice
LOCAL_CFLAGS +=-DLOG_TAG=\"CameraService\"
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_CFLAGS += -DSINGLE_PROCESS
endif
ifeq ($(USE_CAMERA_STUB), true)
LOCAL_STATIC_LIBRARIES += libcamerastub
LOCAL_CFLAGS += -includeCameraHardwareStub.h
else
LOCAL_SHARED_LIBRARIES += libcamera
endif
include $(BUILD_SHARED_LIBRARY)
1. include $(CLEAR_VARS)
這一步一般都要在文件頭部包含。CLEAR_VARS=build/core/clear_vars.mk,在這個文件裡將所有以LOCAL_開頭的變量置為空,除了LOCAL_PATH.因為每個模快都公用同一個LOCAL_變量,防止幹擾。
2. LOCAL_PATH:=$(call my-dir)
通過調用my-dir函數獲得當前目錄。
3. 設置以LOCAL_開頭的變量
LOCAL_SRC_FILES 需要的源文件,不需要包含它的依賴文件,因為編譯時會自動的添加
LOCAL_C_INCLUDES 一些額外的頭文件路徑
LOCAL_SHARED_LIBRARIES 需要的共享庫
LOCAL_MODULE C,C++ 本模塊的名字,必須是唯一的
LOCAL_PACKAGE_NAME JAVA的LOCAL_MODULE
LOCAL_MODULE_TAGS 模塊標記,一般的取值範圍:debug eng tests optionalsamples shell_ash shell_mksh,默認optional
LOCAL_MODULE_CLASS 這個不用我們自己定義,系統會根據生成模塊類型的不同賦值。取值:APPS,JAVA_LIBRARIES,SHARED_LIBRARIES,STATIC_LIBRARIES,EXECUTABLES
LOCAL_MODULE_PATH 模塊的生成後存放的路徑,不用定義,有默認值
LOCAL_MODULE_SUFFIX 後綴名,不用定義,有默認值(.apk,.jar,.so,.a)
LOCAL_BUILT_MODULE_STEM 編譯目標要生成的文件名,如果我們定義了 LOCAL_BUILT_STEM值就是$(LOCAL_BUILT_STEM)$(LOCAL_MODULE_SUFFIX),否則就是$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)。若要編譯JAVA的庫文件和執行文件會被置為jablib.jar和package.apk。
LOCAL_INSTALLED_MODULE_STEM 定義規則跟LOCAL_BUILT_MODULE_STEM相同,但是不會有設置為單一值的情況。
LOCAL_BUILT_MODULE 編譯目標完整的路徑和文件名
LOCAL_PRELINK_MODULE只有在編譯.so的時候才會有的選項,主要是通過預鏈接的方式來加快程序啟動和執行的速度,如果設置是真的話,那你要在build/core/prelink-linux-arm.map中定義你的庫需要使用的空間,空間不夠的話會報錯
4. include$(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY在config.mk裡有定義,指向相應的.mk文件,根據要生成的模塊的類型,包含相應的文件。
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_KEY_CHAR_MAP := $(BUILD_SYSTEM)/key_char_map.mk
主要分為兩種類型:prebuilt和bin/lib文件。這些.mk文件都包含build/core/base_rule.mk。這個文件的作用如下:
(1). 根據LOCAL_IS_HOST_MODULE,LOCAL_MODULE_CLASS,LOCAL_MODULE這三個變量的值來判斷這個模塊是否是全局唯一的,我們應該使LOCAL_MODULE全局唯一的。
(2). 設置LOCALMODULE_PATH的默認值。LOCAL_MODULE_PATH:=$($(my_prefix)OUT$(use_data)$(LOCALMODULE_CLASS))若my_prefix=TARGET use_data=”” LOCAL_MODULE_CLASS=APPS 則LOCAL_MODULE_PATH=$(TARGET_OUT_APPS)。TARGET_OUT_APPS在envsetup.mk定義TARGET_OUT_APPS=out/target/product/generic/system/app
(3). 設置LOCAL_BUILT_MODULE的默認值。LOCAL_BUILT_MODULE:=$(built_module_path)/$(LOCAL_BUILT_MODULE_STEM),built_module_path就是編譯目標存放的路徑。有兩種路經built_module_path=target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)intermediates/,built_module_path=/target/product/generic/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)intermediates/。以Camera為例:LOCAL_BUILT_MODULE=out/target/product/generic/obj/APPS/Camera_intermediates/Camera.apk。
(4). 設置LOCAL_INSTALLED_MODULE的默認值。LOCAL_INSTALLED_MODULE=$(LOCAL_MODULE_PATH)/$(LOCAL_MODULE_SUBDIR)$(LOCAL_INSTALLED_MODULE_STEM),這裡LOCAL_MODULE_SUBDIR留給我們自己定義一般為空。但是要記得的是當我們設置了它之後,要在每個模塊的最後要將這個值清空,因為默認CLEAR_VARS是不會清空這個值的。以Camera為例:LOCAL_INSTALLED_MODULE=out/target/product/generic/system/app/Camera.apk
(5). 將.aidl和.logtags文件轉化為.java文件,存放在out/target/common/obj /src/,out/target/common/obj/目錄是JAVA的中間文件的存放目錄
(6). 定義.PHONY:$(LOCAL_MODULE)目標規則.拷貝$(LOCAL_BUILT_MODULE)到$(LOCAL_INSTALLED_MODULE),這兩個變量的值前面都有說明。若不想把這個模塊編譯進系統的話,聲明LOCAL_UNINSTALLABLE_MODULE即可(只適用於靜態庫)。在這裡只是拷貝文件,真正的編譯工作是在它的外層.mk文件做的,並把生成的目標文件放在$(LOCAL_BUILT_MODULE)。若是prebuild就不需要編譯了,只是將已經存在的文件做簡單的拷貝工作。當我們要安裝指定的模塊到系統的時候,只要make $(LOCAL_MODULE)就行了。定義cleantarget目標規則,刪除$(LOCAL_BUILT_MODULE),$(LOCAL_INSTALLED_MODULE), $(intermediates)文件或目錄
(7). 定義或添加以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
ALL_MODULE_TAGS
ALL_MODULE_TAGS.$(LOCAL_MODULE_TAGS)
ALL_MODULE_NAME_TAGS
(8). 包含$(BUILD_SYSTEM)/notice_files.mk,這個我沒細看估計是生成本模塊的NOTICE文件