JNI开发之CMake使用指南

96

XuYanjun

关注

2018.08.31 18:18* 字数 1272 阅读 283评论 0喜欢 0

一.简介

1、在Android开发过程中,一些功能在Java代码层无法实现,需要借助底层的支持,例如硬件接入,热修复等,通过这些底层的代码都是友C或者C++进行编写的。此时如果需要用调用这些底层的库,就需要用到JNI技术。

2、通常情况下,JNI开发需要在C/CC++代码目录新建Android.mk文件,在对应module中的build.gradle中的defaultConfig 节点下配置ndk节点,然后配置相关信息,这种网上已经有很多博客都有介绍,这里不再赘述。本篇主要介绍CMake开发Android JNI技术。


二、CMake介绍

2.1、CMake官方介绍

CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files, and generate native makefiles and workspaces that can be used in the compiler environment of your choice.

翻译成中文意思是:

CMake是一个开源的跨平台工具系列,旨在构建,测试和打包软件。CMake用于使用简单的平台和独立于编译器的配置文件来控制软件编译过程,并生成可在您选择的编译器环境中使用的本机makefile和工作空间。

2.2、使用CMake的好处


三、Android中使用CMake进行JNI开发

下面我们从0开始进行一个JNI工程的开发,来说明CMake在Android中的使用流程。

3.1 创建工程,添加C++支持

Android Studio中进行如下操作:File--->New--->New Project,出现如下界面:

 

img

添加C++支持

 

注意:要支持CMake,此时我们需要勾选 Include C++ support,然后点击Next--->Finish,完成工程的创建。 创建完成后的截图如下:

 

img

自动生成后的project

这里我们需要关注的是生成的CMakeLists.txt文件,自动生成的文件内容如下:

以上就是关于CMakeLists.txt文件的说明,在生成的工程中,我们对于的module的build.gradle文件内部也会跟正常情况下的不大一样,可参看Google官方说明,具体我们来分析一下(省略部分无关部分):

变量名参数说明
ANDROID_TOOLCHAINclang (默认) gcc (废弃)指定CMake应该使用的编译器工具链
ANDROID_PLATFORMNDK支持的API级别与Android版本可参考Android NDK Native API指定目标Android平台的名称,例如android-23
ANDROID_STL默认情况下,CMake使用gnustl_static,具体可参考C++支持指定应使用的STL CMake
ANDROID_PIEON OFF指定是否使用与位置无关的可执行文件
ANDROID_CPP_FEATURES默认该变量为空 rtti (表示您的代码使用RTTI) exceptions(表示您的代码使用C ++异常)指定CMake在编译本机库时需要使用的某些C ++特性,例如RTTI(运行时类型信息)和C ++异常。
ANDROID_ALLOW_UNDEFINED_SYMBOLSTRUE FALSE指定如果CMake在构建本机库时遇到未定义的引用,是否抛出未定义的符号错误。要禁用这些类型的错误,请将此变量设置为 TRUE。
ANDROID_ARM_MODEarm thumb(默认)指定是否以arm 或thumb模式生成ARM目标二进制文件
ANDROID_ARM_NEONTRUE FALSE(默认)指定CMake是否应构建具有NEON支持的本机库
ANDROID_DISABLE_NO_EXECUTETRUE FALSE(默认)指定是否启用NX位或No eXecute安全功能。要禁用此功能,传递 TRUE
ANDROID_DISABLE_RELROTRUE FALSE(默认)指定是否启用只读重定位
ANDROID_DISABLE_FORMAT_STRING_CHECKSTRUE FALSE(默认)指定是否使用格式字符串保护编译源代码。启用后,如果在printf-style函数中使用非常量格式字符串,则编译器将引发错误

在build.gradle文件中配置好了cmake相关配置之后,我们再回过头看第一张图,工程生成的文件中包含一个cpp文件夹,文件夹中包含有一个native-cpp.lib文件,通常情况下编写JNI代码就在改cpp文件中进行编写,下面我们来具体编写一个JNI代码。


3.2 编写Java代码

JNI开发中Java中的大概步骤如下:

创建一个makeTest类,将最终要引用的 libnative-lib.so 文件引用进来,具体如下:

3.3 编写JNI代码部分

在上面我们创建好了Java的native方法之后,我们需要在与之对应的lib的源文件中(也就是native-lib.cpp文件)添加对应的方法,关于编写JNI代码,需要注意以下几点:

下面我们开始编写JNI部分代码:

上述代码说明:

 

img

本地方法文件结构

至此,我们一个简单的JNI代码就完成了,接下来测试JNI代码是否正确,创建一个测试的Activity,调用Java中对应的native方法来调用JNI部分的代码进行求和计算:

运行结果:

 

img

运行结果

运行结果正确,说明我们使用CMake进行JNI开发完全没问题。


四、总结

使用CMake进行JNI开发,相对于小的JNI工程感觉不到其优点,如果对于大型的JNI工程,就会体现到其中的优点,总体上进行CMake开发步骤如下:

 

img

CMake开发流程

 

https://www.jianshu.com/p/712942cbe3c1