Android Makefile 編譯過程分析

狂熱份子的部落格發表於2015-03-21

本文比較詳細地介紹了Android Make系統,通過手動Makefile編譯Android來提高對Android系統的瞭解,以下是原文:

android make 系統

  • arch
  • board
  • device
  • product

Android.mk中的定義變數

  • include $(CLEAR_VARS)

它對應的是在./build/core/config.mk中的CLEAR_VARS:=$(BUILD_SYSTEM)/clear_vars.mk

  • include $(BUILD_PACKAGE)

它對應的是在./build/core/config.mk中的BUILD_PACKAGE:=$(BUILD_SYSTEM)/package.mk

  • 其它以此類推

main.mk中的模組

.PHONY:checkbuilt
.PHONY:prebuilt
.PHONY: files
.PHONY: ramdisk
.PHONY: systemimage
.PHONY: userdataimage
.PHONY: bootimage
.PHONY: recoveryimage
.PHONY: droidcore
.PHONY: apps_only
.PHONY: sdk
.PHONY: clean
.PHONY: clobber
.PHONY: modules
.PHONY: showcommands

makefile的檔案結構

LOCAL_PATH:=$(call my-dir) //獲取當前目錄
	#include $(CLEAR_VARS) //make系統為子模組定義了很多的私有變數,這個呼叫是為了初始化所有的私有變數
	...
	//裡面的內容根據不同的需要會出現不同的LOCAL變數
	...
	#include $(BUILD_XXX) //執行編譯任務

編譯apk

LOCAL_SRC_FILES:=$(call all-subdir-java-files)
LOCAL_PACKAGE_NAME:=packageName
include $(BUILD_PACKAGE)

編譯依賴靜態java庫的應用程式

LOCAL_STATIC_JAVA_LIBRARIES:=static-library
LOCAL_SRC_FILES:=$(call all-subdir-java-files)
LOCAL_PACKAGE_NAME:=packageName
include $(BUILD_PACKAGE)

編譯一個需要用平臺key簽名的應用程式

LOCAL_SRC_FILES:=$(call all-subdir-java-files)
LOCAL_PACKAGE_NAME:=packageName
LOCAL_CERTIFICATE:=platform
include $(BUILD_PACKAGE)

編譯一個需要特定key的應用程式

LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := LocalPackage
LOCAL_CERTIFICATE := vendor/example/certs/app
include $(BUILD_PACKAGE)

新增一個預編譯應用程式

LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE := LocalModuleName
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_MODULE := sample
include $(BUILD_STATIC_JAVA_LIBRARY)

常用的mk分類

  • Android.mk 用來編譯模組或者apk的,module對應native code,package對應於java
  • AndroidProducts.mk 設定product,設定系統包含了那些應用target_-.mk,host_-.mk,-.mk 針對不同的系統和CPU架框進行設定 +BoardConfig.mk 設定主機板用的,比如driver的選擇
  • ./build/core/Makefile 定義了image是如何生成的
  • frameworks/base/core/java 擴充套件SDK時,可以向裡面新增自己的類

make引數

  • . build/envsetup.sh 可以設定環境,執行之後會支援mm命令,使make支援只編譯一個模組
    使用者也可以通過mm來編譯指定模組,或者通過make clean-module_name來刪除指定模組。
  • make ONE_SHOT_MAKEFILE=

通過CREATE_MODULE_INFO_FILE,build system會將所有的模組資訊列在$(PRODUCT_OUT)/module-info.txt中

  • make CREATE_MODULE_INFO_FILE=true 產生單個的image檔案,用以早期的硬體測試

HOST_BUILD_TYPE 和 TARGET_BUILD_TYPE 用來設定是debug還是release,debug的帶有除錯資訊,這兩個引數也可以在 buildspec.mk中進行設定以防止在別處被重複指定

  • 其它的一些變數
