Android.mk文件語法規範

序言:
————-
android

此文檔旨在描述Android.mk文件的語法,Android.mk文件爲Android NDK(原生開發)描述了你C/C++源文件。
爲了明白下面的內容,你必須已經閱讀了docs/OVERVIEW.TXT的內容,它解釋了Android.mk文件扮演的角色
和用途。
架構

概述:
———

寫一個Android.mk文件是爲了向生成系統描述你的源代碼。更明確的說: app

- 這個文件其實是GNU Make文件的一小片斷,它會被生成系統解析一次或屢次。
所以,你應該在Android.mk裏儘可能少地聲明變量,而不要誤覺得在解析的過程當中
沒有任何東西被定義。
函數

- 該文件的語法的明的人爲了讓你能將你的源代碼組織爲組件(module).一個組件指的是下面的一項:
- 一個靜態庫(static library)
- 一個共享庫(shared library) 工具


只有一個動態庫會被安裝/拷貝至你的application package中。可是靜態庫可用來
生成動態庫。
學習

你能夠在每一個Android.mk文件定義一個或多個組件,而且我能夠在幾個組件中使用
相同的源文件。
- 生成系統爲你處理了一些瑣碎之事。好比,在你的Android.mk裏,你不需要列出頭文件或
列出生成的文件之間的明確認依賴關係。NDK生成系統會爲你自動生成。
測試

這也意味着,當更新至新的NDK版本時,你能獲得新的工具鏈/平臺支持(toolchain/platform support)
的好處,而無須修改你的android.mk文件。 ui

須要注意的是,此語法與徹底開源的Android平臺的Android.mk文件的語法很是類似,但使用它們的
生成系統的實現不一樣,這個爲了讓開發者能更容易的複用「外部」庫的源代碼。
簡單例子:
—————
this

 

在詳細描述語法以前,讓咱們探究一個簡單的「hello JNI」例子,它的文件位於:
apps/hello-jni/projec
spa

這裏,咱們能看到:

- 放有Java源文件的src文件夾。

- 放有本地源文件,即jni/hello-jni.c的jni文件夾。

    這個源文件實現一個簡單的共享庫。這個共享庫有一個本地方法(native method),它將一個字符串
返回給虛擬機應用(著:即Java層應用程序)

- jni/Anroid.mk文件爲NDK生成系統描述了這個共享庫。它的內容爲:

   ———- cut here ——————
LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

   include $(BUILD_SHARED_LIBRARY)
———- cut here ——————

如今,讓咱們逐行解釋:

LOCAL_PATH := $(call my-dir)

每一個Android.mk文件都必須以定義LOCAL_PATH變量開始。其目的是爲了定位源文件的位置。在這個例子,
生成系統提供的宏函數(macro function)‘my-dir’用來返回當前路徑(即放有Android.mk文件的文件夾)

include $(CLEAR_VARS)

CLEAR_VARS變量是生成系統提供的,它指向一個特殊的GNU Makefile.這個Makefile將會爲你自動清除
許多名爲LOCAL_XXX的變量(好比:LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIES,等),
但LOCAL_PATH是例外,它不會被清除。這些變量的清除是必須的,由於全部的控制文件是在單一的GNU make
執行環境中解析的,在這裏全部的變量都是全局的。

LOCAL_MODULE := hello-jni

爲了在你的Android.mk文件標識每一個組件,必須定義LOCAL_MODULE變量。這個名字必需要惟一的而且不能
包含空格。注意:生成系統會自動地爲相應生成的文件加入前綴或後綴。換言之,一個名叫foo的共享庫組件
會生成’libfoo.so’.

重要注意事項:
若是你把組件取名爲‘libfoo’,生成系統將不會加上‘lib’前綴,仍是
生成libfoo.so。這是爲了支持源於Android平臺源代碼的Android.mk文件。

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SRC_FILES變量必須包含一系列將被構建和組合成組件的C/C++源文件。注意:你
不須要列出頭文件或include文件,由於生成系統會爲你自動計算出源文件的依賴關係。
僅僅列出那些將直接傳給編譯器的源文件足矣。

