原文地址:http://blog.csdn.net/smfwuxiao/article/details/8523479 工具
Android NDK r5 開始支持預編譯庫(動態庫和靜態庫),即程序能使用庫的預編譯版本。 ui
該特性可用於如下兩方面: spa
1)向第三方NDK開發人員發佈你的共享庫而不用提供源碼。
2)使用一個提早編譯好的庫(預編譯庫)來加速編譯過程。
本文說明該特性如何工做。 .net
I. 聲明一個預編譯庫的模塊
對於Android編譯工具而言,每一個預編譯庫必須聲明爲一個獨立的模塊。這裏舉一個例子,假設 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)
按如下步驟聲明這樣一個模塊:
1. 給該模塊取一個名字(這裏是 foo-prebuilt)。這個名字不須要與預編譯庫自身的名字相同。
2. 將 LOCAL_SRC_FILES 指定爲你要提供的共享庫的路徑。一般,該路徑是相對於 LOCAL_PATH 的路徑。注意:必須保證共享庫ABI的兼容性。
3. 若是你的庫是共享庫,則包含 PREBUILT_SHARED_LIBRARY 而不是 BUILD_SHARED_LIBRARY;若是是靜態庫,則包含 PREBUILT_STATIC_LIBRARY。
預編譯模塊不須要編譯。該預編譯模塊會被拷貝到 $PROJECT/obj/local 下面,還會被拷貝到 $PROJECT/libs/<abi> 下面(這裏的庫被strip過)。 調試
II. 在其餘模塊中引用這個預編譯庫
在依賴該預編譯庫的模塊對應的Android.mk中,將預編譯庫的名字(前面取的)加入到 LOCAL_STATIC_LIBRARIES 或 LOCAL_SHARED_LIBRARIES 聲明中。例如,一個使用上面libfoo.so的簡單例子以下: blog
- include $(CLEAR_VARS)
- LOCAL_MODULE := foo-user
- LOCAL_SRC_FILES := foo-user.c
- LOCAL_SHARED_LIBRARIES := foo-prebuilt
- include $(BUILD_SHARED_LIBRARY)
III. 將預編譯庫的頭文件導出
獲得預編譯庫以後,通常須要它對應的頭文件。例如前面的libfoo.so,它有對應的foo.h。編譯依賴libfoo.so的模塊時,須要將該頭文件和它的路徑提供給NDK編譯系統。一種簡單方法是,前面在定義該預編譯庫的時候,使用LOCAL_EXPORT_C_INCLUDES 變量。例如,假設文件 foo.h 位於當前預編譯模塊所在目錄的 include 子目錄,則能夠在預編譯模塊的Android.mk文件中編寫以下: ip
- 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 定義確保了任何依賴這個預編譯庫的模塊會自動在本身的 LOCAL_C_INCLUDES 變量中增長到這個預編譯庫的include目錄的路徑,從而可以找到其中的頭文件。
IV. 調試預編譯庫
建議你在預編譯庫中保留調試信息。位於 $PROJECT/libs/<abi> 的版本都是不含調試信息的(被NDK編譯系統執行strip過的),調試版的庫才能用於 ndk-gdb。 開發
V. 共享庫ABI的選擇
如前所述,共享庫與目標系統的ABI兼容性相當重要。應檢查一下 TARGET_ARCH_ABI 的值,能夠是如下值:
armeabi 目標系統CPU是ARMv5TE或更高
armeabi-v7a 目標系統CPU是ARMv7或更高
x86 目標系統CPU是x86
注意,armeabi-v7a的CPU能夠很好地執行armeabi的程序。
舉一個例子,咱們提供一個預編譯庫的兩個版本,而後選擇不一樣的ABI: get
- 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)
這裏假設要拷貝的預編譯庫所在的目錄結構以下:
Android.mk --> 編譯這個預編譯庫的Android.mk
armeabi/libfoo.so --> armeabi版本的共享庫
armeabi-v7a/libfoo.so --> armeabi-v7a版本的共享庫
include/foo.h --> 預編譯庫導出的頭文件
注意:你沒必要提供armeabi-v7a版本,由於armeabi版本的共享庫可以被armeabi-v7a的兼容,可是反過來就不行。