2018-11-22Android.mk文件語法規(guī)范

Android.mk文件語法規(guī)范

根據eoeandroid上的的連載,進行一些更新、修改和加亮截歉。

今天翻譯ANDROID-MK.TXT文件(英文原文件在/development/Ndk/Docs/android-mk.txt)

Android.mk文件語法規(guī)范

 

Introduction:

Android.mk編譯文件是用來向Android NDK描述你的C,C++源代碼文件的, 這篇文檔描述了它的語法箫柳。在閱讀下面的內容之前逞带,假定你已經閱讀了docs/OVERVIEW.TXT文件,了解了它們的腳色和用途庆杜。

 

概述:

一個Android.mk file用來向編譯系統(tǒng)描述你的源代碼简软。具體來說:-該文件是GNU Makefile的一小部分蛮拔,會被編譯系統(tǒng)解析一次或更多次的build系統(tǒng)。因此痹升,您應盡量減少您聲明的變量建炫,不要認為某些變量在解析過程中不會被定義。-這個文件的語法允許把你的源代碼組織成模塊疼蛾,一個模塊屬下列類型之一:

靜態(tài)庫

共享庫

只有共享庫將被安裝/復制到您的應用軟件包肛跌。雖然靜態(tài)庫能被用于生成共享庫。

你可以在每一個Android.mk file中定義一個或多個模塊,你也可以在幾個模塊中使用同一個源代碼文件衍慎。

/*****************************************************************************/

-編譯系統(tǒng)為你處理許多細節(jié)問題转唉。例如,你不需要在你的Android.mk中列出頭文件和依賴文件稳捆。NDK編譯系統(tǒng)將會為你自動處理這些問題赠法。這也意味著,在升級NDK后乔夯,你應該得到新的toolchain/platform支持砖织,而且不需要改變你的Android.mk文件。

注意末荐,這個語法同公開發(fā)布的Android平臺的開源代碼很接近侧纯,然而編譯系統(tǒng)實現(xiàn)他們的方式卻是不同的,這是故意這樣設計的甲脏,可以讓程序開發(fā)人員重用外部庫的源代碼更容易眶熬。

 

簡單的例子:

---------------

在描述語法細節(jié)之前,咱們來看一個簡單的"hello world"的例子块请,比如娜氏,下面的文件:

sources/helloworld/helloworld.c

sources/helloworld/Android.mk

'helloworld.c'是一個JNI共享庫,實現(xiàn)返回"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變量脊凰。它用于在開發(fā)樹中查找源文件抖棘。在這個例子中,宏函數(shù)’my-dir’, 由編譯系統(tǒng)提供狸涌,用于返回當前路徑(即包含Android.mk file文件的目錄)切省。

include $( CLEAR_VARS)

CLEAR_VARS由編譯系統(tǒng)提供,指定讓GNU MAKEFILE為你清除許多LOCAL_XXX變量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),

除LOCAL_PATH 帕胆。這是必要的朝捆,因為所有的編譯控制文件都在同一個GNU MAKE執(zhí)行環(huán)境中,所有的變量都是全局的懒豹。

LOCAL_MODULE := helloworld

LOCAL_MODULE變量必須定義芙盘,以標識你在Android.mk文件中描述的每個模塊。名稱必須是唯一的脸秽,而且不包含任何空格儒老。注意編譯系統(tǒng)會自動產生合適的前綴和后綴,換句話說记餐,一個被命名為'foo'的共享庫模塊驮樊,將會生成'libfoo.so'文件。

重要注意事項

如果你把庫命名為‘libhelloworld’,編譯系統(tǒng)將不會添加任何的lib前綴囚衔,也會生成libhelloworld.so挖腰,這是為了支持來源于Android平臺的源代碼的Android.mk文件,如果你確實需要這么做的話练湿。

LOCAL_SRC_FILES := helloworld.c

