Android.mk文件語法說明
譯者:ChrixLee 2010.5.12 序言: ------------- 此文檔旨在描述Android.mk文件的語法,,Android.mk文件為Android NDK(原生開發(fā))描述了你C/C++源文件,。 為了明白下面的內(nèi)容,你必須已經(jīng)閱讀了docs/OVERVIEW.TXT的內(nèi)容,,它解釋了Android.mk文件扮演的角色 和用途,。 概述: --------- 寫一個(gè)Android.mk文件是為了向生成系統(tǒng)描述你的源代碼。更明確的說: - 這個(gè)文件實(shí)際上是GNU Make文件的一小片段,,它會(huì)被生成系統(tǒng)解析一次或多次,。 因此,你應(yīng)該在Android.mk里盡量少地聲明變量,,而不要誤以為在解析的過程中 沒有任何東西被定義,。 - 該文件的語法的明的人為了讓你能將你的源代碼組織為組件(module).一個(gè)組件指的是下面的一項(xiàng): - 一個(gè)靜態(tài)庫(static library) - 一個(gè)共享庫(shared library) 只有一個(gè)動(dòng)態(tài)庫會(huì)被安裝/拷貝至你的application package中,。但是靜態(tài)庫可用來 生成動(dòng)態(tài)庫。 你可以在每個(gè)Android.mk文件定義一個(gè)或多個(gè)組件,,并且我可以在幾個(gè)組件中使用 相同的源文件,。 - 生成系統(tǒng)為你處理了一些瑣碎之事。比如,,在你的Android.mk里,,你不須要列出頭文件或 列出生成的文件之間的明確認(rèn)依賴關(guān)系。NDK生成系統(tǒng)會(huì)為你自動(dòng)生成,。 這也意味著,,當(dāng)更新至新的NDK版本時(shí),你能得到新的工具鏈/平臺(tái)支持(toolchain/platform support) 的好處,而無須修改你的android.mk文件,。 需要注意的是,,此語法與完全開源的Android平臺(tái)的Android.mk文件的語法非常相似,但使用它們的 生成系統(tǒng)的實(shí)現(xiàn)不同,,這個(gè)為了讓開發(fā)者能更容易的復(fù)用"外部"庫的源代碼,。 簡(jiǎn)單例子: --------------- 在詳細(xì)描述語法之前,讓我們探究一個(gè)簡(jiǎn)單的"hello JNI"例子,,它的文件位于: apps/hello-jni/projec 這里,,我們能看到: - 放有Java源文件的src文件夾。 - 放有本地源文件,,即jni/hello-jni.c的jni文件夾,。 這個(gè)源文件實(shí)現(xiàn)一個(gè)簡(jiǎn)單的共享庫。這個(gè)共享庫有一個(gè)本地方法(native method),,它將一個(gè)字符串 返回給虛擬機(jī)應(yīng)用(著:即Java層應(yīng)用程序) - jni/Anroid.mk文件為NDK生成系統(tǒng)描述了這個(gè)共享庫,。它的內(nèi)容為: ---------- 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 ------------------ 現(xiàn)在,讓我們逐行解釋: LOCAL_PATH := $(call my-dir) 每個(gè)Android.mk文件都必須以定義LOCAL_PATH變量開始,。其目的是為了定位源文件的位置,。在這個(gè)例子, 生成系統(tǒng)提供的宏函數(shù)(macro function)'my-dir'用來返回當(dāng)前路徑(即放有Android.mk文件的文件夾) include $(CLEAR_VARS) CLEAR_VARS變量是生成系統(tǒng)提供的,,它指向一個(gè)特殊的GNU Makefile.這個(gè)Makefile將會(huì)為你自動(dòng)清除 許多名為L(zhǎng)OCAL_XXX的變量(比如:LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIE S,等), 但LOCAL_PATH是例外,,它不會(huì)被清除。這些變量的清除是必須的,,因?yàn)樗械目刂莆募窃趩我坏腉NU make 執(zhí)行環(huán)境中解析的,,在這里所有的變量都是全局的。 LOCAL_MODULE := hello-jni 為了在你的Android.mk文件標(biāo)識(shí)每個(gè)組件,,必須定義LOCAL_MODULE變量,。這個(gè)名字必須要唯一的并且不能 包含空格。注意:生成系統(tǒng)會(huì)自動(dòng)地為相應(yīng)生成的文件加入前綴或后綴,。換言之,,一個(gè)名叫foo的共享庫組件 會(huì)生成'libfoo.so'. 重要注意事項(xiàng): 如果你把組件取名為'libfoo',生成系統(tǒng)將不會(huì)加上'lib'前綴,,還是 生成libfoo.so。這是為了支持源于Android平臺(tái)源代碼的Android.mk文件,。 LOCAL_SRC_FILES := hello-jni.c LOCAL_SRC_FILES變量必須包含一系列將被構(gòu)建和組合成組件的C/C++源文件,。注意:你 不需要列出頭文件或include文件,因?yàn)樯上到y(tǒng)會(huì)為你自動(dòng)計(jì)算出源文件的依賴關(guān)系,。 僅僅列出那些將直接傳給編譯器的源文件足矣,。 注意,默認(rèn)的C++源文件的擴(kuò)展名是'.cpp',。但你可以通過定義LOCAL_DEFAULT_EXTENSION 來指定一個(gè)擴(kuò)展名,。別忘了擴(kuò)展名開始的那一點(diǎn)(比如,'.cxx',能行,但'cxx'不行),。 include $(BUILD_SHARED_LIBRARY) 生成系統(tǒng)提供的BUIL_SHARED_LIBRARY變量指向一個(gè)GNU Makefile腳本,,這個(gè)腳本主管 收集在最近的一次#include $(CLEAR_VARS)(著:即清除'本地'變量)之后你所定義的 LOCAL_XXX變量的信息,并決定生成什么,,如何準(zhǔn)確的生成,。BUILD_STATIC_LIBRARY可 生成一個(gè)靜態(tài)庫。 There are more complex examples under apps/, with commented Android.mk files that you can look at. 在apps文件下有一些復(fù)雜點(diǎn)的例子,,它帶有注釋的Android.mk文件以供你學(xué)習(xí),。 參考: ----------- 以下列出你在Android.mk里應(yīng)該依賴或定義的變量。你能定義其它變量,,但下列的變量名是 由NDK生成系統(tǒng)保留的,。 - 以LOCAL_ 開頭的變量名 (比如,LOCAL_MODULE) - 以PRIVATE_ ,NDK_ 或 APP_ (內(nèi)部使用)開頭的量名 _ 小寫字母變量名(內(nèi)部使用,如 my-dir). 如果你需要在Android.mk里定義方便自己使用的變量名,,我們建議使用MY_ 前綴, 如下面一個(gè)簡(jiǎn)單例子: ---------- 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被解析之前,就被生成系統(tǒng)事先定義 的了.注意,在某些情況下,NDK可能會(huì)多次解析你的Android.mk,,每次對(duì)其中一些變量的 定義不同,。 CLEAR_VARS 指向一個(gè)生成腳本,這個(gè)腳本取消幾乎所有LOCAL_XXX變量的定義(譯者注:除了LOCAL_PATH),。 在開始描述一個(gè)新的組件之前,,你必須include這個(gè)腳本,e.g.: include $(CLEAR_VARS) BUILD_SHARED_LIBRARY 指向一個(gè)生成腳本,,這個(gè)腳本通過LOCAL_XXX變量收集關(guān)于組件的信息,,并決定如何 根據(jù)你列出來的源文件生成目標(biāo)分享庫。注意,,在include這個(gè)腳本文件之前你必須 至少已經(jīng)定義了LOCAL_MODULE和LOCAL_SRC_FILES,。用法舉例: include $(BUILD_SHARED_LIBRARY) 注意,這會(huì)生成一個(gè)名為 lib$(LOCAL_MODULE).so的文件,。(譯者注:$(BUILD_SHARED_MODULE)為文件名) BUILD_STATIC_LIBRARY 與BUILD_SHARED_LIBRARY類似,,但用來生成目標(biāo)靜態(tài)庫,。靜態(tài)庫不會(huì)被拷貝至你的 project/packages文件夾下,但可用來生成分享庫(參考 LOCAL_STATIC_LIBRARIES 和LOCAL_STATIC_WHOLE_LIBRARIES,,將在后面描述) 用法示例: include $(BUILD_STATIC_LIBRARY) 注意,,這會(huì)生成一個(gè)方件名叫l(wèi)ib$(LOCAL_MODULE).a TARGET_ARCH 目標(biāo)CPU的名字,在完整的Android開源代碼的生成中指定,。對(duì)于基于ARM兼容的CPU,, 它被指定為'arm',與CPU架構(gòu)的修訂無關(guān)。 TARGET_PLATFORM 當(dāng)解析該Android.mk文件時(shí)用它來指定Andoid目標(biāo)平臺(tái)的名稱,。譬如,,'android-3'與 Android 1.5系統(tǒng)鏡像相對(duì)應(yīng)。若要了解所有的平臺(tái)名稱及其相應(yīng)的Android系統(tǒng)鏡像,, 請(qǐng)閱讀docs/STABLE-APIS.TXT TARGET_ARCH_ABI 當(dāng)解析該Android.mk時(shí),,CPU+ABI的名稱。目前只有一個(gè)值,。 (譯者注:ABI,Application Binary Interface,,二進(jìn)制應(yīng)用程序接口) armeabi For Armv5TE armeabi 指定Armv5TE 注意:到NDK 1.6_r1為止,僅簡(jiǎn)單的定義這個(gè)變量為'arm',。但為了更好地配合 Android平臺(tái)的內(nèi)部使用,,該值已重定義。 關(guān)于ABI與相應(yīng)的兼容問題更多詳情,,請(qǐng)閱讀docs/CPU-ARCH-ABIS.TXT 未來的NDK版本將會(huì)引入其它的平臺(tái)的ABI并會(huì)有不同的名稱,。注意,所有基于ARM的ABI會(huì) 使TARGET_ARCH定義為'arm',但可能擁有不同的TARGET_ARCH_ABI TARGET_ABI 目標(biāo)平臺(tái)與abi的連接,,它實(shí)際上被定義為 $(TARGET_PLATFORM)-$(TARGET_ARCH_ABI),, 當(dāng)你想在一個(gè)真實(shí)的裝置上測(cè)試特定的目標(biāo)系統(tǒng)鏡像時(shí),它就很有用了,。 默認(rèn)下,,它的值為'android-3-armeabi' (在Android NDK 1.6_r1及之前的版本,它的默認(rèn)值為'android-3-arm') NDK提供的宏函數(shù): ---------------------------- 以下是一些GNU Make的宏'函數(shù)',,必須通過這樣的形式調(diào)用:'$(call <function>)',。 函數(shù)返回文本信息。 my-dir 返回放置當(dāng)前Android.mk的文件夾相對(duì)于NDK生成系統(tǒng)根目錄的路徑,??捎脕? 在Android.mk的開始處定義LOCAL_PATH的值: LOCAL_PATH := $(call my-dir) all-subdir-makefiles 返回'my-dir'子目錄下的所有Android.mk。比如,,代碼的結(jié)構(gòu)如下: sources/foo/Android.mk sources/foo/lib1/Android.mk sources/foo/lib2/Android.mk 如果sources/foo/Android.mk里有這樣一行: include $(call all-subdir-makefiles) 那么,,它將會(huì)自動(dòng)地includesources/foo/lib1/Android.mk和sources/foo/lib2/Android.mk 這個(gè)函數(shù)能將深層嵌套的代碼文件夾提供給生成系統(tǒng)。注意,默認(rèn)情況下,,NDK僅在 source/*/Android.mk里尋找文件,。 this-makefile 返回當(dāng)前Makefile(譯者注:指的應(yīng)該是GNU Makefile)的路徑(即,這個(gè)函數(shù)是在哪里調(diào)用的) parent-makefile 返回在列入樹(inclusion tree)中的父makefile的路徑,。 即,,包含當(dāng)前makefile的那個(gè)makefile的路徑。 grand-parent-makefile 猜猜看...(譯者注:原文為Guess what...) 組件描述相關(guān)的變量: - - - - - - - - - - 以下的變量是用來向生成系統(tǒng)描述你的組件的,。你應(yīng)該在'include $(CLEAR_VARS)' 和'include $(BUILD_XXXXX)'之間定義其中的一些變量,。正如在前面所說的,$(CLEAR_VARS) 是一個(gè)將會(huì)取消所有這些變量的腳本,,除非在對(duì)變量的描述時(shí)有顯式的說明,。 LOCAL_PATH 這個(gè)變量用來設(shè)置當(dāng)前文件的路徑。你必須在Android.mk的開始處定義它,,比如: LOCAL_PATH := $(call my-dir) 這個(gè)變量不會(huì)被$(CLEAR_VARS)消除,,所以每個(gè)Android.mk僅需一個(gè)定義(以防你在 同一個(gè)文件里定義幾個(gè)組件)。 LOCAL_MODULE 定義組件的名稱,。對(duì)于所有的組件名,,它必須是唯一,且不能包含空格,。 在include $(BUILD_XXX)之前你必須定義它,。 這個(gè)組件名決定生成的文件(譯者注:即庫名)。比如,,lib<foo>,,即這個(gè)組件的名稱 為<foo>。但是在你的NDK生成文件(不管是Android.mk還是Application.mk)中 你只能通過'正常'的名稱(如,,<foo>)來引用其它的組件,。 LOCAL_SRC_FILES 用它來定義所有用來生成組件的源文件。僅須列出傳給編譯器的文件,,因?yàn)? 生成系統(tǒng)會(huì)自動(dòng)地計(jì)算它們的相互依賴關(guān)系,。 注意,所有文件名都是相對(duì)于LOCAL_PATH的,,你可以用到路徑組件(path component) 如: LOCAL_SRC_FILES := foo.c \ (譯者注:'\'為連接符) toto/bar.c LOCAL_CPP_EXTENSION 這是一個(gè)可選的變量,可用它來指明C++源文件的擴(kuò)展名,。默認(rèn)情況下是'.cpp', 但你可以改變它,。比如: LOCAL_CPP_EXTENSION := .cxx LOCAL_C_INCLUDES 一個(gè)相對(duì)于相對(duì)于NDK*根*目錄可選的路徑名單,當(dāng)編譯所有的源文件(C,C++和匯編)時(shí),, 它將被添加進(jìn)include搜索路徑,。例如: LOCAL_C_INCLUDES := sources/foo 或者甚至: LOCAL_C_INCLUDES := $(LOCAL_PATH)/../foo LOCAL_CFLAGS 一個(gè)可選的編譯標(biāo)記集,在生成C與C++源文件時(shí),將解析它,。 對(duì)指定額外的宏定義或編譯選項(xiàng)很有用,。 重要:不要試圖改變你Android.mk里的optimization/debuggin level,通過 在你的Android.mk里指定合適的信息,它將被自動(dòng)處理,,并使NDK生成 調(diào)試時(shí)可用的有用的數(shù)據(jù)文件,。 注意:在android-ndk-1.5_r1,相應(yīng)的標(biāo)記(flags)只適用于C源文件,,對(duì)C++ 源文件并不適用,。為了適用于完整的Android生成系統(tǒng)的特性,已作了修 正,。(現(xiàn)在,,你可以使用LOCAL_CPPFLAGS為C++文件指定標(biāo)記) LOCAL_CXXFLAGS LOCAL_CPPFLAGS的別名。注意,,不建議使用這個(gè)變量,,因?yàn)樵谖磥淼腘DK版本中, 它可能會(huì)消失,。 LOCAL_CPPFLAGS 一個(gè)可選的編譯標(biāo)記集,,*僅*在生成C++源文件時(shí)解析它。在編譯器的命令行里 它將在LOCAL_CFLAGS之后出現(xiàn),。 注意:在android-ndk-1.5_r1,,相應(yīng)的標(biāo)記(flags)適用于C與C++源文件。 為了適用于完整的Android生成系統(tǒng)的特性,,已作了修 正,。(現(xiàn)在,你可以使用LOCAL_CFLAGS為C和C++源文件指定標(biāo)記) LOCAL_STATIC_LIBRARIES 一份static libraries組件的名單(以BUILD_STATIC_LIBRARY的方式生成),,它將被 連接到欲生成的組件上,。這僅在生成shared library組件時(shí)有意義。(譯者注:將指定 的一個(gè)或多個(gè)static library module轉(zhuǎn)化為一個(gè)shared library module) LOCAL_SHARED_LIBRARIES 一份該組件在運(yùn)行期依賴于它的shared libraries *組件*,。在連接時(shí)間(link time)里 與及為該生成的文件嵌入相應(yīng)的信息都要用到它,。 注意,它并不將這份組件名單添加入生成圖表(build graph),。即,,在你的Android.mk 里,你仍應(yīng)該將它們加入到你的應(yīng)用程序要求的組件,。 LOCAL_LDLIBS 一份能在生成你的組件時(shí)用到的額外的連接器標(biāo)記(linkerflags)的名單,。在傳遞 有"-l"前綴的特殊系統(tǒng)庫的名稱時(shí)很有用。比如,,下面的語句會(huì)告訴連接器在裝載 時(shí)間(load time)里生成連接到/system/lib/libz.so的組件,。 LOCAL_LDLIBS := -lz 若想知道在這個(gè)NDK版本可以連接哪些暴露的系統(tǒng)庫(exposed system libraries),, 請(qǐng)參見docs/STABLE-APIS。 LOCAL_ALLOW_UNDEFINED_SYMBOLS 缺省值情況下,,當(dāng)嘗試生成一個(gè)shared library遇到?jīng)]有定義的引用時(shí),,會(huì)導(dǎo)致"undefined symbol"error。這對(duì)在你的源代碼里捕捉bugs有很大的幫助,。 但是,,因?yàn)橐恍┰蚰沩氁猟isable這個(gè)檢查,將這個(gè)變量設(shè)置為'true',。注意,,相應(yīng) 的shared library可能在運(yùn)行期裝載失敗。 LOCAL_ARM_MODE 缺省值情況下,,ARM目標(biāo)二進(jìn)制將會(huì)以'thumb'模式生成,,這時(shí)每個(gè)指令都是16-bit寬的。 如果你想強(qiáng)迫組件的object文件以'arm'(32位的指令)的模式生成,,你可以將這個(gè)變量 定義為'arm',。即: LOCAL_ARM_MODE := arm 注意,你也可以通過將'.arm'后綴添加到源文件名字的后面指示生成系統(tǒng)將指定的 源文件以arm模式生成,。例如: LOCAL_SRC_FILES := foo.c bar.c.arm 告訴生成系統(tǒng)總是以arm模式編譯'bar.c',,但根據(jù)LOCAL_ARM_MODE的值生成foo.c 注意:在你的Application.mk里將APP_OPTIM設(shè)置為'debug',這也會(huì)強(qiáng)迫生成ARM二進(jìn)制 代碼。這是因?yàn)楣ぞ哝湹恼{(diào)度器有bugs,,它對(duì)thumb碼的處理不是很好,。 轉(zhuǎn)載請(qǐng)注明出處: http://hi.baidu.com/百囧囧度/blog/item/fde87e95ace1cc12d31b706c.html |
|