本文檔介紹了 ndk-build
所使用的 Application.mk
編譯文件。
我們建議先閱讀概念頁面,然后再閱讀本頁面。
概覽
Application.mk
指定了 ndk-build 的項目范圍設置。默認情況下,它位於應用項目目錄中的 jni/Application.mk
下。
注意:其中許多參數也具有模塊等效項。例如,APP_CFLAGS
對應於 LOCAL_CFLAGS
。無論何種情況下,特定於模塊的選項都將優先於應用范圍選項。對於標記,兩者都使用,但特定於模塊的標記將后出現在命令行中,因此它們可能會替換項目范圍設置。
變量
APP_ABI
默認情況下,NDK 編譯系統會為所有非棄用 ABI 生成代碼。您可以使用 APP_ABI
設置為特定 ABI 生成代碼。表 1 顯示了不同指令集的 APP_ABI
設置。
指令集 | 值 |
---|---|
32 位 ARMv7 | APP_ABI := armeabi-v7a |
64 位 ARMv8 (AArch64) | APP_ABI := arm64-v8a |
x86 | APP_ABI := x86 |
x86-64 | APP_ABI := x86_64 |
所有支持的 ABI(默認) | APP_ABI := all |
您也可以指定多個值,方法是將它們放在同一行上,中間用空格分隔。例如:
APP_ABI := armeabi-v7a arm64-v8a x86
注意:Gradle 的 externalNativeBuild
會忽略 APP_ABI
。請在 splits
塊內部使用 abiFilters
塊或(如果使用的是“多個 APK”)abi
塊。
有關所有受支持 ABI 的列表以及有關其用法和限制的詳細信息,請參閱 ABI 管理。
APP_ASFLAGS
要傳遞給項目中每個匯編源文件(.s
和 .S
文件)的匯編器的標記。
注意:ASFLAGS
與 ASMFLAGS
不同。后者專門適用於 YASM 源文件(請參閱 APP_ASMFLAGS 部分)。
APP_ASMFLAGS
對於所有 YASM 源文件(.asm
,僅限 x86/x86_64),要傳遞給 YASM 的標記。
APP_BUILD_SCRIPT
默認情況下,ndk-build 假定 Android.mk 文件位於相對於項目根目錄的 jni/Android.mk
。
要從其他位置加載 Android.mk 文件,請將 APP_BUILD_SCRIPT
設置為 Android.mk 文件的絕對路徑。
注意:Gradle 的 externalNativeBuild
將根據 externalNativeBuild.ndkBuild.path
變量自動配置此路徑。
APP_CFLAGS
要為項目中的所有 C/C++ 編譯傳遞的標記。
注意:Include 路徑應使用 LOCAL_C_INCLUDES
而不是顯式 -I
標記。
另請參閱:APP_CONLYFLAGS、APP_CPPFLAGS。
APP_CLANG_TIDY
要為項目中的所有模塊啟用 clang-tidy,請將此標記設置為“True”。默認處於停用狀態。
APP_CLANG_TIDY_FLAGS
要為項目中的所有 clang-tidy 執行傳遞的標記。
APP_CONLYFLAGS
要為項目中的所有 C 編譯傳遞的標記。這些標記不會用於 C++ 代碼。
另請參閱:APP_CFLAGS、APP_CPPFLAGS。
APP_CPPFLAGS
要為項目中的所有 C++ 編譯傳遞的標記。這些標記不會用於 C 代碼。
另請參閱:APP_CFLAGS、APP_CONLYFLAGS。
APP_CXXFLAGS
注意:APP_CPPFLAGS 應優先於 APP_CXXFLAGS
。
與 APP_CPPFLAGS
相同,但在編譯命令中將出現在 APP_CPPFLAGS
之后。例如:
APP_CPPFLAGS := -DFOO
APP_CXXFLAGS := -DBAR
以上配置將導致編譯命令類似於 clang++ -DFOO -DBAR
,而不是 clang++ -DBAR -DFOO
。
APP_DEBUG
要編譯可調試的應用,請將此標記設置為“True”。
APP_LDFLAGS
關聯可執行文件和共享庫時要傳遞的標記。
注意:這些標記對靜態庫沒有影響。不會關聯靜態庫。
APP_MANIFEST
AndroidManifest.xml 文件的絕對路徑。
默認情況下將使用 $(APP_PROJECT_PATH)/AndroidManifest.xml)
(如果存在)。
注意:使用 externalNativeBuild
時,Gradle 不會設置此值。
APP_MODULES
要編譯的模塊的顯式列表。此列表的元素是模塊在 Android.mk 文件的 LOCAL_MODULE
中顯示的名稱。
默認情況下,ndk-build 將編譯所有共享庫、可執行文件及其依賴項。僅當項目使用靜態庫、項目僅包含靜態庫或者在 APP_MODULES
中指定了靜態庫時,才會編譯靜態庫。
注意:將不會編譯導入的模塊(在使用 $(call import-module)
導入的編譯腳本中定義的模塊),除非要在 APP_MODULES
中編譯或列出的模塊依賴導入的模塊。
APP_OPTIM
將此可選變量定義為 release
或 debug
。默認情況下,將編譯發布二進制文件。
發布模式會啟用優化,並可能生成無法與調試程序一起使用的二進制文件。調試模式會停用優化,以便可以使用調試程序。
請注意,您可以調試發布二進制文件或調試二進制文件。但是,發布二進制文件在調試期間提供的信息較少。例如,變量可能會被優化掉,導致無法檢查代碼。此外,代碼重新排序會使單步調試代碼變得更加困難;堆棧跟蹤可能不可靠。
在應用清單的 <application>
標記中聲明 android:debuggable
將導致此變量默認為 debug
,而不是 release
。通過將 APP_OPTIM
設置為 release
可替換此默認值。
注意:使用 externalNativeBuild
進行編譯時,Android Studio 將根據您的編譯風格適當地設置此標記。
APP_PLATFORM
APP_PLATFORM
會聲明編譯此應用所面向的 Android API 級別,並對應於應用的 minSdkVersion
。
如果未指定,ndk-build 將以 NDK 支持的最低 API 級別為目標。最新 NDK 支持的最低 API 級別總是足夠低,可以支持幾乎所有使用中的設備。
警告:將 APP_PLATFORM
設置為高於應用的 minSdkVersion
可能會生成一個無法在舊設備上運行的應用。在大多數情況下,庫將無法加載,因為它們引用了在舊設備上不可用的符號。
例如,值 android-16
指定庫使用在 Android 4.1(API 級別 16)以前的版本中不可用的 API,並且無法在運行較低平台版本的設備上使用。有關平台名稱和相應 Android 系統映像的完整列表,請參閱 Android NDK 原生 API。
使用 Gradle 和 externalNativeBuild
時,不應直接設置此參數。而是在模塊級別 build.gradle
文件的 defaultConfig
或 productFlavors
塊中設置 minSdkVersion
屬性。這樣就能確保只有在運行足夠高 Android 版本的設備上安裝的應用才能使用您的庫。
請注意,NDK 不包含 Android 每個 API 級別的庫,省略了不包含新的原生 API 的版本以節省 NDK 中的空間。ndk-build 按以下優先級降序使用 API:
- 匹配
APP_PLATFORM
的平台版本。 - 低於
APP_PLATFORM
的下一個可用 API 級別。例如,APP_PLATFORM
為android-20
時,將使用android-19
,因為 android-20 中沒有新的原生 API。 - NDK 支持的最低 API 級別。
APP_PROJECT_PATH
項目根目錄的絕對路徑。
APP_SHORT_COMMANDS
LOCAL_SHORT_COMMANDS
的項目范圍等效項。有關詳情,請參閱 Android.mk 中有關 LOCAL_SHORT_COMMANDS
的文檔。
APP_STL
用於此應用的 C++ 標准庫。
默認情況下使用 system
STL。其他選項包括 c++_shared
、c++_static
和 none
。請參閱 NDK 運行時和功能。
APP_STRIP_MODE
要為此應用中的模塊傳遞給 strip
的參數。默認為 --strip-unneeded
。要避免剝離模塊中的所有二進制文件,請設置為 none
。有關其他剝離模式,請參閱剝離文檔。
APP_THIN_ARCHIVE
要為項目中的所有靜態庫使用瘦歸檔,請將此變量設置為“True”。有關詳情,請參閱 Android.mk 中有關 LOCAL_THIN_ARCHIVE
的文檔。
APP_WRAP_SH
要包含在此應用中的 wrap.sh 文件的路徑。
每個 ABI 都存在此變量的變體,ABI 通用變體也是如此:
APP_WRAP_SH
APP_WRAP_SH_armeabi-v7a
APP_WRAP_SH_arm64-v8a
APP_WRAP_SH_x86
APP_WRAP_SH_x86_64
注意:APP_WRAP_SH_<abi>
無法與 APP_WRAP_SH
相結合。如果任何 ABI 使用特定於 ABI 的 wrap.sh,則所有 ABI 都必須使用該 wrap.sh。