注意,默認的C++源文件的擴展名是‘.cpp’。但你能夠經過定義LOCAL_DEFAULT_EXTENSION
來指定一個擴展名。別忘了擴展名開始的那一點(好比,‘.cxx’,能行,但‘cxx’不行)。

include $(BUILD_SHARED_LIBRARY)

生成系統提供的BUIL_SHARED_LIBRARY變量指向一個GNU Makefile腳本,這個腳本主管
收集在最近的一次#include $(CLEAR_VARS)(著:即清除’本地’變量)以後你所定義的
LOCAL_XXX變量的信息,並決定生成什麼,如何準確的生成。BUILD_STATIC_LIBRARY可
生成一個靜態庫。

There are more complex examples under apps/, with commented
Android.mk files that you can look at.
在apps文件下有一些複雜點的例子,它帶有註釋的Android.mk文件以供你學習。

 

參考:
———–

如下列出你在Android.mk裏應該依賴或定義的變量。你能定義其它變量,但下列的變量名是
由NDK生成系統保留的。

- 以LOCAL_ 開頭的變量名 (好比,LOCAL_MODULE)
- 以PRIVATE_ ,NDK_ 或 APP_ (內部使用)開頭的量名
_ 小寫字母變量名(內部使用,如 my-dir).

若是你須要在Android.mk裏定義方便本身使用的變量名,咱們建議使用MY_ 前綴,
以下面一個簡單例子:

   ———- cut here ——————
MY_SOURCES := foo.c
ifneq ($(MY_CONFIG_BAR),)
MY_SOURCES += bar.c
endif

    LOCAL_SRC_FILES += $(MY_SOURCES)
———- cut here ——————

So, here we go:
NDK提供的變量:
- – - – - – - – - – - – - -

下列的這些GNU Make變量是在你的Android.mk被解析以前,就被生成系統事先定義
的了.注意,在某些狀況下,NDK可能會屢次解析你的Android.mk,每次對其中一些變量的
定義不一樣。

CLEAR_VARS
指向一個生成腳本,這個腳本取消幾乎全部LOCAL_XXX變量的定義(譯者注:除了LOCAL_PATH)。
在開始描述一個新的組件以前,你必須include這個腳本,e.g.:

include $(CLEAR_VARS)

BUILD_SHARED_LIBRARY
指向一個生成腳本,這個腳本經過LOCAL_XXX變量收集關於組件的信息,並決定如何
根據你列出來的源文件生成目標分享庫。注意,在include這個腳本文件以前你必須
至少已經定義了LOCAL_MODULE和LOCAL_SRC_FILES。用法舉例:
include $(BUILD_SHARED_LIBRARY)

注意,這會生成一個名爲 lib$(LOCAL_MODULE).so的文件。(譯者注:$(BUILD_SHARED_MODULE)爲文件名)

BUILD_STATIC_LIBRARY
與BUILD_SHARED_LIBRARY相似,但用來生成目標靜態庫。靜態庫不會被拷貝至你的
project/packages文件夾下,但可用來生成分享庫(參考 LOCAL_STATIC_LIBRARIES
和LOCAL_STATIC_WHOLE_LIBRARIES,將在後面描述)
用法示例:

include $(BUILD_STATIC_LIBRARY)

    注意,這會生成一個方件名叫lib$(LOCAL_MODULE).a

TARGET_ARCH
目標CPU的名字,在完整的Android開源代碼的生成中指定。對於基於ARM兼容的CPU,
它被指定爲’arm’,與CPU架構的修訂無關。

TARGET_PLATFORM
當解析該Android.mk文件時用它來指定Andoid目標平臺的名稱。譬如,’android-3′與
Android 1.5系統鏡像相對應。若要了解全部的平臺名稱及其相應的Android系統鏡像,
請閱讀docs/STABLE-APIS.TXT


TARGET_ARCH_ABI
當解析該Android.mk時,CPU+ABI的名稱。目前只有一個值。
(譯者注:ABI,Application Binary Interface,二進制應用程序接口)

       armeabi    For Armv5TE

armeabi    指定Armv5TE

