【操作记录】我的 MNN Android LLM 编译学习笔记记录(一)

MNN Android 编译命令零基础解析笔记

我今天尝试在 Windows 上用 Android NDK + Ninja 编译 MNN,生成支持 LLM 的 Android 库。刚开始,我几乎完全不懂命令的意思,只是看教程复制粘贴。这里我把命令拆开,做了每个单词的英文来源、构词法和零基础解释,希望自己以后回头看能懂。

我用的命令是:

bash 复制代码
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

我来一个个解释。


1. cmake ..

  • 英文来源

    • cmake → "C Make",意思是"为 C/C++ 生成构建系统"(Makefile)
    • .. → "上一级目录",告诉 cmake 去上一级目录找 CMakeLists.txt 文件
  • 零基础理解

    • 我们的项目里有一个 CMakeLists.txt,就像"食谱",告诉电脑怎么做饭(编译程序)
    • cmake .. 就是让 cmake 去上一级目录找到这个食谱
  • 比喻

    • 想象你在厨房里(build 目录),你告诉助手(cmake):"去客厅的书架上拿菜谱(...)",然后开始准备原料(生成 Makefile/Ninja 文件)。

2. -G Ninja

  • 英文来源

    • -G → "Generator",意思是生成器
    • Ninja → Ninja 是一个编译工具,比 Make 快
  • 零基础理解

    • cmake 支持生成不同类型的构建文件,比如 Makefile 或 Ninja
    • -G Ninja 就是告诉 cmake:"我用 Ninja 来编译项目"
  • 比喻

    • 就像你选择开车还是骑自行车去超市,-G Ninja 就是选择"骑 Ninja 电动车",速度快。

3. -DCMAKE_TOOLCHAIN_FILE=...

  • 英文来源

    • D → define(定义一个变量)

    • CMAKE_TOOLCHAIN_FILE → "CMake 工具链文件"

      • toolchain → 工具链,指编译、链接等一整套工具
      • file → 文件
  • 零基础理解

    • NDK 里有很多工具(编译器、链接器),要告诉 cmake 用哪一套工具
    • -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake
      就是指向 NDK 提供的"工具链文件",告诉 cmake 用 Android 编译器

NDK 是什么,为什么这里会提到 NDK

1️⃣ NDK 是什么

  • 英文全称Native Development Kit

    • Native → 本地的(这里指直接用 C/C++ 写的程序)
    • Development → 开发
    • Kit → 套件、工具包
  • 零基础理解

    • Android 平常用 Java/Kotlin 写程序,但有些程序要更快或者用 C/C++ 写,比如 MNN 这种神经网络库
    • NDK 就是 Android 官方提供的一套 C/C++ 编译工具,用来把你写的 C/C++ 代码变成 Android 手机能运行的程序

2️⃣ 为什么 CMake 要提到 NDK

  • CMake 是一个"总指挥",它需要知道你用哪套工具来编译程序

  • 工具链(toolchain)

    • 就是一整套工具:编译器、链接器、汇编器等
    • NDK 自带 Android 专用的工具链
  • -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake

    • CMAKE_TOOLCHAIN_FILE → 告诉 CMake "你的工具链文件在哪"
    • $ANDROID_NDK/.../android.toolchain.cmake → 指向 NDK 提供的专门文件,让 CMake 知道用 Android 的编译器
  • 比喻

    • 你要做饭(编译程序),但是厨具太多,不知道用哪套
    • 工具链文件就是一张说明书:告诉你用锅、用刀、用火,按 Android 手机的要求做菜

3️⃣ 总结

  1. NDK = Native Development Kit = Android 官方 C/C++ 工具包
  2. CMake 需要知道"你用哪套工具链",所以用 -DCMAKE_TOOLCHAIN_FILE 指向 NDK 提供的文件
  3. 这就是为什么命令里出现了 NDK

4. -DANDROID_ABI=arm64-v8a

  • 英文来源

    • ABI → Application Binary Interface,应用程序二进制接口
    • arm64-v8a → ARM 64位架构(手机芯片型号)
  • 零基础理解

    • 告诉 cmake 我编译的是 64 位 ARM 手机
    • 如果手机是 32 位,或者 x86 模拟器,这里要改

5. -DANDROID_PLATFORM=android-33

  • 英文来源

    • ANDROID_PLATFORM → 安卓平台版本
    • android-33 → Android API 33(对应 Android 13)
  • 零基础理解

    • 告诉 cmake 你要编译的安卓系统版本
    • 不同版本可能有不同的系统库
  • 比喻

    • 就像做菜:要做给 3 岁的小朋友还是 10 岁的小朋友吃,调料量不一样。

6. -DMNN_LOW_MEMORY=true

  • 英文来源

    • LOW_MEMORY → 低内存
    • true → 开启
  • 零基础理解

    • 告诉 MNN 库尽量节省内存

7. -DMNN_CPU_WEIGHT_DEQUANT_GEMM=true

  • 英文来源

    • CPU_WEIGHT_DEQUANT_GEMM

      • CPU → 中央处理器
      • WEIGHT → 模型权重
      • DEQUANT → 去量化
      • GEMM → General Matrix Multiply(矩阵乘法)
  • 零基础理解

    • 这是让 CPU 在执行神经网络矩阵运算时用去量化方式,提高效率
  • 比喻

    • 就像做饭前把食材切小块,更容易炒熟。

8. -DMNN_BUILD_LLM=true

  • 英文来源

    • BUILD → 编译
    • LLM → Large Language Model(大型语言模型)
  • 零基础理解

    • 告诉 MNN 要编译 LLM 相关模块
  • 比喻

    • 就像选择菜单:"今晚要做大餐(LLM 模块)"。

