下载来的NDK包里有一份介绍NDK内容的文档 《Android NDK Dev Guide》,这里摘记一些信息做个备忘
NDK提供一组工具帮助开发者把使用C/C++开发的代码嵌入到我们开发的android应用中,仅能在1.5以上的Android系统中使用,不过现在市场上的绝大多数设备都是1.5版本以上了,看起来这不是个问题。
NDK开发的步骤概括
- 把C/C++源代码放到$PROJECT_PATH/jni目录下,这些源代码都要按照jni的规范来编写
- 编写$PROJECT_PATH/jni/Android.mk文件内容,这个文件用于将C/C++代码组织成module,module是指static library 或者 shared library。每个Android.mk文件内可以定义一个或多个module,同样的源代码也可以用于多个module
- 编写$PROJECT_PATH/jni/Application.mk文件内容(可选)
- 在项目目录下运行$NDK_PATH/build
- 默认情况下NDK会把编译产生的中间文件放在$PROJECT_PATH/jni/obj目录下面,可以通过NDK_OUT环境变量设置成其他目录。
Android.mk
一个比较典型的Android.mk文件内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir)
Android.mk文件的第一行必须是变量LOCAL_PATH的定义,这个变量用于定位源代码。
my-dir是由build system提供的一个宏,它表示Android.mk文件所在的目录。
include $(CLEAR_VARS)
CLEAR_VARS是由build system提供的并指向一个特殊的GNU Make script,它可以清除掉除了LOCAL_PATH之外很多LOCAL_XXX形式的变量(如LOCAL_MODULE, LOCAL_SRC_FILES 等等)。
LOCAL_MODULE := hello-jni
每个module都需要有一个LOCAL_MODULE变量来定义module的名字,多个module的值必须要是不重复的,名字中也不能携带空格。build system会自动给编译出来的module文件加入前缀和后缀,比如这里可能就编译出来libhello-jni.so
LOCAL_SRC_FILES := hello-jni.c
这里是设置要编译进module的源文件列表,只列出源文件
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY也是build system提供的,指向一个特殊的GNU Make script。它会收集CLEAR_VARS之后的所有LOCAL_XXX的信息,决定如何build,产生的是shared library。
还有一个BUILD_STATIC_LIBRARY用来产生static library的。
Application.mk
NDK支持使用C++来开发,但是默认使用了一个非常小的C++运行时库。这个库不支持stl,不支持exception,不支持rtti。所以当代码中需要用到这些部分时,我们得做出点改变。
目前NDK提供了一共7种选择,下面列出了这7种选择,我们可以在Application.mk文件里通过APP_STL来定义要使用的库
system -> Use the default minimal system C++ runtime library.
gabi++_static -> Use the GAbi++ runtime as a static library.
gabi++_shared -> Use the GAbi++ runtime as a shared library.
stlport_static -> Use the STLport runtime as a static library.
stlport_shared -> Use the STLport runtime as a shared library.
gnustl_static -> Use the GNU STL as a static library.
gnustl_shared -> Use the GNU STL as a shared library.
撇开static 和 shared的区分,实际上NDK一共提供了4个不同的实现,这些实现支持的特性也不一样
C++ C++ Standard Exceptions RTTI Library system no no no gabi++ no yes no stlport no yes yes gnustl yes yes yes
C++ Exceptions support
NDK是支持C++ Exception的,从NDK r5开始默认是未开启这个功能的。如果我们的代码里用到了Exception功能 ,出了要选择一个gnustl外,还要在Application.mk里加入 APP_CPPFLAGS += -fexceptions
RTTI support
类似exception,要使用RTTI功能,除了选择一个支持RTTI的library实现,还要在Application.mk里加入 APP_CPPFLAGS += -frtti