Introduction: html
Android.mk編譯文件是用來向Android NDK描述你的C,C++源代碼文件的, 這篇文檔描述了它的語法。在閱讀下面的內容以前,假定你已經閱讀了docs/OVERVIEW.TXT文件,瞭解了它們的腳色和用途。 android
概述: windows
一個Android.mk file用來向編譯系統描述你的源代碼。具體來講:-該文件是GNU Makefile的一小部分,會被編譯系統解析一次或更屢次的build系統。所以,您應儘可能減小您聲明的變量,不要認爲某些變量在解析過程當中不會被定義。-這個文件的語法容許把你的源代碼組織成模塊,一個模塊屬下列類型之一: api
靜態庫 架構
共享庫 函數
只有共享庫將被安裝/複製到您的應用軟件包。雖然靜態庫能被用於生成共享庫。 測試
你能夠在每個Android.mk file中定義一個或多個模塊,你也能夠在幾個模塊中使用同一個源代碼文件。 ui
/*****************************************************************************/ this
-編譯系統爲你處理許多細節問題。例如,你不須要在你的Android.mk中列出頭文件和依賴文件。NDK編譯系統將會爲你自動處理這些問題。這也意味着,在升級NDK後,你應該獲得新的toolchain/platform支持,並且不須要改變你的Android.mk文件。 debug
注意,這個語法同公開發布的Android平臺的開源代碼很接近,然而編譯系統實現他們的方式倒是不一樣的,這是故意這樣設計的,可讓程序開發人員重用外部庫的源代碼更容易。
簡單的例子:
---------------
在描述語法細節以前,我們來看一個簡單的"hello world"的例子,好比,下面的文件:
sources/helloworld/helloworld.c
sources/helloworld/Android.mk
'helloworld.c'是一個JNI共享庫,實現返回"hello world"字符串的原生方法。
相應的Android.mk文件會象下面這樣:
---------- cut here ------------------
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= helloworld LOCAL_SRC_FILES := helloworld.c include $(BUILD_SHARED_LIBRARY)
---------- cut here ------------------
好,咱們來解釋一下這幾行代碼:
LOCAL_PATH := $(call my-dir)
一個Android.mk file首先必須定義好LOCAL_PATH變量。它用於在開發樹中查找源文件。在這個例子中,宏函數’my-dir’, 由編譯系統提供,用於返回當前路徑(即包含Android.mk file文件的目錄)。
include $( CLEAR_VARS)
CLEAR_VARS由編譯系統提供,指定讓GNU MAKEFILE爲你清除許多LOCAL_XXX變量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),
除LOCAL_PATH 。這是必要的,由於全部的編譯控制文件都在同一個GNU MAKE執行環境中,全部的變量都是全局的。
LOCAL_MODULE := helloworld
LOCAL_MODULE變量必須定義,以標識你在Android.mk文件中描述的每一個模塊。名稱必須是惟一的,並且不包含任何空格。注意編譯系統會自動產生合適的前綴和後綴,換句話說,一個被命名爲'foo'的共享庫模塊,將會生成'libfoo.so'文件。
重要注意事項
若是你把庫命名爲‘libhelloworld’,編譯系統將不會添加任何的lib前綴,也會生成libhelloworld.so,這是爲了支持來源於Android平臺的源代碼的Android.mk文件,若是你確實須要這麼作的話。
LOCAL_SRC_FILES := helloworld.c
LOCAL_SRC_FILES變量必須包含將要編譯打包進模塊中的C或C++源代碼文件。注意,你不用在這裏列出頭文件和包含文件,由於編譯系統將會自動爲你找出依賴型的文件;僅僅列出直接傳遞給編譯器的源代碼文件就好。【注意,默認的C++源碼文件的擴展名是’.cpp’. 指定一個不一樣的擴展名也是可能的,只要定義LOCAL_DEFAULT_CPP_EXTENSION變量,不要忘記開始的小圓點(也就是定義爲‘.cxx’,而不是‘cxx’)(固然這一步咱們通常不會去改它)】
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY是編譯系統提供的變量,指向一個GNU Makefile腳本(應該就是在build/core目錄下的shared_library.mk),負責收集自從上次調用'include $(CLEAR_VARS)'以來,定義在LOCAL_XXX變量中的全部信息,而且決定編譯什麼,如何正確地去作。並根據其規則生成靜態庫。同理對於靜態庫。
/****************************************************************************/
在sources/samples目錄下有更復雜一點的例子,寫有註釋的Android.mk文件,你能夠看看。
參考:
這是一份你應該在Android.mk中依賴或定義的變量列表,您能夠定義其餘變量爲本身使用,
可是NDK編譯系統保留下列變量名:
-以LOCAL_開頭的名字(例如 LOCAL_MODULE)
-以PRIVATE_, NDK_ or 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 ------------------
- - - - - - - - - - -
這些GNU Make 變量在你的Android.mk文件解析以前,就由編譯系統定義好了。
注意在某些狀況下,NDK可能分析Android.mk幾回,每一次某些變量的定義會有不一樣。
CLEAR_VARS
指向一個編譯腳本,幾乎全部未定義的LOCAL_XXX變量都在"Module-description"節中列出。
你必須在開始一個新模塊以前包含這個腳本。include $(CLEAR_VARS)
BUILD_SHARED_LIBRARY
指向編譯腳本,收集全部的你在LOCAL_XXX變量中提供的信息,而且決定如何把你列出的源代碼文件編譯成一個共享庫。注意,你必須至少在包含這個文件以前定義LOCAL_MODULE和LOCAL_SRC_FILES,使用例子:
include $(BUILD_SHARED_LIBRARY)
注意這將生成一個名爲lib$(LOCAL_MODULE).so的文件。
BUILD_STATIC_LIBRARY
一個BUILD_SHARED_LIBRARY變量用於編譯一個靜態庫。靜態庫不會複製到你的project/packages中,誕生可以用於編譯共享庫,(看下面描述的LOCAL_STATIC_LIBRARIES and LOCAL_STATIC_WHOLE_LIBRARIES)
使用例子:
include $(BUILD_STATIC_LIBRARY)
注意,這將會生成一個名爲lib$(LOCAL_MODULE).a的文件。
TARGET_ARCH
目標CPU平臺的名字,如同在android開放源碼中指定的那樣。若是是’arm’,表示要生成ARM兼容的指令,與CPU架構的修訂版無關。
TARGET_PLATFORM
Android.mk解析的時候,目標Android平臺的名字.詳情可參考/development/ndk/docs/stable-apis.txt.
android-3 -> Official Android 1.5 system images
android-4 -> Official Android 1.6 system images
android-5 -> Official Android 2.0 system images
TARGET_ARCH_ABI
暫時只支持兩個value,armeabi和armeabi-v7a。在如今的版本中通常把這兩個值簡單的定義爲arm,經過android 平臺內部對它重定義來得到更好的匹配。
其餘的ABI將在之後的NDK版本中介紹,它們會有不一樣的名字。注意全部基於ARM的ABI都會把'TARGET_ARCH'定義成‘arm’,可是會有不一樣的‘TARGET_ARCH_ABI’
TARGET_ABI
目標平臺和ABI的組合,它事實上被定義成$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI) 在你想要在真實的設備中針對一個特別的目標系統進行測試時,會有用。在默認的狀況下,它會是'android-3-arm'。
/*****************************************************************************/
下面是GNU Make ‘功能’宏,必須經過使用'$(call <function>)'來求值,他們返回文本化的信息。
my-dir
返回當前Android.mk所在的目錄路徑,相對於NDK編譯系統的頂層。這是有用的,在Android.mk文件的開頭如此定義:
LOCAL_PATH := $(call my-dir)
all-subdir-makefiles
返回一個位於當前'my-dir'路徑的子目錄列表。例如,看下面的目錄層次:
sources/foo/Android.mk
sources/foo/lib1/Android.mk
sources/foo/lib2/Android.mk
若是sources/foo/Android.mk包含一行:
include $(call all-subdir-makefiles)
那麼它就會自動包含sources/foo/lib1/Android.mk 和sources/foo/lib2/Android.mk
這項功能用於向編譯系統提供深層次嵌套的代碼目錄層次。注意,在默認狀況下,NDK將會只搜索在sources/*/Android.mk中的文件。
this-makefile
返回當前Makefile的路徑(即這個函數調用的地方)
parent-makefile
返回調用樹中父Makefile路徑。即包含當前Makefile的Makefile路徑。
grand-parent-makefile
猜猜看...
/*****************************************************************************/
模塊描述變量:
下面的變量用於向編譯系統描述你的模塊。你應該定義在'include $(CLEAR_VARS)'和'include $(BUILD_XXXXX)'之間定義。正如前面描寫的那樣,$(CLEAR_VARS是一個腳本,清除全部這些變量,除非在描述中顯式註明。
LOCAL_PATH
這個變量用於給出當前文件的路徑。你必須在Android.mk的開頭定義,能夠這樣使用:
LOCAL_PATH := $(call my-dir)
這個變量不會被$(CLEAR_VARS)清除,所以每一個Android.mk只須要定義一次(即便你在一個文件中定義了幾個模塊的狀況下)。
LOCAL_MODULE
這是你模塊的名字,它必須是惟一的,並且不能包含空格。你必須在包含任一的$(BUILD_XXXX)腳本以前定義它。模塊的名字決定了生成文件的名字,例如,若是一個一個共享庫模塊的名字是<foo>,那麼生成文件的名字就是lib<foo>.so。可是,在你的NDK生成文件中(或者Android.mk或者Application.mk),你應該只涉及(引用)有正常名字的其餘模塊。
LOCAL_SRC_FILES
這是要編譯的源代碼文件列表。只要列出要傳遞給編譯器的文件,由於編譯系統自動爲你計算依賴。
注意源代碼文件名稱都是相對於LOCAL_PATH的,你可使用路徑部分,例如:
LOCAL_SRC_FILES := foo.c \
toto/bar.c
注意:在生成文件中都要使用UNIX風格的斜槓(/).windows風格的反斜槓不會被正確的處理。
LOCAL_CPP_EXTENSION
這是一個可選變量,用來指定C++代碼文件的擴展名,默認是'.cpp',可是你能夠改變它,好比:
LOCAL_CPP_EXTENSION := .cxx
LOCAL_C_INCLUDES
路徑的可選配置,是從根目錄開始的,
all sources (C, C++ and Assembly). For example:
LOCAL_C_INCLUDES := sources/foo
Or even:
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../foo
須要在任何包含LOCAL_CFLAGS / LOCAL_CPPFLAGS標誌以前。
LOCAL_CFLAGS
可選的編譯器選項,在編譯C代碼文件的時候使用。
這多是有用的,指定一個附加的包含路徑(相對於NDK的頂層目錄),宏定義,或者編譯選項。
重要信息:不要在Android.mk中改變optimization/debugging級別,只要在Application.mk中指定合適的信息,就會自動地爲你處理這個問題,在調試期間,會讓NDK自動生成有用的數據文件。
LOCAL_CXXFLAGS
Same as LOCAL_CFLAGS for C++ source files
LOCAL_CPPFLAGS
與LOCAL_CFLAGS相同,可是對C 和 C++ source files都適用。
LOCAL_STATIC_LIBRARIES
應該連接到這個模塊的靜態庫列表(使用BUILD_STATIC_LIBRARY生成),這僅僅對共享庫模塊纔有意義。
LOCAL_SHARED_LIBRARIES
這個模塊在運行時要依賴的共享庫模塊列表,在連接時須要,在生成文件時嵌入的相應的信息。注意:這不會附加列出的模塊到編譯圖,也就是,你仍然須要在Application.mk中把它們添加到程序要求的模塊中。
LOCAL_LDLIBS
編譯你的模塊要使用的附加的連接器選項。這對於使用」-l」前綴傳遞指定庫的名字是有用的。例如,下面將告訴連接器生成的模塊要在加載時刻連接到/system/lib/libz.so
LOCAL_LDLIBS := -lz
看docs/STABLE-APIS.TXT獲取你使用NDK發行版能連接到的開放的系統庫列表。
LOCAL_ALLOW_UNDEFINED_SYMBOLS
默認狀況下,在試圖編譯一個共享庫時,任何未定義的引用將致使一個「未定義的符號」錯誤。這對於在你的源代碼文件中捕捉錯誤會有很大的幫助。
然而,若是你由於某些緣由,須要不啓動這項檢查,把這個變量設爲‘true’。注意相應的共享庫可能在運行時加載失敗。(這個通常儘可能不要去設爲true)
LOCAL_ARM_MODE
默認狀況下,arm目標二進制會以thumb的形式生成(16位),你能夠經過設置這個變量爲arm若是你但願你的module是以32位指令的形式。
'arm' (32-bit instructions) mode. E.g.:
LOCAL_ARM_MODE := arm
注意你一樣能夠在編譯的時候告訴系統編譯特定的類型,好比
LOCAL_SRC_FILES := foo.c bar.c.arm
這樣就告訴系統老是將bar.c以arm的模式編譯,
Android.mk使用模板
在一個Android.mk中能夠生成多個可執行程序、動態庫和靜態庫。
1,編譯應用程序的模板:
#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)
(菜鳥級別解釋::=是賦值的意思,$是引用某變量的值)LOCAL_SRC_FILES中加入源文件路徑,LOCAL_C_INCLUDES 中加入所須要包含的頭文件路徑,LOCAL_STATIC_LIBRARIES加入所須要連接的靜態庫(*.a)的名稱,LOCAL_SHARED_LIBRARIES中加入所須要連接的動態庫(*.so)的名稱,LOCAL_MODULE表示模塊最終的名稱,BUILD_EXECUTABLE表示以一個可執行程序的方式進行編譯。
2,編譯靜態庫的模板:
#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表示編譯一個靜態庫。
3,編譯動態庫的模板:
#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:表示根文件系統。
TARGET_OUT:表示system文件系統。
TARGET_OUT_DATA:表示data文件系統。
用法如:
LOCAL_MODULE_PATH:=$(TARGET_ROOT_OUT)
轉載連接:http://www.cnblogs.com/leaven/archive/2011/01/25/1944688.html