序言:
————- 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