1. Android.mk 介紹
Android.mk 是Android 提供的一種makefile 文件,注意用來編譯生成 exe(二進制可執(zhí)行文件)装盯、so(動態(tài)庫文件)、a(靜態(tài)庫文件)屯吊、jar(jar包) 和 apk 等文件逢倍。Android.mk和一個或多個.c的源文件放在同一目錄下做為一個模塊,通過mm或者mmm命令來編譯該模塊竿刁,生成自己所需的文件黄锤,如:二進制的可執(zhí)行文件、動態(tài)庫食拜、靜態(tài)庫鸵熟、jar包和apk「旱椋可參考原生的Android.mk文件進行修改來編寫適合自己的Android.mk文件流强,故需要掌握Android.mk的基本語法痹届。
通過make命令可以編譯整個android源碼;mm指令編譯當(dāng)前目錄(單獨模塊的編譯)打月;mmm指令就是用來編譯指定目錄(單獨模塊的編譯)短纵。
2. Android.mk 基本語法
2.1 Android.mk 基本語法格式示例:
- 配置環(huán)境變量:定義當(dāng)前模塊的相對路徑
LOCAL_PATH := $(call my-dir) - 清空當(dāng)前環(huán)境變量:除 LOCAL_PATH 外的所有環(huán)境變量
include $(CLEAR_VARS) - 編譯所生成的目標(biāo)文件的文件名
LOCAL_MODULE := test - 編譯該模塊所需的源文件:使用連接符“\”連接多個源文件
LOCAL_SRC_FILES := test.c - 編譯所生成的目標(biāo)文件的格式(類型):
include $(BUILD_EXECUTABLE)
2.2 編譯生成的目標(biāo)文件類型:
- EXECUTABLES:二進制可執(zhí)行文件
- SHARED_LIBRARIES:動態(tài)庫文件
- STATIC_LIBRARY:靜態(tài)庫文件
- JAVA_LIBRARIES:jar包
- PACKAGE:apk
2.3 Android.mk 中引用資源:
- 引用系統(tǒng)靜態(tài)庫 —> LOCAL_STATIC_LIBRARIES += libxxx
- 引用系統(tǒng)動態(tài)庫 —> LOCAL_SHARED_LIBRARIES += libxxx
如引用系統(tǒng)動態(tài)庫:LOCAL_SHARED_LIBRARIES += liblog
- 引用第三方庫文件 —> LOCAL_LDFLAGS := -L/PATH -lxxx
如引用第三方動態(tài)庫:LOCAL_LDFLAGS := -L$(LOCAL_PATH)/lib/ -ltest3
如引用第三方靜態(tài)庫:LOCAL_LDFLAGS := $(LOCAL_PATH)/lib/libtest2.a
- 引用第三方頭文件 —> LOCAL_C_INCLUDES := path
如:LOCAL_C_INCLUDES = $(INCLUDES)
- 引入頭文件等 —> LOCAL_xxx := xxx
- 引入jar包等 —> LOCAL_xxx := xxx
如引入共享(動態(tài))jar包:LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 guava
3 Android.mk管理源碼文件(指定編譯所需的源碼文件)
3.1 編譯多個源碼文件
問題:一個工程下有多個源碼文件,怎么統(tǒng)一管理進行編譯僵控?
解答:將工程下的多個源碼文件添加到Android.mk的變量LOCAL_SRC_FILES中
(1)方法一: 使用連接符“\”將每個源文件添加到Android.mk中 (2) 方法一: 使用系統(tǒng)提供的函數(shù)處理
3.2 一個Android.mk 文件編譯生成多個目標(biāo)文件
問題:如何在一個Android.mk 文件編譯生成多個目標(biāo)文件香到?如同時生成多個 bin 文件(二進制可執(zhí)行文件)、.so 文件(動態(tài)庫文件)和 .a 文件(靜態(tài)庫文件)报破。
解答:LOCAL_PATH變量不變悠就,其他變量復(fù)制并重新進行配置
4 Android.mk 管理編譯所生成的目標(biāo)文件類型
4.1 編譯生成 exe、so 或 a 文件 —> 源文件為 C/C++ 文件
- 如何編譯生成二進制可執(zhí)行文件exe->修改編譯類型為:
BULID_EXECUTABLE
- 如何編譯生成動態(tài)庫文件so->修改編譯類型為:
BULID_SHARED_LIBRARY
- 如何編譯生成靜態(tài)庫文件a->修改編譯類型為:
BULID_STATIC_LIBRARY
(1) 指定編譯生成的文件類型
(2) 編譯生成各類目標(biāo)文件
4.2 編譯生成 jar 包或 apk文件 —> 源文件為 java 文件
(1) 編譯生成 jar 包
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := com.test.myjar
include $(BUILD_JAVA_LIBRARY)
- 靜態(tài)jar包:include $(BUILD_STATIC_JAVA_LIBRARY)
使用.class文件打包而成的JAR文件充易,可以在任何java虛擬機運行 - 動態(tài)jar包:include $(BUILD_JAVA_LIBRARY)
在靜態(tài)jar包基礎(chǔ)之上使用.dex打包而成的jar文件梗脾,.dex是android系統(tǒng)使用的文件格式。
(2) 編譯生成 apk
語法:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := LocalPackage
include $(BUILD_PACKAGE)
- LOCAL_SRC_FILES := $(call all-subdir-java-files) —> 獲取當(dāng)前目錄下所有的java文件作為源文件
- LOCAL_PACKAGE_NAME := LocalPackage —> 編譯生成的目標(biāo)文件名為LocalPackage
- include $(BUILD_PACKAGE) —> 編譯生成的目標(biāo)文件類型為apk
注
:若apk依賴于jar包盹靴,即在apk中導(dǎo)入jar包和庫文件的語法為
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_JAVA_LIBRARIES := share-library
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := LocalPackage
include $(BUILD_PACKAGE)
- apk中導(dǎo)入靜態(tài)jar包 —> LOCAL_STATIC_JAVA_LIBRARIES := static-library
- apk中導(dǎo)入動態(tài)(系統(tǒng)/共享)jar包 —> LOCAL_JAVA_LIBRARIES := share-library
如:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 guava
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Calculator
include $(BUILD_PACKAGE)
5. Android.mk 引入各種庫和頭文件
5.1 在工程引入系統(tǒng)庫
工程如何引入系統(tǒng)庫
:將源文件中使用的系統(tǒng)庫添加到Android.mk中炸茧,即LOCAL_SHARED_LIBRARIES += libxxx
。libxxx 代表系統(tǒng)庫名稱稿静。
(1) 如:新建源文件main.cpp中使用了系統(tǒng)函數(shù) ALOGE("")
#include <stdio.h>
#define LOG_TAG "Main"
#include <utils/Log.h>
int main(void)
{
ALOGE("test");
return 0;
}
(2) 將源文件main.cpp添加至Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= test3
LOCAL_C_ALL_FILES := src/main.cpp
LOCAL_SRC_FILES := $(LOCAL_C_ALL_FILES)
LOCAL_MODULE_PATH := $(LOCAL_PATH)/bin
include $(BUILD_EXECUTABLE)
(3) 直接編譯報錯:沒用將源碼中使用的系統(tǒng)庫文件引入工程
(4) 修改Android.mk:將源文件main.cpp中使用的系統(tǒng)函數(shù)對應(yīng)的庫liblog加入梭冠,即添加LOCAL_SHARED_LIBRARIES += liblog
(5) 重新編譯成功
5.2 在工程引入第三方庫
說明1:新建源文件test1.cpp
#include <stdio.h>
void call_test(void)
{
printf("test1\n");
return;
}
說明2:Android.mk文件如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libtest3
LOCAL_C_ALL_FILES := src/test1.cpp
LOCAL_SRC_FILES := $(LOCAL_C_ALL_FILES)
LOCAL_MODULE_PATH := $(LOCAL_PATH)/lib
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= test3
LOCAL_C_ALL_FILES := src/main.cpp
LOCAL_SHARED_LIBRARIES += liblog
LOCAL_SRC_FILES := $(LOCAL_C_ALL_FILES)
LOCAL_MODULE_PATH := $(LOCAL_PATH)/bin
include $(BUILD_EXECUTABLE)
備注:test1.cpp編譯生成了動態(tài)庫libtest3.so文件(相當(dāng)于第三方庫文件),main.cpp編譯生成了二進制可執(zhí)行test3文件改备。
5.2.1 引入第三方動態(tài)庫
工程如何引入第三方動態(tài)庫
:將源文件中使用的第三方庫添加到Android.mk中控漠,即LOCAL_LDFLAGS := -L/Path -lxxx
。Path 代表第三方庫路徑悬钳,xxx代表第三方庫名稱 or 編譯生成的目標(biāo)文件名
(1) 如:工程源文件main.cpp調(diào)用了test1.cpp中的函數(shù)盐捷,通過extern的方式
(2) 直接編譯則會報錯:
(3) 需修改Android.mk:引入第三方庫libtest3.so文件,即添加:LOCAL_LDFLAGS := -L ./lib/ -ltest3 或LOCAL_LDFLAGS := -L$(LOCAL_PATH)/lib/ -ltest3
(4) 重新編譯成功
5.2.2 引入第三方頭文件
說明1:頭文件test1.h 文件如下
#ifndef TEST1 H
#define TEST1 H
extern void call_test(void);
#endif
說明2:Android.mk文件如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libtest3
LOCAL_C_ALL_FILES := src/test1.cpp
LOCAL_SRC_FILES := $(LOCAL_C_ALL_FILES)
LOCAL_MODULE_PATH := $(LOCAL_PATH)/lib
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= test3
LOCAL_LDFLAGS := -L ./lib/ -ltest3
#LOCAL_LDFLAGS := -L$(LOCAL_PATH)/lib/ -ltest3
LOCAL_C_ALL_FILES := src/main.cpp
LOCAL_SHARED_LIBRARIES += liblog
LOCAL_SRC_FILES := $(LOCAL_C_ALL_FILES)
LOCAL_MODULE_PATH := $(LOCAL_PATH)/bin
include $(BUILD_EXECUTABLE)
工程如何引入第三方頭文件
:在Android.mk文件中配置頭文件路徑LOCAL_C_INCLUDES := Path
默勾。Path 代表頭文件的路徑碉渡。
(1) 如:工程源文件main.cpp調(diào)用了test1.cpp中的函數(shù),通過頭文件的方式
(2) 當(dāng)頭文件的路徑和main.cpp的路徑相差很多時母剥,可通過以下方式來引入頭文件
5.2.3 引入第三方靜態(tài)庫
工程如何引入第三方靜態(tài)庫
:將源文件中使用的第三方庫靜態(tài)庫添加到Android.mk中滞诺,即LOCAL_LDFLAGS := Path
。Path 代表第三方庫靜態(tài)庫的路徑媳搪。
6. Android.mk 中使用判斷語句
語法:
ifeq($(VALUE), x)
do_yes
else
do_no
endif
或
ifneq($(VALUE), x)
do_yes
else
do_no
endif
如: