1. 程式人生 > >android makefile 編譯分析及 android.mk分析

android makefile 編譯分析及 android.mk分析

下面是main.mk檔案包含關係,本文件主要說明的就是這些檔案裡到底做了什麼。(這個檔案被根目錄下的makefile檔案包含)

一. main.mk

1.檢查版本號,設定環境變數(BUILD_SYSTEM)和預設的目標。$(MAKE_VERSION) >= 3.81,BUILD_SYSTEM= build/core

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,返回這個模組的目標檔案路徑

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

顯示命令

二. 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。

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.設定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

三. 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()函式就是運用的這個原理列印變數的值。

  1. # Get the exact value of a buildvariable.
  2. function get_build_var()
  3. {
  4. T=$(gettop)
  5. if [ ! "$T" ]; then
  6. 相關推薦

    android makefile 編譯分析 android.mk分析

    下面是main.mk檔案包含關係,本文件主要說明的就是這些檔案裡到底做了什麼。(這個檔案被根目錄下的makefile檔案包含) 一. main.mk 1.檢查版本號,設定環境變數(BUILD_SYSTEM)和預設的目標。$(MAKE_VER

    編譯原理實踐-----詞法分析

    詞法分析 【實驗目的】 通過設計編制除錯一個具體的詞法分析程式,加深對詞法分析原理的理解。並掌握在對程式設計語言源程式進行掃描過程中將其分解為各類單詞的詞法分析方法。掌握對字元進行靈活處理的方法。 程式開始變得複雜起來,可能是大家目前編過的程式中最複雜

    Android編譯apk常見問題

    軟體下載地址 獲取原始碼 獲取dex 將demo.apk修改後綴為demo.zip並解壓。得到以下檔案: 反編譯dex 解壓dex2jar至指定目錄,開啟cmd至dex2jar目錄,執行命令 dex2jar.bat 目錄\classe

    Android基礎知識】Android Studio 編譯 Adb connection Error:遠端主機強迫關閉了一個現有的連線

    AndroidStudio已經出來了很久了,很多小夥伴們都已經轉戰到Android Studio 上了,今天我也試了一試,介面風格、UI編寫都挺吸引人的,但是也遇到了幾個問題。 1. Gradle Build Running ..... 特變慢,慢到人都睡著了,可能是由於國

    presto UI 分析相關原始碼分析

    CLUSTER OVERVIEW RESERVED MEMORY QUERY DETAILS

    典型使用者分析使用者場景分析

    典型使用者1 (1)名字:王鬆 (2)年齡:23 (3)收入:無 (4)代表的使用者在市場上的比例和重要性:不可缺少的使用者 (5)使用這個軟體的典型場景:對自己不需要的二手書進行拍賣 (6)使用本軟體的環境:有網路的地方 (7)工作情況:學生 (8)知識層次和能力:鐵道大學畢業 (9)使用

    熱血傳奇Tile地圖繪製方法分析平滑繪製分析

    眾所周知熱血傳奇的地圖繪製是不平滑的。因為其繪製間隔是以遊戲中的X,Y座標為單位進行繪製間隔。而一個X座標.和Y座標 在遊戲內表示 48,32 個畫素點。    而遊戲中的房屋等元素在我看來更是坑爹。因為房屋這些元素的繪製並不是以左上角為基點進行繪製 而是以左下角。也就意味

    android makefile android mk 分析 1

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

    【Android7.1.2原始碼解析系列】android init目錄下的Android.mk編譯檔案分析

    上一篇文章對於原始碼中的安卓編譯系統文件進行了翻譯,本文就以android當中的init模組作為例子,對其中的Android.mk檔案進行分析,讀者可以在閱讀本文的同時檢視我的譯文:http://blog.csdn.net/class_brick/article/detai

    androidmakefile -- Android.mk 分析

    首先我們來看看android裡makefile的寫法 (1)Android.mk檔案首先需要指定LOCAL_PATH變數,用於查詢原始檔,巨集函式’my-dir’, 由編譯系統提供。由於一般情況下Android.mk和需要編譯的原始檔在同一目錄下,所以定義成如下形式:LOCAL_PATH:=$(call my

    Android 65K問題之Multidex原理分析NoClassDefFoundError的解決方法

    bottom mini ati ... types auto weight right for Android 65K問題相信困惑了不少人,盡管AS的出來能夠通過分dex高速解決65K問題,可是同一時候也easy由於某些代碼沒有打包到MainDex裏

    Android查缺補漏(線程篇)-- AsyncTask的使用原理詳細分析

    catch 返回 rri 理解 ams tee ive lean keyword 本文作者:CodingBlock 文章鏈接:http://www.cnblogs.com/codingblock/p/8515304.html 一、AsyncTask的使用 AsyncT

    Android編譯apk逆向分析

    Android反編譯apk 反編譯、逆向 軟體下載地址 反編譯、逆向 反編譯 高階語言源程式經過 編譯 變成可執行檔案,反編譯就是逆過程。   但是通常不能把可執行檔案變成高階語言原始碼,只能轉換成彙編程式。   計算機

    Android多程序app中Application回撥onCreate()方法被執行多次分析解決

    最近工作中碰到一個問題,在優化app,使用DDMS檢視Application log過程中看到,app啟動了三個程序,一個主程序,兩個附帶的程序。如下圖可看到一個app啟動的三個程序。  自定義Application回撥方法onCreate()被執行了3次。開始不知是何原因。 相

    Android IntentService原始碼理解 HandlerThread構建訊息迴圈機制分析

      前言:前面寫了Handler的原始碼理解,關於Handler在我們Android開發中是到處能見到的非同步通訊方式。那麼,在Android原生裡,有那些也有到了Handler機制的呢?有很多,比如我們今天所要理解分析的IntentService就使用到了Handler。接下來,我們來深入瞭解一下。   

    Android記憶體洩漏問題分析解決方案

    大家新年好,由於工作繁忙原因,有好一段時間沒有更新博文了(當然Github是一直都有更新的),趁著年底有點放假時間,我覺得抽空更新下部落格,總結一下工作中最常見記憶體洩漏問題,也是自己之前踩過的坑,為了讓大家少走彎路,系統全面總結一下記憶體洩漏問題分析原因及尋找解決方案。 概念 首

    android螢幕適配問題分析各種解決方案優缺點分析

    序 從事android開發已有5年之久,專案中遇到的螢幕適配的問題也有n次了,可是有一個很奇怪也很讓人頭疼的現象讓從事多年開發的我很不爽。什麼問題呢,就是“適配虐我千萬遍,我見適配如初見”,真是想說一句fuck,這次我終於堅決的征服掉了她,下面就來具體講解征服她的全過程,一定要

    Android : 跟我學Binder --- (2) AIDL分析手動實現 Android : 跟我學Binder --- (1) 什麼是Binder IPC?為何要使用Binder機制? Android : 跟我學Binder --- (3) 深入程式碼實戰(假裝有連結)

    一、關於Android日常開發中程序間通訊-AIDL   通常Android應用開發中實現程序間通訊用的最多的就是 AIDL,藉助 AIDL 編譯以後的程式碼能幫助我們進一步理解 Binder IPC 的通訊原理。但是無論是從可讀性還是可理解性上來看,編譯器生成的程式碼對開發者並不友好。比如一個 INano

    Android 5.0 Usb除錯攔截分析修改

    當我們除錯安卓機器時,第一次插上usb線,會彈出一個授權的對話方塊,(前提是打開了usb除錯功能)點選確認,才會允許除錯. 如果我們想機器預設就可以除錯該怎麼做呢? 如果我們想動態攔截,需要使用者輸入帳號密碼,才確認是否可以除錯,該怎麼做呢?或者只是單純的想改變這個不好看

    Android記憶體洩漏分析除錯

     尊重原創作者,轉載請註明出處: 首先了解一下dalvik的Garbage Collection: 如上圖所示,GC會選擇一些它瞭解還存活的物件作為記憶體遍歷的根節點(GC Roots),比方說thread stack中的變數,JNI中的全域性變數,zygote中