LOCAL_AAPT_FLAGS
LOCAL_ACP_UNAVAILABL
LOCAL_ADDITIONAL_JAVA_DIR
LOCAL_AIDL_INCLUDES
LOCAL_ALLOW_UNDEFINED_SYMBOLS
LOCAL_ARM_MODE
LOCAL_ASFLAGS
LOCAL_ASSET_DIR
LOCAL_ASSET_FILES 在與BUILD_PACKAGE一起時有效,表示資原始檔
LOCAL_BUILT_MODULE_STEM
LOCAL_C_INCLUDES 用來指定外面的標頭檔案路徑
LOCAL_CC 可以指定C編譯器
LOCAL_JAR_MANIFEST
LOCAL_JARJAR_RULES
LOCAL_JAR_PATH
LOCAL_SHARED_LIBRARIES 可連結動態庫
LOCAL_SRC_FILES 編譯原始檔
LOCAL_STATIC_JAVA_LIBRARIES
LOCAL_STATIC_LIBRARIES 可連結靜態庫
LOCAL_UNINSTALLABLE_MODULE
LOCAL_WHOLE_STATIC_LIBRARIES 禁止在連線時刪除庫中的無用程式碼
LOCAL_FORCE_STATIC_EXECUTABLE 如果編譯的可執行程式要進行靜態連結(執行時不依賴於任何動態庫)
LOCAL_JAVA_LIBRARIES 編譯java應用程式和庫的時候指定包含的java類庫,目前有core和framework兩種
                     多數情況下定義成:LOCAL_JAVA_LIBRARIES := core framework
                     注意LOCAL_JAVA_LIBRARIES不是必須的,而且編譯APK時不允許定義(系統會自動新增)
  • envsetup.mk會讀取由envsetup.sh寫入環境變數中的一些變數來配置 編譯過程中的輸出目錄
  • config.mk裡面定義了各種module所需要的工具,以及如何來編譯各個模組
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.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
以上的*.mk中都包含了base_rules.mk
  • products設定

./build/target/product/AndroidProducts.mk

  • module設定

native code和java的一些通用方法都在./build/core/definitions.mk中

BUILD_SHARE_xxx等變數在./build/core/config.mk中

  • Board設定

./build/target/board/$(TARGET_DEVICE)/BoardConfig.mk ./vendor/*/$(TARGET_DEVICE)/BoardConfig.mk

  • rules相關

與 LOCAL_MODULE_TAGS相關的定義

include $(BUILD_STATIC_LIBRARY) 編譯成靜態庫
include $(BUILD_SHARED_LIBRARY) 編譯成動態庫。
include $(BUILD_EXECUTABLE) 編譯成可執行程式

常用函式

call my-dir
call all-subdir-java-files
call all-java-files-under
call all-makefiles-under,$(LOCAL_PATH)
call all-clean-step
call import-module,android/native_app_glue
call inherit-product,xxx.mk
call inherit-product-if-exists
call device-test
call include-path-for,libpagemap
call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)
call _add-charger-image,$(_img)
call libfilterfw-all-java-files-under,$(1)
call libfilterfw_to_document,$(LOCAL_PATH)
call intermediates-dir-for,EXECUTABLES,$(LOCAL_MODULE,true)
call all-named-subdir-makefiles,$(legacy_modules)
call RM;call MKDIR
call emugl-begin-host-shared-library,libEGL_translator
call emugl-import,libOpenglOsUtils
call emugl-end-module
call emugl-export,LDLIBS,-lGL
cal emugl-export,LDFLAGS,$(GL_COMMON_LINKER_FLAGS)
call emugl-set-shared-library-subpath,hw
call emugl-export,C_INCLUDES,$(intermediates)
call all-makefiles-under,$(LOCAL_PATH) 這個和下面的區別還不清楚
call all-subdis-makefiles
這個是通常出現在整個makefile的尾部,以實現遞迴呼叫子目錄中的makefile,使整個make系統成為一個樹狀結構

相關文章