NDK Prebuilts library support:
-----------------------------------------
Android NDK r5引入对预编译库(动态或静态)的支持,即在你的应用程序中可以包含和使用之前编译好的库。
这个功能对以下两种情况比较有用:
1.你可以把你的库分享给第三方的NDK开发者,而不需要发布你的源代码。
2.你想要使用之前编译好的库来加快你的编译。
本文档会解释它是如何工作的。
I、声明一个预编译module库:
--------------------------------------
对于编译系统来说,每一个预编译库必须声明为一个单独的module。下面是一个简单的例子,我们假定文件“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)
注意,为了声明一个module,实际上你只需要这样:
1.给module起一个名字(这里是‘foo-prebuilt’)。这个不需要对应预编译库本身的名字。
2.设置LOCAL_SRC_FILES的路径为你提供的预编译库。通常,这个路径是相对于你的LOCAL_PATH。
重要:你必须确保你的预编译库对应你使用的目标ABI。更多的请看下面。
3. 如果你使用的是共享库,用PREBUILT_SHARED_LIBRARY代替BUILD_SHARED_LIBRARY。对于静态库,使用PREBUILT_STATIC_LIBRARY。
预编译的module不会编译任何东西。但是,你的预编译库将会被拷贝到$PROJECT/obj/local和$PROJECT/libs/<abi>下面。
II. 在其他modules中引用预编译库:
--------------------------------------------------
如果你的module需要用到它,在Android.mk文件中声明LOCAL_STATIC_LIBRARIES或LOCAL_SHARED_LIBRARIES,然后简单的列出预编译module的名称即可。
例如,使用libfoo.so模块的一个navie例子:
include $(CLEAR_VARS)
LOCAL_MODULE := foo-user
LOCAL_SRC_FILES := foo-user.c
LOCAL_SHARED_LIBRARIES := foo-prebuilt
include $(BUILD_SHARED_LIBRARY)
III.导出预编译库的头文件:
---------------------------------------
上面的例子之所以叫着‘naive’是因为,实际上,foo-user.c中的代码将会依赖特定的声明,这些声明是在预编译库的头文件中。(例如“foo.h”)
换句话说,foo-user.c会有类似下面的一行:
#include<foo.h>
当编译foo-user module的时候,你需要提供它的头文件和它的include路径给编译器。
一种简单的处理办法是在预编译module定义中使用exports。例如,假定有一个文件“foo.h”在相对于预编译module的‘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的定义确保任何依赖预编译库的module,会将它的LOCAL_C_INCLUDES自动的添加到预编译include目录的前面,这样就能在内部找到头文件。
IV.调试预编译二进制文件:
--------------------------------------
我们推荐你在提供预编译动态库的时候包含debug symbols。被安装在$PROJECT/libs<abi>的版本总是会被NDK编译系统删除,但是debug版本会被ndk-gdb用来进行调试。
V.ABI
如前面所说,在编译的时候提供一个和目标ABI相兼容的预编译动态库是非常关键的。可以检查TARGET_ARCH_ABI的值,它的值将会是:
armeabi => when targeting ARMv5TE or higher CPUs
armeabi-v7a => when targeting ARMv7 or higher CPUs
x86 => when targeting x86 CPUs
mips => when targeting MIPS CPUs
注意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 --> thefile above
armeabi/libfoo.so --> the armeabi prebuilt sharedlibrary armeabi-v7a/libfoo.so --> the armeabi-v7a prebuilt sharedlibrary include/foo.h --> the exported header file
注意:记住你不需要提供armeabi-v7a的预编译库,因为armeabi这个就可以轻易的运行在相应的设备上。