當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Android.mk詳解
Android.mk是Android工程管理文件,其作用基本等用于Linux環(huán)境中的Makefile,在語法上,Android.mk和普通Makefile略有不同,主要區(qū)別是Android.mk包含一些Android編譯系統(tǒng)的公共的宏,Android.mk中選項參考以下文件路徑: build/core/config.mk,各個選項的默認(rèn)值在以下文件中定義:
build/core/base_rules.mk
Android.mk文件只處理從根目錄開始找到的第一個Android.mk文件,如果需要遞歸。需要在當(dāng)前目錄的Android.mk文件中做如下處理:
include $(call all-makefiles-under,$(LOCAL_PATH))
在一個Android.mk中也可以生成多個目標(biāo):可執(zhí)行程序,動態(tài)庫,靜態(tài)庫或者Android用程序包,Android.mk文件可以處理多個內(nèi)容:
include $(CLEAR_VARS) //清理變量
#處理第一個內(nèi)容
include $(CLEAR_VARS)
#處理第二個內(nèi)容
現(xiàn)在我們來討論對于各種目標(biāo)的構(gòu)建方式
1、可執(zhí)行程序
LOCAL_PATH :=$(my_dir) //本地路徑,當(dāng)前目錄
Text EXe
include $(CLEAR_VARS)
LOCAL_SRC_FILES := eng
LCAOL_SRC_FILES :=
main.c
LOCAL_MODULE := text_exe
LOCAL_C_INCLUDES :=
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES := libc
include $(BUILD_EXECUTABLE)
注:編譯一個可執(zhí)行程序,需要在LOCAL_SRC_FILES 中假如遠(yuǎn)見路徑(相對于當(dāng)前Android.mk目錄的路徑),
在LOCAL_C_INCLUDES中假如所需要包含的頭文件路徑;
在LOCAL_STATIC_LIBRARIES 中假如所需要鏈接的靜態(tài)庫(*.a)的名稱;
在LOCAL_SHARED_LIBRARIES中假如所需要鏈接的動態(tài)庫(*.so)的名稱;
LOCAL_MODULE標(biāo)示模塊終的名稱,后使用include$(build_executable),表示以一個可執(zhí)行程序的方式進行編譯,在本例中,LOCAL_MODULE被定義為test_exe,因此終生成可執(zhí)行程序的名稱是test_exe,一個可執(zhí)行程序編譯后生成獨立的目標(biāo)目錄在out/target/product/中,路徑如下所示:
/obj/EXECUTABLES/
2、靜態(tài)庫
靜態(tài)庫,也稱之為歸檔文件,在Linux中擴展名通常為.a,在Android.mk中編譯一個靜態(tài)庫(歸檔文件)的模板如下所示:
LOCAL_PATH :=$(my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_SRC_FILES :=
hello.c
LOCAL_C_INCLUDES :=
LOCAL_STATIC_LIBARIES :=
LOCAL_SHARED_LIBRARAIES := libc
include $(BUILD_STATIC_LIBRARY)
在編譯靜態(tài)庫,基本的內(nèi)容和編譯可執(zhí)行程序相似,區(qū)別在于include$(BUILD_STATIC_LIBRARY) 標(biāo)示編譯靜態(tài)庫。在本例中,LOCAL_MODULE被定義為libtest_static,因此終生成的靜態(tài)庫的名稱是libtest_static.a。
3、動態(tài)庫
動態(tài)庫 也稱之為共享庫,是linux標(biāo)準(zhǔn)的elf格式文件的一種,在Linux中擴展名通常為.so在Android中編譯一個動態(tài)庫(共享庫)的模板如下:
LOCAL_PATH := $(my-dir)
include $ (CLEAR_VARS)
LOCAL_MODULE_TAGS :=eng
LOCAL_SRC_FILES :=
hello.c
LOCAL_MODULE := libtest_stared
TARGET_PRELINK_MODULE := false
LOCAL_C_INCLUDES :=
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES := libc
include $ (BUILD_SHARED_LIBRARY)
編譯一個動態(tài)庫,基本的內(nèi)容和編譯可執(zhí)行程序、靜態(tài)庫相似,區(qū)別在于使用include$(BUILD_SHARED_LIBRARY) 表示編譯動態(tài)庫。在本例中,LOCAL_MODULE被定義為libtest_shared,因此終生成的動搖庫的名稱是:libtest_shared.so 一個動態(tài)庫編譯后生成的獨立的目標(biāo)目錄在out/target/product/中,路徑如下所示:
/obj/STATIC_LIBRARIES/
Android 應(yīng)用程序包是一種特殊的文件,通常以apk為擴展名。在Android.mk中編譯一個應(yīng)用程序包的模板如下所示:
LOCAL_PATH := $(CALL my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_PACKAGE_NAME := TestApplication
include $(BUILD_PACKAGE)
這里使用BUILD_PACKAGE宏表示編譯apk,而LOCAL_SRC_FILES 使用自動查找的方法,將找打所有的java文件進行編譯, 在源代碼環(huán)境中編譯和在SDK中編譯應(yīng)用程序包略有不同,涉及的目錄主要有一下兩個。 out/target/common/obj/APPS: 通用java字節(jié)碼目錄
out/target/product/obj/APPS:Android 應(yīng)用包目錄
每個包在兩個目錄中均具有名為{LOCAL_PACKAGE_NAME}_intermediates/的獨立目錄 例如,對于SkeletonApp包編譯,公共目錄的生成結(jié)構(gòu)如下所示:
關(guān)于在編譯應(yīng)用程序的時候,有一個額外的宏可以控制編譯的行為,如下所示:
WITH_DEXPREOPT := true
如果WITH_DEXPREOPT 被定義為true,一個應(yīng)用程序?qū)⒂蓛蓚部分組成:一個是不包含java字節(jié)碼classes.dex的apk文件,一個是名稱為classes.odex的字節(jié)碼文件。
兩個文件同時預(yù)制在系統(tǒng)中依然可以構(gòu)成能運行的應(yīng)用程序。但是,這種生成的結(jié)構(gòu)就不能在進行動態(tài)的安裝了。
Android4.x以上默認(rèn)為true
LOCAL_MODULE := hello-jni
因為模塊名稱也被用于給構(gòu)建過程所生成的文件命名,所以構(gòu)建系統(tǒng)給該文件添加了適當(dāng)?shù)那熬Y和后綴,本例中,hello-jni模塊匯申城一個共享庫文件且構(gòu)建系統(tǒng)會將他命名為hello-jni.so文件,每一個模塊的寫法都基本類似比如:
include $(CLEAR_VARS)
LOCAL_MODULE := MODULE1
LOCAL_SRC_FILES : = MODUE1.C MODULE2.C(這里可以添加多個文件.c)
INCLUDE $(BUILD_SHARED_LIBRARY)
關(guān)于添加構(gòu)建的靜態(tài)庫
Android NDK 構(gòu)建系統(tǒng)也支持靜態(tài)庫。實際的Android應(yīng)用程序并不直接使用靜態(tài)庫,并且應(yīng)用程序包中也不包含靜態(tài)庫。靜態(tài)庫可以用來構(gòu)建共享庫,例如:在將第三方代碼添加到現(xiàn)有原生項目中時,不用直接將第三方源代碼包括在原生項目中,而是將第三方編譯成靜態(tài)庫然后并入共享庫。
代碼:
LOCAL_PATH := $(call my-dir)
inlcude $(CLEAR_VARS)
LOCAL_MODULE :=avilib
LOCAL_SRC_FILES := avilib.c platform_posix.c
include $(BUILD_STATIC_LIBRARY)
#============================
include $(CLEAR_VARS)
LOCAL_MODULE := MODULE
LOCAL_SRC_FILES :=MODULE.C
LOCAL_STATIC_LIBRARIES := avilib
include $(BUILD_SHARED_LIBRARY)
在將第三方代碼模塊生成靜態(tài)庫之后,共享庫就可以通過講它的模塊名添加到LOCAL_STATIC_LIBRARIES變量中來使用該模塊。
用共享庫共享通用模塊
靜態(tài)庫可以保證源代碼模塊化:但是,當(dāng)靜態(tài)庫與共享庫相連是,它就變成了共享庫的一部分,在多個共享庫的情況下,多個共享庫與同一個靜態(tài)庫鏈接時,需要將通用模塊的多個副本與不同共享庫重復(fù)項鏈,這樣就增加了應(yīng)用程序的大小,在這種情況下,不用構(gòu)建靜態(tài)庫而是將通用模塊作為共享庫建立起來,而動態(tài)鏈接依賴模塊以便消除重復(fù)的副本 Android.mk 問價那種共享庫之間的代碼共享。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=avilib
LOCAL_SRC_FILES := avilib.c platform_posix.c
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_ VARS)
LOCAL_MODULE := MODULE2
LOCAL_SRC_FILES := MODULE2.C
LOCAL_SHARED_LIBRARIES := avilib
include $(BUILD_SHARED_LIBRARY)