Android.mk

本頁說明了 ndk-build 使用的 Android.mk 建構檔案的語法。

總覽

Android.mk 檔案位於專案 jni/ 目錄的子目錄中,功能為向建構系統說明來源及共用程式庫。它實際上是一個微小的 GNU makefile 片段,建構系統可一次或多次剖析。Android.mk 檔案很適合用來定義 Application.mk、建構系統和環境變數未定義的專案層級設定,還可以覆寫特定模組的專案層級設定

Android.mk 的語法可讓您將來源分到不同模組。模組可以是靜態資料庫、共用程式庫或獨立的可執行檔。您可以在每個 Android.mk 檔案中定義一或多個模組,也可以在多個模組中採用同一個來源檔案。建構系統僅會將共用程式庫放到應用程式套件中。此外,靜態資料庫也能產生共用程式庫。

除了封裝程式庫外,建構系統還可為您處理其他各種事項。舉例來說,您無需在 Android.mk 檔案中列出標頭檔案或產生的檔案之間的顯式依附元件。NDK 建構系統會自動計算這些關係。因此,無需處理 Android.mk 檔案,您就能在未來的 NDK 版本中享有新的工具鏈/平台支援帶來的好處。

這個檔案的語法與隨整個 Android 開放原始碼計畫發布的 Android.mk 檔案中使用的語法非常類似。雖然使用這些語法的建構系統實作並不相同,但透過刻意設計相似的語法,可使應用程式開發人員更輕鬆地重複使用外部程式庫的原始碼。

基本概念

在深入探討語法之前,建議先瞭解 Android.mk 檔案所含內容的基本資訊。因此,本部分將使用 Hello-JNI 範例中的 Android.mk 檔案說明其中每一行的作用。

Android.mk 檔案必須先定義 LOCAL_PATH 變數:

LOCAL_PATH := $(call my-dir)

這個變數代表來源檔案在開發樹狀結構中的位置。這裡的巨集函式 my-dir 由建構系統提供,並且會傳回目前目錄 (Android.mk 檔案本身所在的目錄) 的路徑。

下一行會宣告 CLEAR_VARS 變數,這個變數的值由建構系統提供。

include $(CLEAR_VARS)

CLEAR_VARS 變數會指向一個特殊的 GNU Makefile,它會清除許多 LOCAL_XXX 變數,例如 LOCAL_MODULELOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES。請注意,GNU Makefile 不會清除 LOCAL_PATH。這個變數必須保留其值,因為系統會在單一 GNU Make 執行情境中 (其中所有變數均為全域變量) 剖析所有建構控制檔案。您必須 (重新) 宣告這個變數,才能說明每個模組。

接著,LOCAL_MODULE 變數會儲存您要建構的模組名稱。請在應用程式的每個模組中使用一次這個變數。

LOCAL_MODULE := hello-jni

每個模組的名稱皆不得重複,且不可含任何空格。建構系統產生最終共用程式庫檔案時,會自動在您指派給 LOCAL_MODULE 的名稱中加入適當的前置字串和後置字串。例如,上述範例會產生名稱為 libhello-jni.so 的程式庫。

下一行會列舉來源檔案,並以空格分隔多個檔案:

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SRC_FILES 變數必須包含要建構到模組中的 C 和/或 C ++ 來源檔案清單。

最後一行能協助系統結合所有內容:

include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY 變數會指向 GNU Makefile 指令碼,這個指令碼會收集您自最近 include 以來在 LOCAL_XXX 變數中定義的所有資訊。這個指令碼會決定要建構的內容和建構方法。

在範例目錄中有更複雜的範例,您還可以查看含註解的 Android.mk 檔案。此外,範例:native-activity 詳細說明了該範例的 Android.mk 檔案。最後,變數和巨集進一步說明了本部分中的變數。

變數和巨集

建構系統提供許多可在 Android.mk 檔案中使用的變數。其中許多變數已預先賦值,其他則由您賦值。

除了這些變數外,您還可以自行定義任意變數。定義變數時,請注意 NDK 建構系統會保留下列變數名稱:

  • 開頭為 LOCAL_ 的名稱,例如 LOCAL_MODULE
  • 開頭為 PRIVATE_NDK_APP 的名稱。建構系統會在內部使用這些名稱。
  • 小寫名稱,例如 my-dir。建構系統也會在內部使用這些名稱。

如果您需要在 Android.mk 檔案中定義自己的便利變數,建議在名稱前加上 MY_

NDK 定義的 include 變數

本部分會討論在剖析 Android.mk 檔案前,建構系統定義的 GNU Make 變數。在某些情況下,NDK 可能會多次剖析您的 Android.mk 檔案,每次都針對某些變數使用不同的定義。

CLEAR_VARS

這個變數指向的建構指令碼,會取消定義下方「開發人員定義的變數」部分中所列的幾乎所有 LOCAL_XXX 變數。在說明新模組之前,請使用這個變數來加入這個指令碼。使用語法如下:

include $(CLEAR_VARS)

BUILD_EXECUTABLE

這個變數指向的建構指令碼會收集您在 LOCAL_XXX 變數中所提供模組的所有相關資訊,並決定如何根據您列出的來源建構目標執行檔。請注意,使用這個指令碼時,您應至少已經為 LOCAL_MODULELOCAL_SRC_FILES 賦值。如要進一步瞭解這些變數,請參閱模組說明變數

這個變數的使用語法如下:

include $(BUILD_EXECUTABLE)

BUILD_SHARED_LIBRARY

這個變數指向的建構指令碼會收集您在 LOCAL_XXX 變數中所提供模組的所有相關資訊,並決定如何根據您列出的來源建構目標共用程式庫。請注意,使用這個指令碼時,您應至少已經為 LOCAL_MODULELOCAL_SRC_FILES 賦值。如要進一步瞭解這些變數,請參閱模組說明變數

這個變數的使用語法如下:

include $(BUILD_SHARED_LIBRARY)

共用程式庫變數會使建構系統產生副檔名為 .so 的程式庫檔案。

BUILD_STATIC_LIBRARY

用於建構靜態資料庫的 BUILD_SHARED_LIBRARY 的變體。建構系統不會將靜態資料庫複製到專案/套件,但可以使用靜態資料庫建構共用程式庫 (請參閱下方的 LOCAL_STATIC_LIBRARIESLOCAL_WHOLE_STATIC_LIBRARIES)。這個變數的使用語法如下:

include $(BUILD_STATIC_LIBRARY)

靜態資料庫變數會使建構系統產生副檔名為 .a 的程式庫。

PREBUILT_SHARED_LIBRARY

指向用於指定預建共用程式庫的建構指令碼。與 BUILD_SHARED_LIBRARYBUILD_STATIC_LIBRARY 的情況不同,這裡的 LOCAL_SRC_FILES 值不能是來源檔案,而必須是指向預建共用程式庫 (例如 foo/libfoo.so) 的單一路徑。這個變數的使用語法如下:

include $(PREBUILT_SHARED_LIBRARY)

您也可以使用 LOCAL_PREBUILTS 變數參照其他模組中的預建程式庫。如要進一步瞭解如何使用預建程式庫,請參閱使用預建程式庫

PREBUILT_STATIC_LIBRARY

PREBUILT_SHARED_LIBRARY 相同,但用於預建靜態資料庫。如要進一步瞭解如何使用預建程式庫,請參閱使用預建程式庫

目標資訊變數

建構系統會為 APP_ABI 變數指定的每個 ABI 剖析 Android.mk 一次,該變數通常是在 Application.mk 檔案中定義。如果 APP_ABIall,則建構系統會為 NDK 支援的每個 ABI 剖析 Android.mk 一次。本部分會說明建構系統每次剖析 Android.mk 時定義的變數。

TARGET_ARCH

建構系統在剖析此 Android.mk 檔案時指定的 CPU 系列。這個變數會是以下其中一項:armarm64x86x86_64

TARGET_PLATFORM

建構系統在剖析此 Android.mk 檔案時指定的 Android API 級別號碼。舉例來說,Android 5.1 系統映像檔會對應 Android API 級別 22:android-22。如需平台名稱與對應 Android 系統映像檔的完整清單,請參閱原生 API。以下範例為這個變數的使用語法:

ifeq ($(TARGET_PLATFORM),android-22)
    # ... do something ...
endif

TARGET_ARCH_ABI

建構系統在剖析此 Android.mk 檔案時指定的 ABI。表 1 顯示了各支援的 CPU 和架構使用的 ABI 設定。

表 1. 不同 CPU 和架構的 ABI 設定。

CPU 和架構 設定
ARMv7 armeabi-v7a
ARMv8 AArch64 arm64-v8a
i686 x86
x86-64 x86_64

以下範例說明了如何檢查 ARMv8 AArch64 是否為目標 CPU 與 ABI 組合:

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
  # ... do something ...
endif

如要進一步瞭解架構 ABI 和相關相容性問題,請參閱 Android ABI

日後的新目標 ABI 將會使用不同的值。

TARGET_ABI

目標 Android API 級別和 ABI 的串連,特別適用於要對實際裝置測試特定目標系統映像檔的情況。例如,如要檢查在 Android API 級別 22 上執行的 64 位元 ARM 裝置:

ifeq ($(TARGET_ABI),android-22-arm64-v8a)
  # ... do something ...
endif

模組說明變數

本部分中的變數會向建構系統說明您的模組。每個模組說明應遵循下列基本流程:

  1. 使用 CLEAR_VARS 變數來初始化或取消定義與模組相關的變數。
  2. 為用於說明模組的變數賦值。
  3. 使用 BUILD_XXX 變數設定 NDK 建構系統,以便將適當的建構指令碼用於模組。

LOCAL_PATH

這個變數用於提供目前檔案的路徑。您必須在 Android.mk 檔案的開頭定義這個變數。以下範例說明了如何定義:

LOCAL_PATH := $(call my-dir)

CLEAR_VARS 指向的指令碼不會清除這個變數。因此,即使 Android.mk 檔案說明多個模組,只需定義這個變量一次即可。

LOCAL_MODULE

這個變數會儲存模組名稱。模組名稱皆不得重複,且不可包含任何空格。您必須先定義這個名稱,才能家入任何指令碼 (CLEAR_VARS 的指令碼除外)。您不需要加上 lib 前置字串,或 .so.a 副檔名,建構系統會自動進行這些修改。在整個 Android.mkApplication.mk 檔案中,請用未修改的名稱參照模組。例如,下列程式碼會產生名為 libfoo.so 的共用程式庫模組:

LOCAL_MODULE := "foo"

如果您想讓產生的模組使用「lib + LOCAL_MODULE 的值」以外的名稱,可以使用 LOCAL_MODULE_FILENAME 變數自行為產生的模組命名。

LOCAL_MODULE_FILENAME

這個選用變數可讓您覆寫建構系統產生的檔案預設使用的檔案名稱。舉例來說,如果 LOCAL_MODULE 的名稱為 foo,您可以強制系統將其產生的檔案命名為 libnewfoo。以下將示範如何完成這項操作:

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo

針對共用程式庫模組,這個範例會產生名為 libnewfoo.so 的檔案。

LOCAL_SRC_FILES

這個變數包含建構系統產生模組時所使用的來源檔案清單。由於建構系統會自動計算任何相關聯的依附元件,因此清單中只會列出建構系統實際傳遞給編譯器的檔案。請注意,您可以同時使用相對 (相對於 LOCAL_PATH) 和絕對檔案路徑。

但建議您避免使用絕對檔案路徑;相對路徑可以提高 Android.mk 檔案的移植性。

LOCAL_CPP_EXTENSION

您可以使用這個選用變數為 C++ 來源檔案指定 .cpp 以外的副檔名。例如,下列程式碼會將副檔名變更為 .cxx (設定中必須包含點)。

LOCAL_CPP_EXTENSION := .cxx

您可以使用這個變數指定多個副檔名。例如:

LOCAL_CPP_EXTENSION := .cxx .cpp .cc

LOCAL_CPP_FEATURES

您可以使用這個選用變數指示程式碼需要特定的 C++ 功能,並在建構程序中啟用正確的編譯器和連結器標記。如果是預建的二進位檔,此變數也會宣告二進位檔需要的功能,進而確保最終連結可以正常運作。建議您使用這個變數,而不要直接在 LOCAL_CPPFLAGS 定義中啟用 -frtti-fexceptions

如果使用這個變數,建構系統就能針對每個模組使用適當的標記。使用 LOCAL_CPPFLAGS 會導致編譯器針對所有模組使用所有指定的標記,而不管實際需求為何。

例如,如要指示您的程式碼使用 RTTI (執行階段類型資訊),請輸入:

LOCAL_CPP_FEATURES := rtti

如要指示程式碼使用 C++ 例外狀況,請輸入:

LOCAL_CPP_FEATURES := exceptions

您也可以為這個變數指定多個值。例如:

LOCAL_CPP_FEATURES := rtti features

說明值的順序無關緊要。

LOCAL_C_INCLUDES

您可以使用這個選用變數來指定相對於 NDK root 目錄的路徑清單,以便在編譯所有來源 (C、C++ 和 Assembly) 時新增至 include 搜尋路徑。例如:

LOCAL_C_INCLUDES := sources/foo

或甚至:

LOCAL_C_INCLUDES := $(LOCAL_PATH)/<subdirectory>/foo

透過 LOCAL_CFLAGSLOCAL_CPPFLAGS 設定任何對應的包含標記前,請定義這項變數。

使用 ndk-gdb 啟動原生偵錯時,建構系統也會自動使用 LOCAL_C_INCLUDES 路徑。

LOCAL_CFLAGS

這個選用變數會在建構 C 和 C ++ 來源檔案時,設定建構系統要傳遞的編譯器標記。這樣一來,您就可以指定額外的巨集定義或編譯選項。使用 LOCAL_CPPFLAGS 即可指定僅限 C++ 的標記。

請勿嘗試在 Android.mk 檔案中變更最佳化/偵錯層級。 建構系統可以使用 Application.mk 檔案中的相關資訊自動處理這項設定,這樣建構系統就可以產生偵錯期間會用到的實用資料檔案。

您可以編寫以下程式碼來指定其他 include 路徑:

LOCAL_CFLAGS += -I<path>,

但是,要這麼做的話最好使用 LOCAL_C_INCLUDES,因為這樣也可以使用適用於 ndk-gdb 原生偵錯的路徑。

LOCAL_CPPFLAGS

建構 C++ 來源檔案時將傳遞的一組選用編譯器標記,這些標記會顯示在編譯器指令列的 LOCAL_CFLAGS 後方。使用 LOCAL_CFLAGS 同時指定 C 和 C++ 的標記。

LOCAL_STATIC_LIBRARIES

這個變數會儲存目前模組依附的靜態資料庫模組清單。

如果目前的模組是共用程式庫或執行檔,這個變數會強制將這些程式庫連結至產生的二進位檔。

如果目前的模組是靜態資料庫,則這個變數只會指示依附目前模組的其他模組也會依附列出的程式庫。

LOCAL_SHARED_LIBRARIES

這個變數會列出此模組在執行階段所依附的共用程式庫模組。連結時必須使用這項資訊,並在產生的檔案中嵌入對應資訊。

LOCAL_WHOLE_STATIC_LIBRARIES

這個變數是 LOCAL_STATIC_LIBRARIES 的變體,表示連結器應將相關程式庫模組視為完整封存檔案。如要進一步瞭解完整封存內容,請參閱 --whole-archive 標記的 GNU ld 說明文件

當多個靜態資料庫之間存在循環依附元件時,這個變數就十分有用。使用這個變數建構共用程式庫時,即會強制建構系統將靜態資料庫中的所有物件檔案新增至最終二進位檔。然而,產生執行檔時不會發生這種情況。

LOCAL_LDLIBS

這個變數列出了建構共用程式庫或執行檔時可使用的其他連結器標記。利用這個變量,您可使用 -l 前置字串傳遞特定系統程式庫的名稱。例如,以下範例會指示連結器產生要在載入時連結至 /system/lib/libz.so 的模組:

LOCAL_LDLIBS := -lz

如需此 NDK 版本中可供連結的公開系統程式庫清單,請參閱原生 API

LOCAL_LDFLAGS

這個變數列出了建構系統在建構共用程式庫或執行檔時可使用的其他連結器標記。例如,如要在 ARM/X86 上使用 ld.bfd 連結器:

LOCAL_LDFLAGS += -fuse-ld=bfd

LOCAL_ALLOW_UNDEFINED_SYMBOLS

根據預設,如果建構系統在嘗試建構共用程式庫時遇到未定義的參照,將會擲回「未定義的符號」錯誤。這個錯誤有助於找出原始碼中的錯誤。

如要停用這項檢查,請將這個變數設為 true。請注意,這項設定可能會導致共用程式庫在執行階段載入。

LOCAL_ARM_MODE

根據預設,建構系統會以 thumb 模式產生 ARM 目標二進位檔,其中每則指令的寬度為 16 位元,並與 thumb/ 目錄中的 STL 程式庫連結。將這個變數定義為 arm,即可強制建構系統以 32 位元的 arm 模式產生模組的物件檔案。以下示範如何進行這項操作:

LOCAL_ARM_MODE := arm

您也可以為來源檔案名稱加上 .arm 後置字串,藉此指示建構系統僅建構 arm 模式的特定來源。例如,下列範例指示建構系統一律以 ARM 模式編譯 bar.c,但根據 LOCAL_ARM_MODE 的值建構 foo.c

LOCAL_SRC_FILES := foo.c bar.c.arm

LOCAL_ARM_NEON

只有在以 armeabi-v7a ABI 為目標時,這個變數才有意義。它可讓您在 C 和 C++ 來源中使用 ARM Advanced SIMD (NEON) 編譯器內建函式,以及在 Assembly 檔案中使用 NEON 指示。

請注意,並非所有 ARMv7 型的 CPU 都支援 NEON 指令集擴充功能。因此,您必須進行執行階段偵測,才能在執行階段安全地使用這個程式碼。詳情請參閱 Neon 支援CPU 功能

此外,您也可以使用 .neon 後置字串,來指定建構系統僅以 NEON 支援編譯特定來源檔案。在下列範例中,建構系統以 Thumb 和 Neon 支援編譯 foo.c,以 Thumb 支援編譯 bar.c,並以 ARM 和 NEON 支援編譯 zoo.c

LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon

如果同時使用這兩種後置字串,.arm 必須在 .neon 前面。

LOCAL_DISABLE_FORMAT_STRING_CHECKS

根據預設,建構系統會在編譯程式碼時保護格式字串。這麼一來,如果在 printf 樣式的函式中使用了非常數格式的字串時,就會強制觸發編譯器錯誤。這項保護功能預設為開啟,但您可以將這個變數的值設為 true 來停用功能。非必要情況下不建議停用。

LOCAL_EXPORT_CFLAGS

這個變數會記錄一組 C/C++ 編譯器標記,這些標記將新增至透過 LOCAL_STATIC_LIBRARIESLOCAL_SHARED_LIBRARIES 變數使用這個模組的任何其他模組的 LOCAL_CFLAGS 定義。

例如,假設有下列模組對 foobar,依附 foo

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)


include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_CFLAGS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

在這個範例中,建構系統在建構 bar.c 時會向編譯器傳遞 -DFOO=1-DBAR=2 標記,也會在模組的 LOCAL_CFLAGS 前面加上匯出的標記,以便您輕鬆覆寫。

此外,模組間的關係具有轉移性:如果 zoo 依附 bar,後者則依附 foo,那麼 zoo 也會沿用從 foo 匯出的所有標記。

最後,建構系統在執行本機建構時 (即建構要匯出標記的模組),不會使用匯出的標記。因此,在上述範例中,建構系統在建構 foo/foo.c 時不會將 -DFOO=1 傳遞給編譯器。如要執行本機建構,請改用 LOCAL_CFLAGS

LOCAL_EXPORT_CPPFLAGS

這個變數與 LOCAL_EXPORT_CFLAGS 相同,但僅適用於 C++ 標記。

LOCAL_EXPORT_C_INCLUDES

這個變數與 LOCAL_EXPORT_CFLAGS 相同,但僅適用於 C include 路徑。舉例來說,當 bar.c 需要包含模組 foo 的標頭時,這個變數就非常實用。

LOCAL_EXPORT_LDFLAGS

這個變數與 LOCAL_EXPORT_CFLAGS 相同,但適用於連結器標記。

LOCAL_EXPORT_LDLIBS

這個變數與 LOCAL_EXPORT_CFLAGS 相同,會指示建構系統將特定系統程式庫的名稱傳遞給編譯器。請在您指定的每個程式庫名稱前面加上 -l

請注意,建構系統會將匯入的連結器標記附加至模組的 LOCAL_LDLIBS 變數值上。原因在於 Unix 連結器的運作方式。

foo 是靜態資料庫,且具依附系統程式庫的程式碼時,這個變數通常很實用。接著,您可以使用 LOCAL_EXPORT_LDLIBS 匯出依附元件。例如:

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

在這個範例中,建構系統於建構 libbar.so 時,將 -llog 置於連結器指令尾部。這麼做會告知連結器,因為 libbar.so 依附 foo,所以也依附系統記錄程式庫。

LOCAL_SHORT_COMMANDS

如果您的模組有很多來源和/或依附的靜態或共用程式庫,請將這個變數設為 true,這樣會強制建構系統針對含有中繼物件檔案或連結程式庫的封存使用 @ 語法。

這項功能在 Windows 上相當實用,因為在 Windows 上指令列最多只接受 8191 個字元,而這對複雜的專案來說可能太少。這項功能也會影響個別來源檔案的編譯作業,而且將幾乎所有編譯器標記都放入清單檔案。

請注意,true 以外的任何值都會還原為預設行為。您也可以在 Application.mk 檔案中定義 APP_SHORT_COMMANDS,對專案中的所有模組強制實施這項行為。

我們不建議預設啟用這項功能,因為這會減慢建構速度。

LOCAL_THIN_ARCHIVE

建構靜態資料庫時,請將這個變數設為 true。這樣會產生一個精簡封存,也就是不含物件檔案的程式庫檔案,而只會包含其通常包含的實際物件檔案路徑。

這有助於縮減建構輸出內容的大小,但缺點是這類程式庫無法移至其他位置 (其中的所有路徑都是相對路徑)。

有效值為 truefalse 或空白,您可在 Application.mk 檔案中透過 APP_THIN_ARCHIVE 變數設定預設值。

LOCAL_FILTER_ASM

請將這個變數定義為殼層指令,供建構系統用於篩選根據您位 LOCAL_SRC_FILES 指定的檔案擷取或產生的組合檔案。定義這個變數會造成以下結果:

  1. 建構系統從任何 C 或 C++ 來源檔案產生臨時組合檔案,而不是將這些檔案編譯入物件檔案。
  2. 建構系統在任何臨時組合檔案和 LOCAL_SRC_FILES 中所列任何組合檔案的 LOCAL_FILTER_ASM 中執行殼層指令,因此會產生另一個臨時組合檔案。
  3. 建構系統將這些篩選的組合檔案編譯入物件檔案。

例如:

LOCAL_SRC_FILES  := foo.c bar.S
LOCAL_FILTER_ASM :=

foo.c --1--> $OBJS_DIR/foo.S.original --2--> $OBJS_DIR/foo.S --3--> $OBJS_DIR/foo.o
bar.S                                 --2--> $OBJS_DIR/bar.S --3--> $OBJS_DIR/bar.o

「1」對應於編譯器,「2」對應於篩選器,「3」則對應於組合器。篩選器必須是獨立的殼層指令,並使用輸入檔案名稱做為第一個引數,將輸出檔案名稱做為第二個引數。例如:

myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S

NDK 提供的函式巨集

本部分說明了 NDK 提供的 GNU Make 函式巨集。使用 $(call <function>) 進行評估,函式巨集會傳回文字資訊。

my-dir

這個巨集會傳回最後包含的 makefile 的路徑,通常是目前 Android.mk 的目錄。my-dir 適合用來在 Android.mk 檔案開頭定義 LOCAL_PATH。例如:

LOCAL_PATH := $(call my-dir)

由於 GNU Make 的運作方式,這個巨集實際傳回的是建構系統剖析建構指令碼時包含的最後一個 makefile。因此,包含其他檔案後就不應呼叫 my-dir

例如,請看以下範例:

LOCAL_PATH := $(call my-dir)

# ... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(call my-dir)

# ... declare another module

這裡的問題在於,對 my-dir 的第二次呼叫將 LOCAL_PATH 定義為 $PATH/foo,而非 $PATH,因為這是其最近的 include 指向的位置。

如要避免這個問題,請在 Android.mk 檔案中的任何其他內容後面指定其他 include。例如:

LOCAL_PATH := $(call my-dir)

# ... declare one module

LOCAL_PATH := $(call my-dir)

# ... declare another module

# extra includes at the end of the Android.mk file
include $(LOCAL_PATH)/foo/Android.mk

如果無法以這種方式建構檔案,請將第一個 my-dir 呼叫的值儲存至其他變數。例如:

MY_LOCAL_PATH := $(call my-dir)

LOCAL_PATH := $(MY_LOCAL_PATH)

# ... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

LOCAL_PATH := $(MY_LOCAL_PATH)

# ... declare another module

all-subdir-makefiles

傳回位於目前 my-dir 路徑所有子目錄中的 Android.mk 檔案清單。

您可以使用此函式為建構系統提供深度巢狀來源目錄階層。根據預設,NDK 只會在 Android.mk 檔案所在的目錄中尋找檔案。

this-makefile

傳回目前 makefile (建構系統從中呼叫函式) 的路徑。

parent-makefile

傳回包含樹狀結構中父項 makefile 的路徑 (包含目前檔案的 makefile 的路徑)。

grand-parent-makefile

傳回包含樹狀結構中祖父項 makefile 的路徑 (包含目前檔案的 makefile 的路徑)。

import-module

這個函式可用來依模組名稱尋找和包含模組的 Android.mk 檔案。常見的範例如下:

$(call import-module,<name>)

在這個範例中,建構系統在 NDK_MODULE_PATH 環境變數所參照的目錄清單中,尋找具有 <name> 標記的模組,並自動包含其 Android.mk 檔案。