注意:到NDK 1.6_r1爲止,僅簡單的定義這個變量爲’arm’。但爲了更好地配合
Android平臺的內部使用,該值已重定義。

關於ABI與相應的兼容問題更多詳情,請閱讀docs/CPU-ARCH-ABIS.TXT

    將來的NDK版本將會引入其它的平臺的ABI並會有不一樣的名稱。注意,全部基於ARM的ABI會
使TARGET_ARCH定義爲’arm’,但可能擁有不一樣的TARGET_ARCH_ABI

TARGET_ABI
目標平臺與abi的鏈接,它實際上被定義爲 $(TARGET_PLATFORM)-$(TARGET_ARCH_ABI),
當你想在一個真實的裝置上測試特定的目標系統鏡像時,它就頗有用了。

默認下,它的值爲’android-3-armeabi’

(在Android NDK 1.6_r1及以前的版本,它的默認值爲’android-3-arm’)


NDK提供的宏函數:
—————————-

如下是一些GNU Make的宏‘函數’,必須經過這樣的形式調用:’$(call <function>)’。
函數返回文本信息。

my-dir
返回放置當前Android.mk的文件夾相對於NDK生成系統根目錄的路徑。可用來
在Android.mk的開始處定義LOCAL_PATH的值:

LOCAL_PATH := $(call my-dir)      


all-subdir-makefiles
返回‘my-dir’子目錄下的全部Android.mk。好比,代碼的結構以下:
sources/foo/Android.mk
sources/foo/lib1/Android.mk
sources/foo/lib2/Android.mk

若是sources/foo/Android.mk裏有這樣一行:

include $(call all-subdir-makefiles)

那麼,它將會自動地includesources/foo/lib1/Android.mk和sources/foo/lib2/Android.mk

這個函數能將深層嵌套的代碼文件夾提供給生成系統。注意,默認狀況下,NDK僅在
source/*/Android.mk裏尋找文件。


this-makefile
返回當前Makefile(譯者注:指的應該是GNU Makefile)的路徑(即,這個函數是在哪裏調用的)

parent-makefile
返回在列入樹(inclusion tree)中的父makefile的路徑。
即,包含當前makefile的那個makefile的路徑。  

grand-parent-makefile
猜猜看…(譯者注:原文爲Guess what…)

組件描述相關的變量:
- – - – - – - – - -

如下的變量是用來向生成系統描述你的組件的。你應該在’include $(CLEAR_VARS)’
和’include $(BUILD_XXXXX)’之間定義其中的一些變量。正如在前面所說的,$(CLEAR_VARS)
是一個將會取消全部這些變量的腳本,除非在對變量的描述時有顯式的說明。


LOCAL_PATH
這個變量用來設置當前文件的路徑。你必須在Android.mk的開始處定義它,好比:

LOCAL_PATH := $(call my-dir)

這個變量不會被$(CLEAR_VARS)消除,因此每一個Android.mk僅需一個定義(以防你在
同一個文件裏定義幾個組件)。

LOCAL_MODULE
定義組件的名稱。對於全部的組件名,它必須是惟一,且不能包含空格。
在include $(BUILD_XXX)以前你必須定義它。

這個組件名決定生成的文件(譯者注:即庫名)。好比,lib<foo>,即這個組件的名稱
爲<foo>。可是在你的NDK生成文件(不論是Android.mk仍是Application.mk)中
你只能經過‘正常’的名稱(如,<foo>)來引用其它的組件。

LOCAL_SRC_FILES
用它來定義全部用來生成組件的源文件。僅須列出傳給編譯器的文件,由於
生成系統會自動地計算它們的相互依賴關係。

注意,全部文件名都是相對於LOCAL_PATH的,你能夠用到路徑組件(path component)
如:
LOCAL_SRC_FILES := foo.c \ (譯者注:‘\’爲鏈接符)
toto/bar.c


LOCAL_CPP_EXTENSION
這是一個可選的變量,可用它來指明C++源文件的擴展名。默認狀況下是’.cpp’,
但你能夠改變它。好比:

LOCAL_CPP_EXTENSION := .cxx

LOCAL_C_INCLUDES
一個相對於相對於NDK*根*目錄可選的路徑名單,當編譯全部的源文件(C,C++和彙編)時,
它將被添加進include搜索路徑。例如:

LOCAL_C_INCLUDES := sources/foo

或者甚至:

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../foo
LOCAL_CFLAGS
一個可選的編譯標記集,在生成C與C++源文件時,將解析它。

對指定額外的宏定義或編譯選項頗有用。

重要:不要試圖改變你Android.mk裏的optimization/debuggin level,經過
在你的Android.mk裏指定合適的信息,它將被自動處理,並使NDK生成
調試時可用的有用的數據文件。

注意:在android-ndk-1.5_r1,相應的標記(flags)只適用於C源文件,對C++
源文件並不適用。爲了適用於完整的Android生成系統的特性,已做了修
正。(如今,你可使用LOCAL_CPPFLAGS爲C++文件指定標記)

LOCAL_CXXFLAGS
LOCAL_CPPFLAGS的別名。注意,不建議使用這個變量,由於在將來的NDK版本中,
它可能會消失。

LOCAL_CPPFLAGS
一個可選的編譯標記集,*僅*在生成C++源文件時解析它。在編譯器的命令行裏
它將在LOCAL_CFLAGS以後出現。

    注意:在android-ndk-1.5_r1,相應的標記(flags)適用於C與C++源文件。
爲了適用於完整的Android生成系統的特性,已做了修
正。(如今,你可使用LOCAL_CFLAGS爲C和C++源文件指定標記)

LOCAL_STATIC_LIBRARIES
一份static libraries組件的名單(以BUILD_STATIC_LIBRARY的方式生成),它將被
鏈接到欲生成的組件上。這僅在生成shared library組件時有意義。(譯者注:將指定
的一個或多個static library module轉化爲一個shared library module)

LOCAL_SHARED_LIBRARIES
一份該組件在運行期依賴於它的shared libraries *組件*。在鏈接時間(link time)裏
與及爲該生成的文件嵌入相應的信息都要用到它。

    注意,它並不將這份組件名單添加入生成圖表(build graph)。即,在你的Android.mk
裏,你仍應該將它們加入到你的應用程序要求的組件。

LOCAL_LDLIBS
一份能在生成你的組件時用到的額外的鏈接器標記(linkerflags)的名單。在傳遞
有「-l」前綴的特殊系統庫的名稱時頗有用。好比,下面的語句會告訴鏈接器在裝載
時間(load time)裏生成鏈接到/system/lib/libz.so的組件。

      LOCAL_LDLIBS := -lz

    若想知道在這個NDK版本能夠鏈接哪些暴露的系統庫(exposed system libraries),
請參見docs/STABLE-APIS。

LOCAL_ALLOW_UNDEFINED_SYMBOLS
缺省值狀況下,當嘗試生成一個shared library遇到沒有定義的引用時,會致使「undefined
symbol」error。這對在你的源代碼裏捕捉bugs有很大的幫助。

可是,由於一些緣由你需要disable這個檢查,將這個變量設置爲’true’。注意,相應
的shared library可能在運行期裝載失敗。

LOCAL_ARM_MODE
缺省值狀況下,ARM目標二進制將會以‘thumb’模式生成,這時每一個指令都是16-bit寬的。
若是你想強迫組件的object文件以‘arm’(32位的指令)的模式生成,你能夠將這個變量
定義爲’arm’。即:

      LOCAL_ARM_MODE := arm

    注意,你也能夠經過將‘.arm’後綴添加到源文件名字的後面指示生成系統將指定的
源文件以arm模式生成。例如:

       LOCAL_SRC_FILES := foo.c bar.c.arm

    告訴生成系統老是以arm模式編譯‘bar.c’,但根據LOCAL_ARM_MODE的值生成foo.c

    注意:在你的Application.mk裏將APP_OPTIM設置爲’debug’,這也會強迫生成ARM二進制
代碼。這是由於工具鏈的調度器有bugs,它對thumb碼的處理不是很好。

轉載自:http://apps.hi.baidu.com/share/detail/15447104

相關文章
相關標籤/搜索