Android源碼分析(一)-----如何快速掌握Android編譯文件


一 : Android.mk文件概述

主要向編譯系統指定相應的編譯規則。會被解析一次或多次。因此盡量減少源碼中聲明變量,因為這些變量可能會被多次定義從而影響到后面的解析。這個文件的語法會把源代碼組織成模塊,每個模塊屬於下列類型之一:

- APK程序:一般的Android程序,編譯打包生成apk文件。
- JAVA庫:java類庫,編譯打包生成jar包文件。
- C\C++應用程序:可執行的C/C++應用程序。
- C\C++靜態庫:編譯生產C/C++靜態庫,並打包成.a文件。
- C\C++共享庫:編譯生成共享庫,並打包成.so文件,有且只有共享庫才能被安裝/復制到APK包中。

二 : 系統變量####

- LOCAL_PATH:這個變量用於給出當前文件的路徑,必須在Android.mk的開頭定義,可以這樣使用LOCAL_PATH := $(call my-dir),這樣這個變量不會被$(CLEAR_VARS)清除,因為每個Android.mk只需要定義一次(即使一個文件中定義了多個模塊的情況下)。
- LOCAL_SRC_FILES:當前模塊包含的所有源代碼文件。
- LOCAL_MODULE:當前模塊的名稱,這個名稱應當是唯一的,並且不能包含空格。模塊間的依賴關系就是通過這個名稱來引用的。
- LOCAL_MODULE_CLASS:標識所編譯模塊最后放置的位置。ETC表示放置在/system/etc.目錄下,APPS表示放置在/system/app目錄下,SHARED_LIBRARIES表示放置在/system/lib目錄下。如果具體指定,則編譯的模塊不會放到編譯系統中,最后會在out對應product的obj目錄下的對應目錄中。
- LOCAL_SRC_FILES:這是要編譯的源代碼文件列表。只要列出要傳遞給編譯器的文件即可,編譯系統會自動計算依賴關系。源代碼文件路徑都是相相對於LOCAL_PATH的,因此可以使用相對路徑進行描述。
- LOCAL_JAVA_LIBRARIES:當前模塊依賴的Java共享庫,也叫Java動態庫。例如framework.jar包。
- LOCAL_STATIC_JAVA_LIBRARIES:當前模塊依賴的Java靜態庫,在Android里,導入的jar包和引用的第三方工程都屬於Java靜態庫。
- LOCAL_STATIC_LIBRARIES:當前模塊在運行時依賴的靜態庫的名稱。
- LOCAL_SHARED_LIBRARIES:當前模塊在運行時依賴的動態庫的名稱。
- LOCAL_C_INCLUDES:c或c++語言需要的頭文件的路徑。
- LOCAL_CFLAGS:提供給C/C++編譯器的額外編譯參數。
- LOCAL_PACKAGE_NAME:當前APK應用的名稱。
- LOCAL_CERTIFICATE:簽署當前應用的證書名稱。
- LOCAL_MODULE_TAGS:當前模塊所包含的標簽,一個模塊可以包含多個標簽。標簽的值可能是eng、user、debug、development、optional。其中,optional是默認標簽。
- LOCAL_DEX_PREOPT:apk的odex優化開關,默認是false。

三 : mk文件模板####

  • 編譯C/C++應用程序的模板:
     #Test Exe
     LOCAL_PATH := $(call my-dir)
     include $(CLEAR_VARS)
     LOCAL_SRC_FILES:= main.c
     LOCAL_MODULE:= test_exe
     #LOCAL_C_INCLUDES :=
     #LOCAL_STATIC_LIBRARIES :=
     #LOCAL_SHARED_LIBRARIES :=
     include $(BUILD_EXECUTABLE)

