📒 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