9. -DMNN_SUPPORT_TRANSFORMER_FUSE=true

  • 英文来源

    • SUPPORT → 支持
    • TRANSFORMER → Transformer 模型
    • FUSE → 融合
  • 零基础理解

    • 开启 Transformer 模型优化融合
  • 比喻

    • 就像做菜时把两个步骤合并成一个步骤,更快完成。

10. -DMNN_ARM82=true

  • 英文来源

    • ARM82 → ARM CPU 的一个指令集扩展
  • 零基础理解

    • 让 MNN 优化 ARMv8.2 架构的指令
  • 比喻

    • 就像厨房升级了更高档的炉子,可以快炒。

11. -DMNN_USE_LOGCAT=true

  • 英文来源

    • LOGCAT → Android 的日志系统
  • 零基础理解

    • 让程序在 Android 上打印日志,方便调试

12. -DMNN_OPENCL=true

  • 英文来源

    • OPENCL → Open Computing Language,GPU 加速
  • 零基础理解

    • 告诉 MNN 使用 GPU 来加速计算

为什么 -DMNN_OPENCL=trueGPU 有关系?

1. 英文来源

  • OPENCLOpen Computing Language

    • Open → 开放的
    • Computing → 计算
    • Language → 语言
  • 所以完整意思就是"开放计算语言",是一种可以用来控制GPU进行计算的语言


13. -DLLM_SUPPORT_VISION=true

  • 英文来源

    • VISION → 视觉
    • SUPPORT → 支持
  • 零基础理解

    • 开启 LLM 的视觉模块,需要处理图像
  • 比喻

    • 就像做大餐不仅要炒菜,还要拍美图。

14. -DMNN_BUILD_OPENCV=true

  • 英文来源

    • OPENCV → Open Source Computer Vision Library(开源计算机视觉库)
  • 零基础理解

    • 告诉 MNN 编译自带的 OpenCV 功能,比如 imread(读图)
  • 比喻

    • 就像准备相机拍菜,拍之前得先准备好相机。

15. -DBUILD_TEST=OFF-DMNN_BUILD_TEST=OFF

  • 英文来源

    • BUILD_TEST → 是否编译测试程序
    • OFF → 关闭
  • 零基础理解

    • 不编测试程序,只编正式库
  • 比喻

    • 就像做饭时不做试吃菜,只做正餐。

总结

  • 每个 -D 是"定义一个变量",cmake 根据变量决定编译哪些模块

  • 每个模块名称都有英文原意,很多是缩写

  • -G Ninja 是选择 Ninja 构建系统

  • -DCMAKE_TOOLCHAIN_FILE 是指定 NDK 工具链

  • -DANDROID_ABI=arm64-v8a 指定手机芯片架构

  • -DMNN_BUILD_LLM=true 要编 LLM

  • -DMNN_OPENCL=true 是 GPU 加速

  • -DMNN_BUILD_OPENCV=true 让 MNN 自带的 OpenCV 功能编进去

配置完后,CMake 没报错,看起来一切正常:

复制代码
-- Configuring done
-- Generating done
-- Build files have been written to: G:/down/MNN-master/MNN-master/build_64

二、开始编译

我直接运行:

bash 复制代码
ninja install

然后就报错了:

复制代码
undefined symbol: MNN::CV::imread
referenced by omni.cpp:557

我只知道 imread 是读图像的意思,其他完全没概念。我尝试理解:

  • 编译器说找不到 MNN::CV::imread 这个东西
  • 它好像在 omni.cpp 里被用到了
  • 我的 CMake 配置里 -DMNN_BUILD_OPENCV=true,理论上应该有这个函数啊

总之,我看到就是链接失败


三、查找原因

我尝试去看 OpenCV 模块有没有生成:

bash 复制代码
D:/sdk/ndk/27.2.12479018/toolchains/llvm/prebuilt/windows-x86_64/bin/llvm-nm.exe -gC OFF/arm64-v8a/libMNNOpenCV.so | grep "imread"

报错:

复制代码
No such file or directory

我心里一紧:原来 OpenCV 模块根本没生成。

然后尝试单独编 OpenCV 模块:

bash 复制代码
ninja MNNOpenCV

结果:

复制代码
ninja: no work to do.

我完全懵了,好像它又说已经编好了,但实际上那个库文件根本不存在。

相关推荐
Frank_HarmonyOS18 分钟前
Android MVVM(Model-View-ViewModel)架构
android·架构
Insist75329 分钟前
k8s----学习站点搭建
学习
月盈缺41 分钟前
学习嵌入式第二十三天——数据结构——栈
数据结构·学习
mysla1 小时前
嵌入式学习day34-网络-tcp/udp
服务器·网络·学习
Moonnnn.1 小时前
【51单片机学习】AT24C02(I2C)、DS18B20(单总线)、LCD1602(液晶显示屏)
笔记·单片机·学习·51单片机
牛奶咖啡132 小时前
学习设计模式《二十三》——桥接模式
学习·设计模式·桥接模式·认识桥接模式·桥接模式的优点·何时选用桥接模式·桥接模式的使用示例
Jenkinscao4 小时前
我从零开始学习C语言(13)- 循环语句 PART2
c语言·开发语言·学习
lincats6 小时前
一步一步学习使用FireMonkey动画(1) 使用动画组件为窗体添加动态效果
android·ide·delphi·livebindings·delphi 12.3·firemonkey
✎ ﹏梦醒͜ღ҉繁华落℘6 小时前
单片机学习---字节对齐
单片机·嵌入式硬件·学习