使用預編譯庫
NDK 支持使用預編譯庫(同時支持靜態庫和共享庫)。此功能有以下兩個主要用例:
- 向第三方 NDK 開發者分發您自己的庫(而不分發您的源代碼)。
- 使用您自己的庫的預編譯版本來提升編譯速度。
本頁將介紹如何使用預編譯庫。
聲明預編譯庫
您必須將自己使用的每個預編譯庫聲明為一個獨立模塊。為此,請執行以下步驟:
- 為模塊提供名稱。此名稱不需要與預編譯庫本身的名稱相同。
- 在模塊的
Android.mk
文件中,將指向您提供的預編譯庫的路徑分配到LOCAL_SRC_FILES
。指定LOCAL_PATH
變量的值的相對路徑。注意:請務必選擇與您的目標 ABI 對應的預編譯庫版本。要詳細了解如何確保庫支持 ABI,請參閱為預編譯庫選擇 ABI。
- 根據您使用的是共享庫 (
.so
) 還是靜態庫 (.a
),添加PREBUILT_SHARED_LIBRARY
或PREBUILT_STATIC_LIBRARY
。
下面這個小例子假設預編譯庫 libfoo.so
與描述它的 Android.mk
文件位於同一個目錄中。
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt LOCAL_SRC_FILES := libfoo.so include $(PREBUILT_SHARED_LIBRARY)
在此示例中,模塊名稱與預編譯庫的名稱相同。
編譯系統會將您的預編譯共享庫副本置於 $PROJECT/obj/local
中,而將另一個提取的調試信息的副本置於 $PROJECT/libs/<abi>
中。在這里,$PROJECT
是您項目的根目錄。
從其他模塊引用預編譯庫
要從其他模塊引用預編譯庫,請在與這些模塊關聯的 Android.mk
文件中,將該預編譯庫的名稱指定為 LOCAL_STATIC_LIBRARIES
或 LOCAL_SHARED_LIBRARIES
變量。
例如,使用 libfoo.so
的模塊說明可能類似於以下內容:
include $(CLEAR_VARS) LOCAL_MODULE := foo-user LOCAL_SRC_FILES := foo-user.c LOCAL_SHARED_LIBRARIES := foo-prebuilt include $(BUILD_SHARED_LIBRARY)
此處,LOCAL_MODULE
是引用預編譯庫的模塊的名稱;LOCAL_SHARED_LIBRARIES
是預編譯庫本身的名稱。
導出預編譯庫的標頭
foo-user.c
中的代碼取決於通常位於標頭文件(如 foo.h
)中的特定聲明,而該標頭文件是使用預編譯庫分配的。例如,foo-user.c
中可能會有類似於以下內容的一行代碼:
#include <foo.h>
在這種情況下,如果您編譯 foo-user
模塊,則需要提供標頭及其指向編譯器的 include 路徑。完成此任務的一個簡單方法是在預編譯模塊定義中使用導出內容。例如,只要標頭 foo.h
位於與預編譯模塊關聯的 include
目錄下,您就可以按以下方式對其進行聲明:
include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt LOCAL_SRC_FILES := libfoo.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY)
此處的 LOCAL_EXPORT_C_INCLUDES
定義會確保編譯系統導出指向預編譯庫的 include
目錄的路徑,針對依賴於它的模塊將該路徑附加到 LOCAL_C_INCLUDES
的值。
此操作可讓編譯系統查找必需的標頭。
調試預編譯庫
建議您提供包含調試符號的預編譯共享庫。NDK 編譯系統總是會從其安裝到 $PROJECT/libs/<abi>/
的那版庫中提取符號,但您可以使用調試版本通過 ndk-gdb
進行調試。
為預編譯庫選擇 ABI
請務必為您的目標 ABI 選擇正確版本的預編譯共享庫。Android.mk
文件中的 TARGET_ARCH_ABI
變量可以將編譯系統指向適當版本的庫。
例如,假設您的項目包含庫 libfoo.so
的以下兩個版本:
armeabi/libfoo.so x86/libfoo.so
以下代碼段顯示了如何使用 TARGET_ARCH_ABI
,以便編譯系統選擇適當版本的庫:
include $(CLEAR_VARS) LOCAL_MODULE := foo-prebuilt LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfoo.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY)
如果您將 armeabi
指定為 TARGET_ARCH_ABI
的值,編譯系統便會使用位於 armeabi
目錄中的 libfoo.so
版本。如果您將 x86
指定為 TARGET_ARCH_ABI
的值,編譯系統便會使用 x86
目錄中的版本。