📒 MNN Chat Android App 构建笔记
一、背景知识
-
MNN 简介
- MNN 是阿里开源的轻量级深度学习框架,支持 Android / iOS / Linux / Windows。
- 提供推理、LLM、Vision、Audio 等模块。
- Android App 里用到的是 Java + JNI 调用 MNN 库。
-
CMake + NDK 的作用
- CMake:跨平台构建工具,用于生成工程文件(Makefile / Ninja)。
- NDK:Android 原生开发工具包,提供交叉编译环境,把 C++ 源码编译成
.so
库。 - Gradle:Android Studio 的构建系统,最终把
.so
打包到 APK。
-
构建的两部分
- MNN 主库 (libMNN.so):用 CMake + NDK 编译。
- MnnLlmChat App:用 Android Studio (Gradle) 构建,依赖上面生成的
libMNN.so
。
二、官方推荐步骤
MNN 官方文档的流程(apps/Android/MnnLlmChat/README.md 里给出):
-
编译 MNN 主库
cd project/android mkdir build_64 ../build_64.sh "-DMNN_BUILD_LLM=true -DMNN_OPENCL=true ..." make install
- 输出:
libMNN.so
- 输出:
-
打开 Android App 工程
- 路径:
apps/Android/MnnLlmChat/
- 用 Android Studio 打开,Gradle 会自动拉依赖。
- 连接 Android 手机,运行
Run app
。
- 路径:
三、我的操作过程
1. 初次尝试:跟随官方步骤
cd project/android
mkdir build_64
../build_64.sh "-DMNN_BUILD_LLM=true ..."
make install
❌ 报错:
Could not find toolchain file: D:/Git/build/cmake/android.toolchain.cmake
CMake Error: CMAKE_C_COMPILER not set
原因:
- 系统环境找不到 Android NDK 的路径(脚本默认路径不对)。
- Windows 下
make
也不可用。
2. 修改后尝试:手动 CMake
export ANDROID_NDK=/d/sdk/ndk/27.2.12479018
cmake .. -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake ...
❌ 报错:
The source directory "project/android" does not appear to contain CMakeLists.txt
原因:
- 在
project/android
目录下运行,但CMakeLists.txt
在 项目根目录。
3. 正确构建方式
cd /g/down/MNN-master/MNN-master
mkdir -p build_64
cd build_64cmake .. -G Ninja \-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \-DANDROID_ABI=arm64-v8a \-DANDROID_PLATFORM=android-33 \-DMNN_BUILD_LLM=true \-DMNN_OPENCL=true \-DMNN_ARM82=true \-DMNN_USE_LOGCAT=true \-DMNN_BUILD_OPENCV=true \-DLLM_SUPPORT_VISION=true \-DLLM_SUPPORT_AUDIO=trueninja install
✅ 成功输出:build_64/lib/libMNN.so
4. Android Studio 部分
- 打开
apps/Android/MnnLlmChat/
- 等待 Gradle 下载依赖(可能比较慢,需要网络)
⚠️ 遇到的错误:
Unknown host 'repo.maven.apache.org'
原因:网络问题,无法下载依赖。
解决:
- 关掉 Gradle 的 offline mode
- 确保网络能访问
repo.maven.apache.org
(必要时开代理)
后续 Gradle 下载 kotlin-compiler-embeddable
包时:
Downloading kotlin-compiler-embeddable-2.1.21.jar (56MB)
这是 正常的依赖下载过程。
四、报错与解决总结
步骤 | 报错 | 原因 | 解决 |
---|---|---|---|
build_64.sh | 找不到 toolchain.cmake | 默认路径不对 | 设置 ANDROID_NDK 环境变量 |
cmake … | 没有 CMakeLists.txt | 路径选错 | 必须在 项目根目录 执行 |
make | 找不到 make | Windows 下没有 GNU Make | 用 Ninja |
Gradle sync | Unknown host | 网络问题 | 配置代理,关闭 offline mode |
Gradle build | kotlin-compiler 下载很慢 | 包很大 (56MB) | 等待即可 |
五、最终全流程总结
-
准备环境
- Android NDK:
D:\sdk\ndk\27.2.12479018
- CMake:
D:\sdk\cmake\3.22.1\bin
- Ninja: 已安装 (
ninja --version
正常)
- Android NDK:
-
编译 MNN 主库
cd /g/down/MNN-master/MNN-master mkdir -p build_64 && cd build_64cmake .. -G Ninja \-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \-DANDROID_ABI=arm64-v8a \-DANDROID_PLATFORM=android-33 \-DMNN_BUILD_LLM=true \-DMNN_OPENCL=true \-DMNN_ARM82=true \-DMNN_USE_LOGCAT=true \-DMNN_BUILD_OPENCV=true \-DLLM_SUPPORT_VISION=true \-DLLM_SUPPORT_AUDIO=trueninja install
最后失败了
遇到的是 链接阶段报错,编译 .o
文件都成功了,但是在 生成可执行文件 时失败了:
clang++: error: linker command failed with exit code 1
ninja: build stopped: subcommand failed.
结合日志可以看到,它失败的位置大概在这里:
[748/766] Linking CXX executable OpenCLProgramBuildTest.out
...
[756/766] Linking CXX executable timeProfile.out
为什么会失败?
MNN 的 CMakeLists.txt
默认会编译很多 测试用的可执行文件(比如 timeProfile.out
, testModel.out
,这些都是 PC/Linux 下测试 MNN 用的,不是 Android 必须的)。
但是我现在的目标是 交叉编译到 Android,这些可执行文件在 Android NDK 下是没法正常链接的(因为它们需要 main()
,还依赖 host 库),所以链接失败。
✅ 解决方法
只需要 构建 so 库,而不是这些测试程序。
在 CMake 配置时加上:
-DBUILD_TEST=OFF -DMNN_BUILD_TEST=OFF
完整命令变成:
cmake .. -G Ninja \-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \-DANDROID_ABI=arm64-v8a \-DANDROID_PLATFORM=android-33 \-DMNN_LOW_MEMORY=true \-DMNN_CPU_WEIGHT_DEQUANT_GEMM=true \-DMNN_BUILD_LLM=true \-DMNN_SUPPORT_TRANSFORMER_FUSE=true \-DMNN_ARM82=true \-DMNN_USE_LOGCAT=true \-DMNN_OPENCL=true \-DLLM_SUPPORT_VISION=true \-DMNN_BUILD_OPENCV=true \-DBUILD_TEST=OFF \-DMNN_BUILD_TEST=OFF
然后重新执行:
ninja install
编译结果
这样就不会去编译那些 xxxTest.out
、xxxProfile.out
,只会输出核心库:
build_64/lib/libMNN.so
build_64/lib/libMNN_Express.so
这些 .so
文件才是在 Android App 里要用的。
-
构建 Android App
- 打开
apps/Android/MnnLlmChat/
- Gradle 自动拉依赖(需要联网)
- 连接手机,点击 Run
遇到的错误是典型的 Android Studio + CMake/Ninja 找不到预编译的 libMNN.so 错误:
- 打开
ninja: error: '../../../../../../../../project/android/build_64/lib/libMNN.so',
needed by '.../libmnn_tts.so', missing and no known rule to make it
意思是:
libmnn_tts.so
依赖libMNN.so
。- Ninja/Gradle 想在路径
project/android/build_64/lib/libMNN.so
找到它,但实际没有。 - 因为 CMake 没有生成
.so
或者生成路径不对,所以报错。
🔑 原因分析
- 可能没有把 MNN 编译成 Android 库(或者编译失败了,参考你之前的链接报错)。
- 或者 CMake 输出路径不对,默认可能在
build_64/lib/
或build_64/install/lib/
。 - 或者测试程序编译失败导致 Ninja 中断,所以
.so
没生成。
✅ 解决方案
1️⃣ 重新配置 CMake,只生成 Android 库
在 project/android/build_64
里:
cmake .. -G Ninja \-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \-DANDROID_ABI=arm64-v8a \-DANDROID_PLATFORM=android-33 \-DMNN_LOW_MEMORY=true \-DMNN_CPU_WEIGHT_DEQUANT_GEMM=true \-DMNN_BUILD_LLM=true \-DMNN_SUPPORT_TRANSFORMER_FUSE=true \-DMNN_ARM82=true \-DMNN_USE_LOGCAT=true \-DMNN_OPENCL=true \-DLLM_SUPPORT_VISION=true \-DMNN_BUILD_OPENCV=true \-DBUILD_TEST=OFF \-DMNN_BUILD_TEST=OFF
重点:
BUILD_TEST=OFF
+MNN_BUILD_TEST=OFF
确保不会去编译 PC 测试程序导致中断。
2️⃣ 编译安装
ninja install
遇到的错误是 LLM 模块在编译 Android 共享库 libllm.so 时链接失败,报错信息:
undefined symbol: MNN::CV::imread(std::__ndk1::basic_string<char, ...> const&, int)
referenced by omni.cpp:557