如何寫 Android.mk

本篇記錄一下如何寫 Android.mk,雖然 Google 已經開始全面地改用 Android.bp,但這段過渡期可能還需幾年的時間,Android.mk 的了解以及如何撰寫還是值得學習的。

從 Android 7 Nougat 開始逐漸地改用 Android.bp

如何寫 Android.mk

首先先清理變數

1
2
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

指定模組名與模組變數

LOCAL_MODULE︰模組名稱,這名稱必須是唯一,不能和既有模組相同。 如果 LOCAL_MODULE 未設定,則使用LOCAL_PACKAGE_NAME。 如果再沒有,就會編譯失敗。例如模組名叫做hello,那麼就可以透過 make hello 指令直接編譯hello這個模組。
LOCAL_SRC_FILES︰原始碼檔案列表

引用編譯規則

1
include $(BUILD_EXECUTABLE)

以下這些用來給Android.mk引用的文件及其變數,定義在build/core/config.mk中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
BUILD_COMBOS:= $(BUILD_SYSTEM)/combo

CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
BUILD_NATIVE_BENCHMARK := $(BUILD_SYSTEM)/native_benchmark.mk
BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk

BUILD_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/shared_test_lib.mk
BUILD_HOST_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/host_shared_test_lib.mk
BUILD_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/static_test_lib.mk
BUILD_HOST_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/host_static_test_lib.mk

BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk
BUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mk
BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk

範例:編譯一個可執行檔

模組名稱為 hellowrold,編譯出一個 hellowrold 的執行檔。

1
2
3
4
5
6
7
8
9
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := main.cpp
LOCAL_MODULE := hellowrold
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
LOCAL_SHARED_LIBRARIES :=

include $(BUILD_EXECUTABLE)

範例:編譯一個靜態函式庫

模組名稱為 libfoo,編譯出一個 libfoo.a 的靜態函式庫。

1
2
3
4
5
6
7
8
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := libfoo
LOCAL_SRC_FILES := aaa.cpp
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror

include $(BUILD_STATIC_LIBRARY)

範例:編譯一個動態函式庫

模組名稱為 libfoo,編譯出一個 libfoo.so 的動態函式庫。

1
2
3
4
5
6
7
8
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := libfoo
LOCAL_SRC_FILES := aaa.cpp
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror

include $(BUILD_SHARED_LIBRARY)

範例:編譯一個 APK 文件

1
2
3
4
5
6
7
8
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files) # 獲取所有子目錄中的 Java 文件
LOCAL_STATIC_JAVA_LIBRARIES := static-library # 當前模塊依賴的靜態 Java 庫,如果有多個以空格分隔
LOCAL_PACKAGE_NAME := LocalPackage # 當前模塊的名稱

include $(BUILD_PACKAGE) # 編譯 APK 文件

範例:編譯一個 Java 的靜態函式庫

1
2
3
4
5
6
7
8
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-subdir-java-files) # 獲取所有子目錄中的 Java 文件
LOCAL_JAVA_LIBRARIES := android.test.runner # 當前模塊依賴的動態 Java 庫名稱
LOCAL_MODULE := sample # 當前模塊的名稱

include $(BUILD_STATIC_JAVA_LIBRARY) # 將當前模塊編譯成一個靜態的 Java 庫

下表格為常用與常見的編譯規則

引用編譯規則變數 檔名 說明
BUILD_EXECUTABLE executable.mk 編譯成裝置上的可執行檔
BUILD_STATIC_LIBRARY static_library.mk 編譯成裝置上的靜態函式庫
BUILD_SHARED_LIBRARY shared_library.mk 編譯成裝置上的動態函式庫
BUILD_PREBUILT prebuilt.mk 處理一個預編譯好的檔案 (例如.a, .so, .jar)
BUILD_PACKAGE package.mk 編譯成apk

參考
[1] Android.mk的深入介绍
https://note.qidong.name/2017/08/android-mk/
[2] 理解 Android Build 系統
https://www.ibm.com/developerworks/cn/opensource/os-cn-android-build/