上篇咱们编写了NDK代码了。也调用到了C/C++的方法,这篇咱们来编译成动态库so文件, 在编译生成SO文件须要配下Android.mk文件 为何须要这个文件Android.mk。当你须要使用JNI的时候,你须要建立一个native工程。Android.mk就是一个makefile配置文件,帮你把C/C++的代码编译成动态库so的。 咱们来看下Android.mk文件内容android
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hellojni LOCAL_SRC_FILES := hajskdh.c include $(BUILD_SHARED_LIBRARY)
解释下这几行代码:bash
LOCAL_PATH := $(call my-dir) 它用于在开发树中查找源文件。 在这个例子中,宏函数‘my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。app
include $(CLEAR_VARS) CLEAR_VARS 由编译系统提供(能够在 android 安装目录下的/build/core/config.mk 文件看到其定义,为 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk),指定让 GNU MAKEFILE为你清除许多 LOCAL_XXX 变量 ( 例如 LOCAL_MODULE , LOCAL_SRC_FILES ,LOCAL_STATIC_LIBRARIES,等等…),除 LOCAL_PATH。这是必要的,由于全部的编译控制文件都在同一个 GNU MAKE 执行环境中,全部的变量都是全局的。函数
LOCAL_MODULE := hellojni LOCAL_MODULE变量必须定义,以表示你在Android.mk文件中描述的每一个模块名称必须是惟一的,通俗的说这个就是你最后生成so的名称,好比你填写的hellojni最后生成的就是libhellojni.so文件。注意:若是把库命名为‘libhellojni’,编译系统将不会添加任何的 lib 前缀,也会生成libhelloworld.so,这是为了支持来源于 Android平台的源代码的 Android.mk 文件。gradle
LOCAL_SRC_FILES := hajskdh.c LOCAL_SRC_FILES变量必须包含将要编译的打包进模块中的C/C++文件源码。这里不须要引用头文件。ui
include $(BUILD_SHARED_LIBRARY) BUILD_SHARED_LIBRARY 是编译系统提供的变量,指向一个 GNU Makefile 脚本(应该就是在 build/core 目录下的 shared_library.mk) ,负责收集自从上次调用 'include $(CLEAR_VARS)'以来,定义在 LOCAL_XXX 变量中的全部信息,而且决定编译什么,如何正 确地去作。并根据其规则生成静态库。同理对于静态库。命令行
Android.mk是必要文件,那么application.mk就是否是必要文件了。这个文件目的是描述在你的应用程序中所须要的模块(即静态库或动态库)。code
APP_MODULES := hellojni APP_ABI := all
这两行就相对简单, APP_MODULES这个变量是可选的,若是没有定义,NDK将由在Android.mk中声明的默认的模块编译,而且包含全部的子文件(makefile文件)若是APP_MODULES定义了,它不准是一个空格分隔的模块列表,这个模块名字被定义在Android.mk文件中的LOCAL_MODULE中。 APP_ABI默认状况下,NDK的编译系统"armeabi"ABI生成机器代码。 all就表示全部类型都生成, 若是不须要所有只须要部分就能够设置APP_ABI := armeabi armeabi-v7a x86 这样就ok。 以上介绍是的编译SO须要的两个配置文件。那么接下来就正式编译so文件,找到以前hellojni项目的jni目录,在目录上右键选择ndk-build(在前篇有介绍的,不知道的同窗能够过去看下)。点击完成就能够看到控制台输出的结果以下,orm
这里就会看到项目目录里面多生成了两个目录一个是libs,另外一个是obj。libs下面就是编译生成的so对应的机器码,而后obj目录就没有什么用能够删除了。这里须要注意下obj这个目录在第二次编译以前请删除掉。否则二次编译就会收到影响。 删除的编译生成的文件可使用ndk-build clear这个命令配置。这个命令就会清楚以前因编译生成的so相关文件,图片
咱们在介绍另外一种编译SO文件的办法,这种办法相对上面一种办法对依赖AS相对较少。 这里可使用.sh脚本去执行编译SO文件操做。咱们先介绍下.sh模板
#!/usr/bin/env bash NDK_PROJECT_PATH=../ function build_so(){ ANDROID_MK=Android.mk APPLICATION_MK=Application.mk XXX/xxx/xxx/android-ndk-r12b/ndk-build -j8 NDK_TOOLCHAIN_VERSION=clang NDK_DEBUG=$1 #-platforms } #set_env DEBUG=1 RELEASE=0; build_so $RELEASE
以上就是build.sh的模板了。 直接将这段代码复制到文本后缀名改成.sh 而后将xxx/xxx/xxx/Android-ndk/ndk-build更改成你当前ndk的存放目录便可。 运行的话打开命令行进入到项目目录的jni目录下,而后执行sh build.sh文件便可获得同上面同样效果的文件目录结构。
以上还须要注意点内容就是: 经过AS编译出来的so文件配置是能够不须要依赖Aapplication.mk文件的。它对应的配置文件是build.gradle 中这个配置,因此在调整本身须要的so文件的时候注意下,
//定义使用ndk ndk{ moduleName "hellojni" //生成的so名字 abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前无关紧要。 }
而经过脚本编译出来以来的文件就是Aapplication.mk因此最后在使用的时候记得分清楚。以避免搞混乱了。