天天看點

android入門-----Android.mk

        做android源碼修改的人,對android.mk并不陌生,它相當與makefile檔案,在源碼環境裡不管是內建第三方庫,還是源碼環境編譯應用等,都離不開這個檔案。具體來說:該檔案是GNU Makefile的一小部分,會被編譯系統解析一次或多次。你可以在每一個Android.mk file中定義一個或多個子產品,你也可以在幾個子產品中使用同一個源代碼檔案。編譯系統為你處理許多細節問題下面就簡單的介紹一下基本用法,紅色标注的是一般都會有了,藍色的是如果有的話就加上的。

1. LOCAL_PATH := $(call my-dir) 

      $(call 目錄,目錄 ….) 目錄引入操作符,如該目錄下有個檔案夾名稱 src ,則可以這樣寫 $(call src) ,那麼就會得到 src 目錄的完整路徑

一個Android.mk file首先必須定義好LOCAL_PATH變量。 這個變量不會被$(CLEAR_VARS) 清除,它用于在開發樹中查找源檔案。在這個例子中,宏函數’my-dir’, 由編譯系統提供,用于傳回目前路徑(即包含Android.mk file 檔案的目錄)。

2. include $( CLEAR_VARS)

CLEAR_VARS 由編譯系統提供(CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk) , 在 build/core/config.mk 定義 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk,  通過include 包含自定義的 .mk 檔案(即是自定義編譯規則)或是引用系統其他的 .mk 檔案(系統定義的編譯規則),指定讓GNU MAKEFILE為你清除許多LOCAL_XXX變量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH 。這是必要的,因為所有的編譯控制檔案都在同一個GNU MAKE執行環境中,所有的變量都是全局的。

3 . LOCAL_MODULE :=  

LOCAL_MODULE變量必須定義,以辨別你在Android.mk檔案中描述的每個子產品。名稱必須是唯一的,而且不包含任何空格。注意編譯系統會自動産生合适的字尾,換句話說,一個被命名為'libbonovosensor'的共享庫子產品,将會生成'libbonovosensor.so'檔案。

4. LOCAL_C_INCLUDES := 

LOCAL_C_INCLUDES 中加入所需要包含的頭檔案路徑

LOCAL_STATIC_LIBRARIES :=

LOCAL_STATIC_LIBRARIES 加入所需要連結的靜态庫 的名稱(譬如libutils),  應該連結到這個子產品的靜态庫清單( 使用 BUILD_STATIC_LIBRARY 生成 ) ,這僅僅對共享庫子產品才有意義。

LOCAL_SHARED_LIBRARIES :=

LOCAL_SHARED_LIBRARIES 中加入所需要連結的動态庫 的名稱,  這個子產品在運作時要依賴的共享庫子產品清單,在連結時需要,在生成檔案時嵌入的相應的資訊。注意:這不會附加列出的子產品到編譯圖,也就是仍然需要在 Application.mk 中把它們添加到程式要求的子產品中。

LOCAL_JAVA_LIBRARIES      加入 jar 包

5 . LOCAL_SRC_FILES  :=

LOCAL_SRC_FILES中加入源檔案路徑(需要編譯的檔案),多個檔案用‘\’ 隔開.  如果編譯目錄子目錄,采用相對路徑,如子目錄/ 檔案名。也可以通過 $(call 目錄 ) ,指明編譯某目錄下所有 .c/.cpp/.java/.S/ .aidl 檔案 . 追加檔案 LOCAL_SRC_FILES += 檔案

LOCAL_CPP_EXTENSION:  這是一個可選變量,用來指定C++ 代碼檔案的擴充名,預設是 '.cpp', 但是你可以改變它

LOCAL_PACKAGE_NAME := Java 應用程式的名字用該變量定義

6、LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib –llog

表示允許列印Log

7.  include $(BUILD_EXECUTABLE)

BUILD_EXECUTABLE 表示以一個可執行程式的方式進行編譯

BUILD_STATIC_LIBRARY 表示編譯一個靜态庫,

BUILD_SHARED_LIBRARY 表示編譯一個共享庫

BUILD_PREBUILT

BUILD_HOST_STATIC_LIBRARY

BUILD_HOST_SHARED_LIBRARY

BUILD_HOST_EXECUTABLE

BUILD_HOST_PREBUILT

BUILD_RAW_STATIC_LIBRARY

BUILD_RAW_EXECUTABLE

BUILD_MULTI_PREBUILT

BUILD_JAVA_LIBRARY

BUILD_PACKAGE

BUILD_DROIDDOC

BUILD_COPY_HEADERS

BUILD_KEY_CHAR_MAP

BUILD_STATIC_JAVA_LIBRARY 編譯靜态 JAVA 庫

BUILD_HOST_JAVA_LIBRARY 編譯本機用的 JAVA 庫

8. TARGET_ARCH:=

目标 CPU 平台的名字 ,  和 android 開放源碼中指定的那樣。如果是arm ,表示要生成 ARM 相容的指令,與 CPU 架構的修訂版無關。

9. TARGET_PLATFORM:= 

Android.mk 解析的時候,目标 Android 平台的名字 .

10. TARGET_ARCH_ABI:=

暫時隻支援兩個value , armeabi 和 armeabi-v7a 。在 現在的版本中一般把這兩個值簡單的定義為 arm , 通過 android  平台内部對它重定義來獲得更好的比對。其他的 ABI 将在以後的 NDK 版本中介紹,它們會有不同的名字。注意所有基于 ARM 的 ABI 都會把 'TARGET_ARCH' 定義成 ‘arm’ , 但是會有不同的 ‘TARGET_ARCH_ABI’ 。

11. TARGET_ABI:=

目标平台和 ABI 的組合,它事實上被定義成

$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI)  ,在想要在真實的裝置中針對一個特别的目标系統進行測試時,會有用。在預設的情況下,它會是 'android-3-arm' 。

12. LOCAL_CFLAGS: =

可選的編譯器選項,在編譯 C 代碼檔案的時候使用。這可能是有用的,指定一個附加的包含路徑 ( 相對于 NDK 的頂層目錄 ) ,宏定義,或者編譯選項。

LOCAL_CXXFLAGS:  與 LOCAL_CFLAGS 相同,針對 C++ 源檔案。

LOCAL_CPPFLAGS:  與 LOCAL_CFLAGS 相同,但是對 C 和 C++ source files 都适用。

13. LOCAL_LDLIBS: =

     譯子產品時要使用的附加的連結器選項。這對于使用‘-l’ 字首傳遞指定庫的名字是有用的。

14. LOCAL_ALLOW_UNDEFINED_SYMBOLS:=

     預設情況下, 在試圖編譯一個共享庫時,任何未定義的引用将導緻一個“ 未定義的符号 ” 錯誤。這對于在源代碼檔案中捕捉錯誤會有很大的幫助。然而,如果因為某些原因,需要不啟動這項檢查,可把這個變量設為 ‘true’ 。注意相應的共享庫可能在運作時加載失敗。 ( 這個一般盡量不要去設為 true) 。

15. LOCAL_ARM_MODE:=

預設情況下,arm 目标二進制會以 thumb 的形式生成 (16 位 ) ,你可以通過設定這個變量為 arm 如果你希望你的 module 是以 32 位指令的形式。 通過設定編譯器操作,優化級别,-O0 表示沒有優化 ,-O1 為預設值, -O3 優化級别最高

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

TARGET_ROOT_OUT :表示根檔案系統。

TARGET_OUT :表示 system 檔案系統。

TARGET_OUT_DATA :表示 data 檔案系統。

17.  LOCAL_PRELINK_MODULE

     Prelink 利用事先連結代替運作時連結的方法來加速共享庫的加載,它不僅可以加快起動速度,還可以減少部分記憶體開銷,是各種 Linux 架構上用于減少程式加載時間、縮短系統啟動時間和加快應用程式啟動的很受歡迎的一個工具。程式運作時的動态連結尤其是重定位 (relocation) 的開銷對于大型系統來說是很大的。動态連結和加載的過程開銷很大,并且在大多數的系統上 , 函數庫并不會常常被更動 , 每次程式被執行時所進行的連結動作都是完全相同的,對于嵌入式系統來說尤其如此。是以,這一過程可以改在運作時之前就可以預先處理好,即花一些時間利用 Prelink 工具對動态共享庫和可執行檔案進行處理,修改這些二進制檔案并加入相應的重定位等資訊,節約了本來在程式啟動時的比較耗時的查詢函數位址等工作,這樣可以減少程式啟動的時間,同時也減少了記憶體的耗用。 Prelink 的這種做法當然也有代價:每次更新動态共享庫時,相關的可執行檔案都需要重新執行一遍 Prelink 才能保證有效,因為新的共享庫中的符号資訊、位址等很可能與原來的已經不同了,這就是為什麼 android framework 代碼一改動,這時候就會導緻相關的應用程式重新被編譯。 這種代價對于嵌入式系統的開發者來說可能稍微帶來一些複雜度,不過好在對使用者來說幾乎是可以忽略的。 預設是需要prlink 的,同時需要在 build/core/prelink-linux-arm.map 中加入

        libhellod.so      0x96000000

這個map檔案好像是制定動态庫的位址的,在前面注釋上面有一些位址範圍的資訊,注意庫與庫之間的間隔數,如果指定不好的話編譯的時候會提示說位址空間沖突的問題。另外,注意排序,這裡要把數大的放到前面去,按照大小降序排序。

以下是幾個常用的模闆:

(1)編譯應用程式的模闆:

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)

(2)編譯靜态庫的模闆:

LOCAL_PATH := $(call my-dir)

 include $(CLEAR_VARS)

 LOCAL_SRC_FILES := \

 main.c

 LOCAL_MODULE:= libtest_static

 #LOCAL_C_INCLUDES :=

 #LOCAL_STATIC_LIBRARIES :=

 #LOCAL_SHARED_LIBRARIES :=

 include $(BUILD_STATIC_LIBRARY)

( 3 )編譯動态庫的模闆:

 LOCAL_PATH := $(call my-dir)

 include $(CLEAR_VARS)

 LOCAL_SRC_FILES := main.c

 LOCAL_MODULE := libtest_shared

 TARGET_PRELINK_MODULES := false

#LOCAL_C_INCLUDES :=

#LOCAL_STATIC_LIBRARIES :=

#LOCAL_SHARED_LIBRARIES :=

include $(BUILD_SHARED_LIBRARY)

( 4 )編譯java應用的模闆:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_PACKAGE_NAME := BonovoDvdPlayer

include $(BUILD_PACKAGE)

# Use the following include to make our test apk.

include $(call all-makefiles-under,$(LOCAL_PATH))