Android mk檔案介紹

來源:互聯網
上載者:User

Introduction:
    Android.mk編譯檔案是用來向Android NDK描述你的C,C++原始碼檔案的, 這篇文檔描述了它的文法。在閱讀下面的內容之前,假定你已經閱讀了docs/OVERVIEW.TXT檔案,瞭解了它們的腳色和用途。
一、概述
    一個Android.mk file用來向編譯系統描述你的原始碼。具體來說:
    (1) 該檔案是GNU Makefile的一小部分,會被編譯系統解析一次或更多次的build系統。
         因此,您應盡量減少您聲明的變數,不要認為某些變數在解析過程中不會被定義。
    (2) 這個檔案的文法允許把你的原始碼組織成模組,一個模組屬下列類型之一:
         1) 靜態庫 2) 共用庫,且只有共用庫將被安裝/複製到您的應用軟體包,雖然靜態庫能被用於產生共用庫。
    你可以在每一個Android.mk file中定義一個或多個模組,你也可以在幾個模組中使用同一個原始碼檔案。
    (1) 編譯系統為你處理許多細節問題。例如,你不需要在你 的Android.mk中列出標頭檔和依賴檔案。NDK編譯系統將會為你自動處理這些問題。這也意味著,在升級NDK後,你應該得到新的 toolchain/platform支援,而且不需要改變你的Android.mk檔案。
    注意,這個文法同公開發布的Android平台的開原始碼很接近,然而編譯系統實現他們的方式卻是不同的,這是故意這樣設計的,可以讓程式開發人員重用外 部庫的原始碼更容易。
   在描述文法細節之前,咱們來看一個簡單的"hello world"的例子,比如,下面的檔案:
sources/helloworld/helloworld.c
sources/helloworld/Android.mk
     'helloworld.c'是一個JNI共用庫,實現返回"hello world"字串的原生方法。相應的Android.mk檔案會象下面這樣:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= helloworld
LOCAL_SRC_FILES := helloworld.c
include $(BUILD_SHARED_LIBRARY)
    好,我們來解釋一下這幾行代碼:
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_首碼,一個小例子:
MY_SOURCES := foo.c
ifneq ($(MY_CONFIG_BAR),)
MY_SOURCES += bar.c
endif
LOCAL_SRC_FILES += $(MY_SOURCES)
1. GNU Make 變數
    這些GNU Make 變數在你的Android.mk檔案解析之前,就由編譯系統定義好了。注意在某些情況下,NDK可能分析Android.mk幾次,每一次某些變數的定義 會有不同。
(1) CLEAR_VARS: 指向一個編譯指令碼,幾乎所有未定義的LOCAL_XXX變數都在"Module-description"節中列出。你必須在開始一個新模組之前包含這個 指令碼。include $(CLEAR_VARS)
(2) BUILD_SHARED_LIBRARY: 指向編譯指令碼,收集所有的你在LOCAL_XXX變數中提供的資訊,並且決定如何把你列出的原始碼檔案編譯成一個共用庫。注意,你必須至少在包含這個檔案 之前定義LOCAL_MODULE和LOCAL_SRC_FILES,使用例子:
include $(BUILD_SHARED_LIBRARY) (注意這將產生一個名為lib$(LOCAL_MODULE).so的檔案)
(3) BUILD_STATIC_LIBRARY: 一個BUILD_SHARED_LIBRARY變數用於編譯一個靜態庫。靜態庫不會複製到你的project/packages中,但是能夠用於 編譯共用庫,(看下面描述的LOCAL_STATIC_LIBRARIES and LOCAL_STATIC_WHOLE_LIBRARIES)
使用例子:include $(BUILD_STATIC_LIBRARY) (注意,這將會產生一個名為lib$(LOCAL_MODULE).a的檔案)。
(4) TARGET_ARCH: 目標CPU平台的名字, 和android開放源碼中指定的那樣。如果是arm,表示要產生ARM相容的指令,與CPU架構的修訂版無關。
(5) 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
 (6) TARGET_ARCH_ABI: 暫時只支援兩個value,armeabi和armeabi-v7a。在現在的版本中一般把這兩個值簡單的定義為arm,通過android 平台內部對它重定義來獲得更好的匹配。其他的ABI將在以後的NDK版本中介紹,它們會有不同的名字。注意所有基於ARM的ABI都會把 'TARGET_ARCH'定義成‘arm’,但是會有不同的‘TARGET_ARCH_ABI’
 (7) TARGET_ABI: 目標平台和ABI的組合,它事實上被定義成$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI) 在你想要在真實的裝置中針對一個特別的目標系統進行測試時,會有用。在預設的情況下,它會是'android-3-arm'。
2. 模組描述變數
    下面的變數用於向編譯系統描述你的模組。你應該定義在'include $(CLEAR_VARS)'和'include $(BUILD_XXXXX)'之間。正如前面描寫的那樣,$(CLEAR_VARS是一個指令碼,清除所有這些變數,除非在描述中顯式注 明。
(1) LOCAL_PATH: 這個變數用於給出當前檔案的路徑。你必須在Android.mk的開頭定義,可以這樣使用:
 LOCAL_PATH := $(call my-dir)
    這個變數不會被$(CLEAR_VARS)清除,因此每個Android.mk只需要定義一次(即使你在一個檔案中定義了幾個模組的情況下)。
 (2) LOCAL_MODULE: 這是你模組的名字,它必須是唯一的,而且不能包含空格。你必須在包含任一的$(BUILD_XXXX)指令碼之前定義它。模組的名字決定了組建檔案的名字, 例如,如果一個一個共用庫模組的名字是<foo>,那麼組建檔案的名字就是lib<foo>.so。但是,在你的NDK組建檔案 中(或者Android.mk或者Application.mk),你應該只涉及(引用)有正常名字的其他模組。
 (3) LOCAL_SRC_FILES: 這是要編譯的原始碼檔案清單。只要列出要傳遞給編譯器的檔案,因為編譯系統自動為你計算依賴。注意原始碼檔案名稱都是相對於LOCAL_PATH的,你可 以使用路徑部分,例如:
LOCAL_SRC_FILES := foo.c \
toto/bar.c
    注意:在組建檔案中都要使用UNIX風格的斜杠(/).windows風格的反斜線不會被正確的處理。
 (4) LOCAL_CPP_EXTENSION: 這是一個可選變數,用來指定C++代碼檔案的副檔名,預設是'.cpp',但是你可以改變它,比如:
LOCAL_CPP_EXTENSION := .cxx
 (5) 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標誌之前。
 (6) LOCAL_CFLAGS: 可選的編譯器選項,在編譯C代碼檔案的時候使用。這可能是有用的,指定一個附加的包含路徑(相對於NDK的頂層目錄),宏定義,或者編譯選項。
     重要訊息:不要在Android.mk中改變 optimization/debugging層級,只要在Application.mk中指定合適的資訊,就會自動地為你處理這個問題, 在調試期間,會讓NDK自動產生有用的資料檔案。
 (7) LOCAL_CXXFLAGS: Same as LOCAL_CFLAGS for C++ source files
 (8) LOCAL_CPPFLAGS: 與LOCAL_CFLAGS相同,但是對C 和C++ source files都適用。
 (9) LOCAL_STATIC_LIBRARIES: 應該連結到這個模組的靜態庫列表(使用BUILD_STATIC_LIBRARY產生),這僅僅對共用庫模組才有意義。
 (10) LOCAL_SHARED_LIBRARIES: 這個模組在運行時要依賴的共用庫模組列表,在連結時需要,在組建檔案時嵌入的相應的資訊。注意:這不會附加列出的模組到編譯圖,也就是,你仍然需要在 Application.mk中把它們添加到程式要求的模組中。
 (11) LOCAL_LDLIBS: 編譯你的模組要使用的附加的連結器選項。這對於使用”-l”首碼傳遞指定庫的名字是有用的。例如,下面將告訴連結器產生的模組要在載入時刻連結到 /system/lib/libz.so
    LOCAL_LDLIBS := -lz
    看docs/STABLE-APIS.TXT擷取你使用 NDK發行版能連結到的開放的系統庫列表。
 (13) LOCAL_ALLOW_UNDEFINED_SYMBOLS: 預設情況下,在試圖編譯一個共用庫時,任何未定義的引用將導致一個“未定義的符號”錯誤。這對於在你的原始碼檔案中捕捉錯誤會有很大的協助。然而,如果你 因為某些原因,需要不啟動這項檢查,把這個變數設為‘true’。注意相應的共用庫可能在運行時載入失敗。(這個一般盡量不要去設為true)
 (14) LOCAL_ARM_MODE: 預設情況下,arm目標二進位會以thumb的形式產生(16位),你可以通過設定這個變數為arm如果你希望你的module是以32位指令的形式。
'arm' (32-bit instructions) mode. E.g.:
 (15) LOCAL_ARM_MODE := arm   注意你同樣可以在編譯的時候告訴系統編譯特定的類型,比如
 (16) LOCAL_SRC_FILES := foo.c bar.c.arm  這樣就告訴系統總是將bar.c以arm的模式編譯,下面是GNU Make‘功能’宏,必須通過使用'$(call <function>)'來求值,他們返迴文本化的資訊。
 (17) my-dir: 返回當前Android.mk所在的目錄路徑,相對於NDK編譯系統的頂層。這是有用的,在Android.mk檔案的開頭如此定義:
LOCAL_PATH := $(call my-dir)
 (18) 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中的檔案。
 (19) this-makefile: 返回當前Makefile的路徑(即這個函數調用的地方)
 (20) parent-makefile: 返回調用樹中父Makefile路徑。即包含當前Makefile的Makefile路徑。
 (21) grand-parent-makefile 猜猜看...
3. 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)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.