以jrtplib的依赖库jthread的编译为例,介绍cmake的交叉编译,因为这个库相对简单,构建完成后就可以直接使用,将动态库或者静态库放置到安卓指定的文件夹下,通过引用头文件来编写jni即可。
这篇文章用到了一点cmake交叉编译的东西,在我的掘金主页有关于如何使用cmake的教程。
https://juejin.im/post/5a8ebe006fb9a0635a6574de
文章废话少,干货多,请静下心来看:
关于ndk的东西网上已经烂大街了,我这里就不多介绍了。这篇文章主要是关于如何使用bash控制cmake来cross-compile。
- 创建build文件夹用于外部构建
- 创建target及架构平台文件夹用于存放构建好的动态库
- cmake外部编译、交叉编译
- 将构建好的项目导出至target文件夹下
ndk-build生成多abi动态库相对简单,安卓环境的cmake环境生成动态库也很简单,不多说,但是在非安卓cmake环境中的cmake中我目前还没找到如何一次生成多个平台架构,所以写了一个脚本来实现。
由于脚本相对来说比较简单,这文章篇幅不会很长:
android架构
armeabi
armeabiv7a
arm64v8a
x86
x86_64
mips
mips64
这七种是我们今天将要编译的abi,这七个文件夹会在target文件夹中生成,并在对应的文件夹下生成动态库
一些变量
使用cmake交叉编译时必须找到ndk路径,否则不能编译,定义如下,将NDK_PATH替换为自己的路径即可。
1 | !/bin/bash |
准备build文件夹
采用外部构建的方式,build文件夹是构建的文件夹,所有的生成文件都会在这边,所以先检测是否有这个文件夹,没有就创建,有就清除里边的内容。
1 | 清除build文件夹下的内容 |
准备target文件夹
target文件夹是我们用来存放各种abi动态库的文件夹,我们会将build文件夹中生成的动态库和静态库复制到target对应的文件夹下
1 | function prepare_target() { |
这里边有三个函数,第一个用来创建target文件夹,第二个用来创建abi架构的文件夹,第三个用于复制库到创建好的文件夹下。
构建函数
1 | function build_lib() { |
看起来很长的一段函数,其实没毛的内容,第一个函数是用来交叉编译的主要函数,他接受一个平台参数,也就是我们定义好的TARGETS数组中的元素,后边的七个函数是分别构建单一abi架构。最后一个就牛逼了,他会遍历数组,构建所有的abi平台。
到这里主要功能完成了。
自动补全
为了让程序更完美,我做了一个自动补全的命令,在bash中安tab即可自动补全你想要的架构。
1 | function sbuild() { |
在这里我们扩展了一下TARGETS数组,添加了一个all,这个参数就是用来构建全平台abi。
执行命令
最后执行一下,最好在bash中执行,zsh好像没有自动补全的complete命令。
1 | source build.sh |
这个命令是用来输出执行脚本,然后我们就可以用构建命令了
1 | sbuild all |
构建全平台
1 | sbuild armeabi |
构建armeabi平台。七种架构都能单独构建。
单独构建后只有一种平台架构:
1 | . |
全部构建后:
1 | . |
最后说明一下,这个方式是用cmake来构建安卓平台的动态库和静态库的方式,生成好的文件最后还是要放进安卓指定的文件夹中,这些库的调用必须是用jni编程来实现的,不能直接来调用。