缘起
生活不止眼前的苟且,还有诗与远方。如果你是个菜鸟,想成为一个万人敬仰的大神,那么你不妨先给自己定个小目标,比如说先活它个200年,然后向天再借500年。嗯,第一次听到它的时候,一颗心不停的颤抖,好像前生彼此曾拥有,今生却等了很久很久。跨平台作业的脚本,简单的风格,正处于青春期的 cmake,蓬勃的生机与活力,让人忍不住为之着迷。
介绍
Cmake 是什么?巨头百度说了:
CMake 是一个跨平台的安装工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试所支持的C++特性,类似UNIX下的automake。CMake 可以编译、制作、产生适配器(wrapper)、还可以用任意的顺序建构。CMake 支持 in-place 建构(二进档和源代码在同一个目录树中)和 out-of-place 建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake 也支持静态与动态程式库的建构。“CMake”这个名字是“cross platform make”的缩写。
简单而言,对于我们,就是生成so。
准备工作
对于 cmake,as 的支持来得有点晚,直到 as 2.2 之后才开始。所以 as 较低版本的,请升级,如有不便,请联系谷歌客服。升级完毕,打开 SDKManager,还有几个小插件需要安装。比如说 cmake 插件,这个你不装不行,如果,假如说如果,不好意思这里没有如果。比如说 NDK 插件,套用官方的话说,原生开发工具包,允许您为 Android 使用 C 和 C++ 代码,并提供众多平台库。比如说 LLDB 插件,调试原生代码,可选项,推荐使用。
勾选情况图
上图,从官网文档截取,请自主勾选需要项。如果你嫌烦,一键勾选所有,耐心等待个三天三夜,我连手带脚支持。
征程开始
出师未捷身先死,啊呸,这个,这个我们还是回归正题,开始我们的 hello jni 征途。一个目标(项目支持 cmake),两条途径。其中一条捷径,创建一个新项目,选中 Include C++ Support 复选框。对于这种方式,没什么需要解释的,下一步,下一步。
Include C++ Support 复选框
另外一条就是在已有项目中支持 cmake,分几个步骤。
步骤1. 在 src/main 目录下创建一个目录,取名叫 cpp。这个命名随意,你喜欢就好。把需要引入的代码放入创建的目录下,这里千万别随意,不能闹情绪。
步骤2. 创建 CMake 构建脚本,一个纯文本文件,取名 CMakeLists.txt,这个命名固定格式,不允许有脾气。至于这个文件你放哪里,随你喜欢好了。
我的选择
步骤3. 在 app module 中的 build.gradle 文件中,给予 cmake 支持。
android{
...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
第一个配置,声明 Native Build 方式为 cmake,并指定 cmake 脚本路径。
android{
...
defaultConfig{
...
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions"
}
}
}
}
哟哟,走过路过看过别错过。第二个配置,设置 cmake 编译的条件,比如说 c11++ 标准。同样都是 externalNativeBuild,这里是在 defaultConfig 域,而 cmake path 是 android 域。我有时候想,为什么不合二为一呢,非要让人写两遍,头疼,此处不求甚解。
征途关键,cmake 的配置
cmake 的文档,E文,让人沉醉于其中,不能自拔。有这么几个 api,比较重要。
重要1. add_library,生成 lib。对于我们而言,System.loadLibrary("xxx"),这里的 xxx 就是我们的lib。 示例如下:
# 创建一个 lib,静态 or 动态,可创建多个
add_library( # lib名称
JniDemo
# lib类型
SHARED
# .c/cpp目录
jni_dynamic.cpp )
重要2. set_target_properties,用来使用 .a 等已构建好的 lib。示例如下:
# 添加自己的 lib 库
add_library( libHello
SHARED
# 由于.a 已经属于已经构建好的库,使用 IMPORTED 标志,告诉 cmake 不需要编译了
IMPORTED )
set_target_properties(
#名称
libHello
# 指定要定义的参数.
PROPERTIES IMPORTED_LOCATION
# 导入 lib 的路径
${CMAKE_SOURCE_DIR}/sources/${ANDROID_ABI}/libHello.a)
重要3. find_library,查找 lib。示例如下:
# 搜索 NDK 指定 lib
find_library( # lib 路径变量的名称。
log-lib
# 查找指定 lib 名称
log )
重要4. target_link_libraries,链接所有 lib,生成新的 lib,示例如下:
# 链接库
target_link_libraries( # 指定目标 lib
JniDemo
# 自己的 lib
libHello
# NDK log lib //这里放 find 的路径 ${log-lib} 也是可以
log )
暂且就讲这么几个,基本上应该也差不多可以满足了。如果,那么请自觉查看 cmake 文档,我想你会喜欢的。这里有个事还是提一下,对于上边四个重点,有两个是重中之重。重点1,是生成 lib,建立 java 与 c/c++ 之间的桥梁。重点4, 是链接所有 lib, 建立一个完整的可运行 lib。这两个,基本也可以解决问题了。至于多余的两个重点,为了结构比较清晰,直观罢了。
分享征途喜悦
到了这,jni 就告一段路了。至于前边想的,算是有一个可喜的圆满结局了。我之所以这么认真的待 jni,是因为我愿意,我喜欢。若能以此换回对 jni 的认知,了解,固然可喜。如是没有,我也没有什么可后悔的了。
附送一张github机票,带你领略世界的浩瀚
网友评论