使用AndroidStudio为Unity编译C/C++动态库

安卓平台是基于Linux,所以动态库是so后缀,在AndroidStudio 中生成动态库有两种方式,一种是通过cmake,另一种是通过ndk-build,本文采用的是ndk-build,目前AS对于这两种方式都支持,但是对于新的项目,官方建议采用CMake来构建。

安装 AndroidStudio

软件可以从 Google 官网下载,不需要翻墙,安装过程可以参考之前的,需要注意以下几点:

  • 编译c/c++需要安装ndk
  • ndk版本与 unity 一致
  • 安装特定版本ndk,参考这里

编译动态库

编译主要步骤:

  1. 创建 Empty 工程
  2. 将C/C++文件导入到项目jni文件夹
  3. jni目录中创建构建脚本,如果是CMake需要创建CMakeLists.txt,如果是ndk-build需要创建Android.mk
  4. 将构建脚本添加到gradle构建脚本
  5. 执行构建

下面以编译sqlite为例,详细介绍编译过程

创建工程

首先创建 Android Studio 工程,项目模板选 No Activity即可

参数设置,这里 Minimum SDK 要与Unity PlayerSetting 一致,NDK编译过程中会根据该参数匹配编译平台

创建 jni 文件夹,切换到 Project 视图,在app/src/main 右键选择 New->Folder->JNI Folder

勾选 Change Folder Location,点击结束

导入C/C++源码

下载 sqlite 源码,解压之后将sqlite3.csqlite3.hsqlite3ext.h复制到jni文件夹内

创建构建脚本

jni文件夹创建 ndk-build 构建文件Android.mk,它实际上是 makefile 片段,用于定义构建行为

文件内容如下:

1
2
3
4
5
6
7
8
9
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := sqlite3

LOCAL_SRC_FILES =: sqlite3.c

include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir) 语句定义 LOCAL_PATH变量,表明源文件在项目中的位置,宏函数my-dir返回Android.mk文件所在目录;

include $(CLEAR_VARS) 包含一个由变量CLEAR_VARS表示的 GNU Makefile 文件,该文件会清除一些 LOCAL_XXX 变量,比如LOCAL_MODULELOCAL_SRC_FILES等,但是不会清除 LOCAL_PATH

LOCAL_MODULE := sqlite3 设置要构建的模块的名称,一个模块就是一个动态库(so),模块名称必须唯一,不能包含空格,最终生成会自动添加前缀和后缀,例如上面示例会生成libsqlite3.so;

LOCAL_SRC_FILES =: sqlite3.c 列出C/C++ 源文件,多个文件之间用空格分隔,相对路径使用正斜杠(/),不要使用 Windows 的反斜杠(\);

include $(BUILD_SHARED_LIBRARY) 上面说了,Android.mk 只是 GNU Makefile 片段,我们只需要把这部分片段设置好,再和其他部分组到一块就可以进行编译,所以这里的BUILD_SHARED_LIBRARY 指向的就是其他部分文件,该文件用于构建动态库文件,该文件至少要求已经设置了LOCAL_MODULELOCAL_SRC_FILES变量;类似的还有构建静态库的BUILD_STATIC_LIBRARY,构建执行文件的BUILD_EXECUTABLE

sqlite编译不需要依赖其他库,如果需要添加依赖库,可以设置以下变量:

  • LOCAL_C_INCLUDES,附加包含目录,include 搜索路径,相对 ndk 根目录
  • LOCAL_STATIC_LIBRARIES,依赖的静态库列表
  • LOCAL_SHARED_LIBRARIES,依赖的静态库列表

默认会生成所有非弃用的ABI生成库,如果要设置为特定的ABI 生成代码,可以按照以下步骤:

  1. jni目录创建 Application.mk 文件
  2. 编辑Application.mk,文件内容如下
1
2
3
APP_MODULES := sqlite3

APP_ABI := all

APP_MODULES := sqlite3 要构建的模块列表,与Android.mk中的LOCAL_MODULE 对应

APP_ABI := all,指定ABI 类型,值包括armeabi-v7aarm64-v8ax86x86_64all,多个值之间用空格分隔

构建

构建是通过执行 ndk-build.cmd完成,为了方便构建,可以借助命令行或者AndroidStudio 的 External tool。

命令行

1
2
cd <app\src\main>
<ndk>\ndk-build.cmd

External Tools

添加构建工具,在File-Settings打开设置面板,在Tools/External Tools中,添加编译工具,这里的 Tools Settings - Program 设置为 ndk 的根目录,这里要注意ndk版本。

运行工具

构建完成之后,可以在 src/main/libs 目录中找到生成的 so文件。

拷贝到 Unity 工程

将生成的 libs 文件夹,拷贝到 Unity 工程,放到 Plugins/Android/ 目录下,检查导入设置是否正确

参考

Unity用户手册
NDK开发指南