BUILD_EXECUTABLE表示以一個可執行程序的方式進行編譯。補充說明:include $(BUILD_PACKAGE)則是編譯出一個apk,include $(BUILD_STATIC_JAVA_LIBRARY)則是編譯出jar包。

  • 編譯靜態庫的模板:
    `#Test Static Lib
     LOCAL_PATH := $(call my-dir)
     include $(CLEAR_VARS)
     LOCAL_SRC_FILES:= /
               helloworld.c
     LOCAL_MODULE:= libtest_static
     #LOCAL_C_INCLUDES :=
     #LOCAL_STATIC_LIBRARIES :=
     #LOCAL_SHARED_LIBRARIES :=
     include $(BUILD_STATIC_LIBRARY)

一般的和上面相似,BUILD_STATIC_LIBRARY表示編譯一個靜態庫.a文件。靜態庫不會復制到的APK包中,但是能夠用於編譯共享庫。

  • 編譯動態庫的模板:
     #Test Shared Lib
     LOCAL_PATH := $(call my-dir)
     include $(CLEAR_VARS)
     LOCAL_SRC_FILES:= /
               helloworld.c
     LOCAL_MODULE:= libtest_shared
     TARGET_PRELINK_MODULES := false
     #LOCAL_C_INCLUDES :=
     #LOCAL_STATIC_LIBRARIES :=
     #LOCAL_SHARED_LIBRARIES :=
      include $(BUILD_SHARED_LIBRARY)

一般的和上面相似,BUILD_SHARED_LIBRARY表示編譯一個動態庫。
以上三者的生成結果分別在如下,generic依具體target會變:
out/target/product/generic/obj/EXECUTABLE
out/target/product/generic/obj/STATIC_LIBRARY
out/target/product/generic/obj/SHARED_LIBRARY

每個模塊的目標文件夾分別為:
可執行程序:XXX_intermediates
靜態庫: XXX_static_intermediates
動態庫: XXX_shared_intermediates

另外,在Android.mk文件中,還可以指定最后的目標安裝路徑,用LOCAL_MODULE_PATH和LOCAL_UNSTRIPPED_PATH來指定。不同的文件系統路徑用以下的宏進行選擇:

- TARGET_ROOT_OUT:表示根文件系統out/target/product/xxxxx/root。
- TARGET_OUT:表示system文件系統out/target/product/xxxx/system。
- TARGET_OUT_DATA:表示data文件系統out/target/product/xxxx/data。
- TARGET_OUT_SHARED_LIBRARIES:表示out/target/product/xxxx/system/lib
- TARGET_OUT_APPS:表示out/target/product/xxxx/system/app
- ANDROID_PRODUCT_OUT:out/target/product/xxxx/
- TARGET_OUT_JAVA_LIBRARIES:out/target/product/xxxx/system/framework

四 : 常用函數####

- $(call my-dir):獲取當前文件夾的路徑。
- $(call all-java-files-under, <src>):獲取指定目錄下的所有java文件。
- $(call all-c-files-under, <src>):獲取指定目錄下的所有c文件。
- $(call all-Iaidl-files-under, <src>):獲取指定目錄下的所有AIDL文件。
- $(call all-makefiles-under, <folder>):獲取指定目錄下的所有Make文件。
- $(call intermediates-dir-for, <class>, <app_name>, <host or target>, <common?>):獲取Build輸入的目標文件夾路徑。

五 : Settings模塊Android.mk文件分析####

# 當前文件的路徑
LOCAL_PATH:= $(call my-dir)
# 清除變量
include $(CLEAR_VARS)

# 列舉所有需要編譯的源文件
LOCAL_SRC_FILES := \
        $(call all-logtags-files-under, src)

# 模塊名稱--唯一
LOCAL_MODULE := settings-logtags

#依賴的java靜態庫
include $(BUILD_STATIC_JAVA_LIBRARY)

# Build the Settings APK
include $(CLEAR_VARS)

#依賴的java庫
LOCAL_JAVA_LIBRARIES := bouncycastle core-oj telephony-common ims-common
#依賴的jar包,包括系統的和第三方的(放在libs目錄)jar包
LOCAL_STATIC_JAVA_LIBRARIES := \
    android-support-v4 \
    android-support-v13 \
    android-support-v7-recyclerview \
    android-support-v7-preference \
    android-support-v7-appcompat \
    android-support-v14-preference \
    jsr305 \
    settings-logtags
    
#user: 指該模塊只在user版本下才編譯
#eng: 指該模塊只在eng版本下才編譯
#tests: 指該模塊只在tests版本下才編譯
#optional:指該模塊在所有版本下都編譯
LOCAL_MODULE_TAGS := optional

#列舉所有需要編譯的源文件
LOCAL_SRC_FILES := \
        $(call all-java-files-under, src)

#列舉所有需要的資源文件夾
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
    frameworks/support/v7/preference/res \
    frameworks/support/v14/preference/res \
    frameworks/support/v7/appcompat/res \
    frameworks/support/v7/recyclerview/res

#打包成apk的名稱--包名
LOCAL_PACKAGE_NAME := Settings

#用於指定簽名時使用的KEY
LOCAL_CERTIFICATE := platform

#編譯后在ROM中的安裝位置
#true,安裝位置為system/priv-app
#false,安裝位置為system/app
LOCAL_PRIVILEGED_MODULE := true

#混淆文件名
LOCAL_PROGUARD_FLAG_FILES := proguard.flags

LOCAL_AAPT_FLAGS := --auto-add-overlay \
    --extra-packages android.support.v7.preference:android.support.v14.preference:android.support.v17.preference:android.support.v7.appcompat:android.support.v7.recyclerview

ifneq ($(INCREMENTAL_BUILDS),)
    LOCAL_PROGUARD_ENABLED := disabled
    LOCAL_JACK_ENABLED := incremental
    LOCAL_DX_FLAGS := --multi-dex
    LOCAL_JACK_FLAGS := --multi-dex native
endif

#包含的其他mk文件
include frameworks/opt/setupwizard/library/common-full-support.mk
include frameworks/base/packages/SettingsLib/common.mk

#打包成apk
include $(BUILD_PACKAGE)

# Use the following include to make our test apk.
ifeq (,$(ONE_SHOT_MAKEFILE))
#獲取當前目錄下的所有Make文件
include $(call all-makefiles-under,$(LOCAL_PATH))
endif


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM