Android NDK-0.ndk-build的Android.mk和Android.mk簡介
文章目錄
ndk-build是什麼
ndk-build 檔案是 Android NDK r4 中引入的一個 shell 指令碼。其用途是呼叫正確的 NDK 構建指令碼。可以用這個命令來生成.so檔案。
ndk-build如何使用
當你想使用該命令將.cpp/.c檔案生成.so檔案,必須有具備以下幾個條件
- 需有Android.mk檔案,並且與對應的.cpp/.c檔案在同一個大目錄下,.cpp/.c檔案可以在子目錄,Android.mk中用相對路徑標識。
- 需要有Application.mk檔案,一般位於最上層大目錄。
什麼是Android.mk
參看谷歌官方的參考
變數:
LOCAL_PATH
Android.mk 檔案必須首先定義 LOCAL_PATH
變數:
LOCAL_PATH := $(call my-dir)
my-dir
將返回當前目錄(包含 Android.mk 檔案本身的目錄)的路徑。
CLEAR_VARS
下一行宣告 CLEAR_VARS
變數,其值由構建系統提供。
include $(CLEAR_VARS)
CLEAR_VARS
變數指向特殊 GNU Makefile,可為您清除許多 LOCAL_XXX 變數,例如 LOCAL_MODULE
、LOCAL_SRC_FILES
和 LOCAL_STATIC_LIBRARIES
。 請注意,它不會清除 LOCAL_PATH
。此變數必須保留其值,因為系統在單一 GNU Make 執行環境(其中所有變數都是全域性的)中解析所有構建控制檔案。 在描述每個模組之前,必須宣告(重新宣告)此變數。
LOCAL_MODULE
接下來,LOCAL_MODULE
變數將儲存您要構建的模組的名稱。請在應用中每個模組使用一個此變數。
LOCAL_MODULE := va++
每個模組名稱必須唯一,且不含任何空格。構建系統在生成最終共享庫檔案時,會將正確的字首和字尾自動新增到您分配給 LOCAL_MODULE
的名稱。 例如,上述示例會導致生成一個名為 libva++.so 的庫。
注:如果模組名稱的開頭已是 lib,則構建系統不會附加額外的字首 lib;而是按原樣採用模組名稱,並新增 .so 副檔名。 因此,比如原來名為 libfoo.c 的原始檔仍會生成名為 libfoo.so 的共享物件檔案。 此行為是為了支援 Android 平臺原始檔從 Android.mk 檔案生成的庫;所有這些庫的名稱都以 lib 開頭。
LOCAL_CFLAGS
LOCAL_CFLAGS
此可選變數為構建系統設定在構建 C 和 C++ 原始檔時要傳遞的編譯器標誌。 此功能對於指定額外的巨集定義或編譯選項可能很有用。
儘量不要更改 Android.mk 檔案中的優化/除錯級別。構建系統可使用 Application.mk 檔案中的相關資訊自動為您處理此設定。 這樣允許構建系統生成在除錯時使用的有用資料檔案。
您現在可以使用 LOCAL_CPPFLAGS 只為 C++ 原始檔指定標誌
LOCAL_CFLAGS := -Wno-error=format-security -fpermissive -DLOG_TAG=\"VA++\"
LOCAL_CFLAGS += -fno-rtti -fno-exceptions
-Wno-error=format-security
用於禁用指定的format-security
型別Werror。
-fpermissive
允許編譯一些不合格的程式碼,從錯誤降級為警告,相容一些老的語法。
-DLOG_TAG=\"VA++\"
定義一個LOG_TAG的巨集。
-fno-rtti
禁用執行時型別資訊。
-fno-exceptions
禁用異常機制。
LOCAL_C_INCLUDES
可以使用此可選變數指定相對於 NDK root 目錄的路徑列表,以便在編譯所有原始檔(C、C++ 和 Assembly)時新增到 include 搜尋路徑。 例如:
LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH)
LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH)/Foundation
LOCAL_C_INCLUDES += $(MAIN_LOCAL_PATH)/Jni
LOCAL_SRC_FILES
此變數包含構建系統用於生成模組的原始檔列表。 只列出構建系統實際傳遞到編譯器的檔案,因為構建系統會自動計算所有關聯的依賴關係。
LOCAL_SRC_FILES := Jni/VAJni.cpp \
Foundation/IOUniformer.cpp \
Foundation/VMPatch.cpp \
Foundation/SymbolFinder.cpp \
Foundation/Path.cpp \
Foundation/SandboxFs.cpp \
Substrate/hde64.c \
Substrate/SubstrateDebug.cpp \
Substrate/SubstrateHook.cpp \
Substrate/SubstratePosixMemory.cpp \
請注意,可以使用相對檔案路徑(指向 LOCAL_PATH)和絕對檔案路徑。
注:在構建檔案中務必使用 Unix 樣式的正斜槓 (/)。構建系統無法正確處理 Windows 樣式的反斜槓 ()。
LOCAL_LDLIBS
此變數包含在構建共享庫或可執行檔案時要使用的其他連結器標誌列表。 它可讓您使用 -l
字首傳遞特定系統庫的名稱, 以下依賴了liblog.so
和libatomic.so
,注意lib
要省略。
LOCAL_LDLIBS := -llog -latomic
注: 如果為靜態庫定義此變數,構建系統會忽略它,並且 ndk-build 會顯示一則警告。
LOCAL_STATIC_LIBRARIES
此變數用於儲存當前模組依賴的靜態庫模組列表。如果當前模組是共享庫或可執行檔案,此變數將強制這些庫連結到生成的二進位制檔案。如果當前模組是靜態庫,此變數只是指示,依賴當前模組的模組也會依賴列出的庫。
以下表示它依賴於另一個libfb.a
靜態庫。
LOCAL_STATIC_LIBRARIES := fb
BUILD_SHARED_LIBRARY
此變數指向的指令碼用於收集您在 LOCAL_XXX 變數中提供的模組所有相關資訊,以及確定如何從列出的原始檔構建目標共享庫
。 請注意,使用此指令碼要求您至少已為 LOCAL_MODULE
和 LOCAL_SRC_FILES
賦值,也就是應該先呼叫了include $(CLEAR_VARS)
。
include $(BUILD_SHARED_LIBRARY)
共享庫變數導致構建系統生成具有 .so 副檔名的庫檔案。
BUILD_STATIC_LIBRARY
用於構建靜態庫的變體。構建系統不會將靜態庫複製到您的專案/軟體包,但可能使用它們構建共享庫(LOCAL_STATIC_LIBRARIES := fb
),使用此變數的語法為:
include $(BUILD_STATIC_LIBRARY)
include xx/yy.mk
因為my-dir
返回最後包含的 makefile 的路徑,通常是當前 Android.mk 的目錄。但是如果這樣寫:
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
可避免此問題
include $(MAIN_LOCAL_PATH)/fb/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)
什麼是Application.mk
參看谷歌官方的參考
變數:
APP_ABI
預設情況下,NDK 構建系統為 armeabi ABI
生成機器程式碼。您可以使用 APP_ABI
選擇不同的 ABI。
APP_ABI := arm64-v8a
APP_PLATFORM
此變數包含目標 Android 平臺的名稱。例如,android-3
指定 Android 1.5 版本。 如需平臺名稱和對應 Android 系統映像的完整列表,請參閱 Android NDK 原生 API
APP_PLATFORM := android-14 // Android 4.0 到 4.0.2版本
APP_STL
預設情況下,NDK 構建系統為 Android 系統提供的最小 C++ 執行時庫 (system/lib/libstdc++.so)
提供 C++ 標頭。 此外,它隨附您可以在自己的應用中使用或連結的替代 C++ 實現。請使用 APP_STL
選擇其中一個
APP_STL := gnustl_static
gnustl_static
其實就是LOCAL_MODULE
名字,指定了c++庫用gnu的libstdc++.a
靜態庫。
APP_OPTIM
將此可選變數定義為 release
或 debug
。在構建應用的模組時可使用它來更改優化級別。
發行模式是預設模式,可生成高度優化的二進位制檔案。除錯模式會生成未優化的二進位制檔案,更容易除錯。
在應用清單的 <application>
標記中宣告 android:debuggable
將導致此變數預設使用 debug
而非 release
。 將 APP_OPTIM
設定為 release
可替換此預設值。
APP_OPTIM := release
其他全域性定義
也可以在這裡定義一些全域性的巨集
VA_ROOT := $(call my-dir)
NDK_MODULE_PATH := $(NDK_MODULE_PATH):$(VA_ROOT)