LOCAL_SRC_FILES變量必須包含將要編譯打包進模塊中的C或C++源代碼文件猴仑。注意,你不用在這里列出頭文件和包含文件肥哎,因為編譯系統(tǒng)將會自動為你找出依賴型的文件宁脊;僅僅列出直接傳遞給編譯器的源代碼文件就好∠湍罚【注意榆苞,默認的C++源碼文件的擴展名是’.cpp’. 指定一個不同的擴展名也是可能的,只要定義LOCAL_DEFAULT_CPP_EXTENSION變量霞捡,不要忘記開始的小圓點(也就是定義為‘.cxx’,而不是‘cxx’)(當然這一步我們一般不會去改它)】

include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY是編譯系統(tǒng)提供的變量坐漏,指向一個GNU Makefile腳本(應該就是在build/core目錄下的shared_library.mk),負責收集自從上次調用'include $(CLEAR_VARS)'以來碧信,定義在LOCAL_XXX變量中的所有信息赊琳,并且決定編譯什么,如何正確地去做砰碴。并根據其規(guī)則生成靜態(tài)庫躏筏。同理對于靜態(tài)庫。

 

 

 

/****************************************************************************/

在sources/samples目錄下有更復雜一點的例子呈枉,寫有注釋的Android.mk文件趁尼,你可以看看。

參考:

這是一份你應該在Android.mk中依賴或定義的變量列表猖辫,您可以定義其他變量為自己使用酥泞,

但是NDK編譯系統(tǒng)保留下列變量名:

-以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文件解析之前,就由編譯系統(tǒng)定義好了辛萍。

注意在某些情況下悯姊,NDK可能分析Android.mk幾次,每一次某些變量的定義會有不同贩毕。

CLEAR_VARS

指向一個編譯腳本悯许,幾乎所有未定義的LOCAL_XXX變量都在"Module-description"節(jié)中列出。

你必須在開始一個新模塊之前包含這個腳本耳幢。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變量用于編譯一個靜態(tài)庫冈在。靜態(tài)庫不會復制到你的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亮元。在現(xiàn)在的版本中一般把這兩個值簡單的定義為arm猛计,通過android 平臺內部對它重定義來獲得更好的匹配。

其他的ABI將在以后的NDK版本中介紹爆捞,它們會有不同的名字奉瘤。注意所有基于ARM的ABI都會把'TARGET_ARCH'定義成‘arm’,但是會有不同的‘TARGET_ARCH_ABI’

 

TARGET_ABI

  目標平臺和ABI的組合煮甥,它事實上被定義成$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI) 在你想要在真實的設備中針對一個特別的目標系統(tǒng)進行測試時盗温,會有用。在默認的情況下苛秕,它會是'android-3-arm'肌访。

 

 

/*****************************************************************************/

下面是GNU Make ‘功能’宏找默,必須通過使用'$(call <function>)'來求值艇劫,他們返回文本化的信息。

my-dir

返回當前Android.mk所在的目錄路徑惩激,相對于NDK編譯系統(tǒng)的頂層店煞。這是有用的,在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

這項功能用于向編譯系統(tǒng)提供深層次嵌套的代碼目錄層次。注意骡技,在默認情況下鸣个,NDK將會只搜索在sources/*/Android.mk中的文件羞反。

 

this-makefile

返回當前Makefile的路徑(即這個函數(shù)調用的地方)

 

parent-makefile

  返回調用樹中父Makefile路徑。即包含當前Makefile的Makefile路徑囤萤。

 

grand-parent-makefile

猜猜看...

 

 

/*****************************************************************************/

模塊描述變量:

下面的變量用于向編譯系統(tǒng)描述你的模塊昼窗。你應該定義在'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

這是要編譯的源代碼文件列表驱犹。只要列出要傳遞給編譯器的文件,因為編譯系統(tǒng)自動為你計算依賴足画。

注意源代碼文件名稱都是相對于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自動生成有用的數(shù)據文件漂洋。

 

LOCAL_CXXFLAGS

Same as LOCAL_CFLAGS for C++ source files

 

LOCAL_CPPFLAGS

與LOCAL_CFLAGS相同,但是對C 和 C++ source files都適用力喷。

 

LOCAL_STATIC_LIBRARIES

應該鏈接到這個模塊的靜態(tài)庫列表(使用BUILD_STATIC_LIBRARY生成)刽漂,這僅僅對共享庫模塊才有意義。

 

LOCAL_SHARED_LIBRARIES

這個模塊在運行時要依賴的共享庫模塊列表弟孟,在鏈接時需要贝咙,在生成文件時嵌入的相應的信息。注意:這不會附加列出的模塊到編譯圖拂募,也就是庭猩,你仍然需要在Application.mk中把它們添加到程序要求的模塊中。

 

LOCAL_LDLIBS

編譯你的模塊要使用的附加的鏈接器選項陈症。這對于使用”-l”前綴傳遞指定庫的名字是有用的蔼水。例如,下面將告訴鏈接器生成的模塊要在加載時刻鏈接到/system/lib/libz.so

LOCAL_LDLIBS := -lz

看docs/STABLE-APIS.TXT獲取你使用NDK發(fā)行版能鏈接到的開放的系統(tǒng)庫列表录肯。

 

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

注意你同樣可以在編譯的時候告訴系統(tǒng)編譯特定的類型贬芥,比如

       LOCAL_SRC_FILES := foo.c bar.c.arm

這樣就告訴系統(tǒng)總是將bar.c以arm的模式編譯,

 

 

Android.mk使用模板

在一個Android.mk中可以生成多個可執(zhí)行程序宣决、動態(tài)庫和靜態(tài)庫。

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加入所需要鏈接的靜態(tài)庫(*.a)的名稱赦肃,LOCAL_SHARED_LIBRARIES中加入所需要鏈接的動態(tài)庫(*.so)的名稱裙戏,LOCAL_MODULE表示模塊最終的名稱眶痰,BUILD_EXECUTABLE表示以一個可執(zhí)行程序的方式進行編譯。

2烟很,編譯靜態(tài)庫的模板:

     #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表示編譯一個靜態(tài)庫蜡镶。

3雾袱,編譯動態(tài)庫的模板:

     #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

      每個模塊的目標文件夾分別為:

可執(zhí)行程序:XXX_intermediates

靜態(tài)庫:      XXX_static_intermediates

動態(tài)庫:      XXX_shared_intermediates

      另外,在Android.mk文件中望伦,還可以指定最后的目標安裝路徑林说,用LOCAL_MODULE_PATH和LOCAL_UNSTRIPPED_PATH來指定。不同的文件系統(tǒng)路徑用以下的宏進行選擇:

TARGET_ROOT_OUT:表示根文件系統(tǒng)屯伞。

TARGET_OUT:表示system文件系統(tǒng)腿箩。

TARGET_OUT_DATA:表示data文件系統(tǒng)。

用法如:

 LOCAL_MODULE_PATH:=$(TARGET_ROOT_OUT)

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末劣摇,一起剝皮案震驚了整個濱河市度秘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饵撑,老刑警劉巖剑梳,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異滑潘,居然都是意外死亡垢乙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門语卤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來追逮,“玉大人,你說我怎么就攤上這事粹舵∨シ酰” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵眼滤,是天一觀的道長巴席。 經常有香客問我,道長诅需,這世上最難降的妖魔是什么漾唉? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任荧库,我火速辦了婚禮,結果婚禮上赵刑,老公的妹妹穿的比我還像新娘分衫。我一直安慰自己,他們只是感情好般此,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布蚪战。 她就那樣靜靜地躺著,像睡著了一般铐懊。 火紅的嫁衣襯著肌膚如雪邀桑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天居扒,我揣著相機與錄音概漱,去河邊找鬼。 笑死喜喂,一個胖子當著我的面吹牛瓤摧,可吹牛的內容都是我干的。 我是一名探鬼主播玉吁,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼照弥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了进副?” 一聲冷哼從身側響起这揣,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎影斑,沒想到半個月后给赞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡矫户,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年片迅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片皆辽。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡柑蛇,死狀恐怖,靈堂內的尸體忽然破棺而出驱闷,到底是詐尸還是另有隱情耻台,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布空另,位于F島的核電站盆耽,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜征字,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一都弹、第九天 我趴在偏房一處隱蔽的房頂上張望娇豫。 院中可真熱鬧匙姜,春花似錦、人聲如沸冯痢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浦楣。三九已至袖肥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間振劳,已是汗流浹背椎组。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留历恐,地道東北人寸癌。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像弱贼,于是被迫代替她去往敵國和親蒸苇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內容