NDK 预生库支持:
-----------------------------
Android NDK r5 已引入对预生成库的支持(共享库和静态库),可以在你的应用程序中包含和使用库的预生成库。
该功能对两种情况是有用的:
1.你想要对第三方 NDK 开发者发布你自己的库而不发行你的源文件。
2.你想要使用一个你自己的库的预生版本使你的生成加快速度。
本文档说明如何这个支持如何使用。
I. 声明一个预生成库模块:
---------------------------------------
对每个预生成库必须作为单个的独立的模块向生成系统声明。
这里是一个小小的例子我们假设 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_SRC_FILES 变量值只能为一个!
像平常一样,该路径是相对于你的 LOCAL_PATH 变量值的路径。
重点:
1.你必须确保该预生成库对应你正在使用的目标 ABI 。
更多信息在后面。
3. 用 PREBUILT_SHARED_LIBRARY 替代 BUILD_SHARED_LIBRARY 。
静态库为 PREBUILT_STATIC_LIBRARY
注:一个预生模块并不生成任何东西,只是将共享库复制进 $PROJECT/obj/local 目录下,
并且另一个将复制并裁剪进 $PROJECT/libs/<abi> 目录下。
II. 如何在其它模块中引用预生成库:
------------------------------------------------------
在依赖预生成库的模块的 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_LIBRARY := foo-prebuilt
include $(BUILD_SHARED_LIBRARY)
III. 为预生成库导出头文件:
----------------------------------------------
上面的例子被称之简单是因为在实际中用 foo-user.c 代码通常将要依赖具体的头文件声明,
通常找到在随预生成库一起发布的头文件中。(例如:foo.h)
换句话说,foo-user.c 将要有像如下一行:
#include <foo.h>
所以你需要在生成 foo-user 模块时需要指定 foo.h 的路径。
一个简单处理方法是在预生成模块定义中使用导出。
例如,假设一个 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_C_INCLUDES 作为预生包含目录的前置,这样编译器就能够找到头文件了。
IV. 调试预生成二进制文件:
--------------------------------
我们推荐你提供包含调试符号的预生成共享库。
一般在 $PROJECT/libs/<abi>/ 目录中生成的版本经过了 NDK 生成系统优化将不包含调试信息,
但是调试版本将被 ndk-gdb 用于调试目的。
V. 预生成二进制文件的 ABI 选择:
--------------------------------------
如前面所述,在生成期间提供一个兼容目标 ABI 的预生成共享库是至关重要的。
要做到这一点,检查 TARGET_ARCH_ABI 的值,它的值将是:
armeabi => ARMv5TE 或更高版本 CPU
armeabi-v7a => ARMv7 或更高版本 CPU
x86 => x86 CPU
注意 armeabi-v7a 系统可以很好的运行 armeabi 版本的二进制文件。
这里有一个例子,我们提供一个预生成库的两个版本并基于目标 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)
所以这里我们假设预生成库复制是在如下目录层次:
Android.mk --> 上述文件
armeabi/libfoo.so --> armeabi 版本的 so
armeabi-v7a/libfoo.so --> armeabi-v7a 版本的 so
include/foo.h --> 要导出的头文件
注:
你不需要专门提供一个 armeabi-v7a 预生成库,因为一个 armeabi 可以顺利地运行在相应的设备上。