基于 Flutter 实现 Windows 平台离线大模型对话应用实战
1、背景
前面文章《基于 Flutter 实现跨平台离线大模型对话应用》中介绍了基于 Flutter 实现跨平台的离线模型对话应用,跑通了 Android、iOS、Mac 平台,在编译 Windows 平台时由于不熟悉 Windows 平台编译器,踩了一些坑,最终搞了一个晚上加一个上午成功搞定。
2、Windows 编译器介绍
传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd)。在编译过程中:
前端主要负责词法和语法分析,将源代码转化为抽象语法树;
优化器则是在前端的基础上,对得到的中间代码进行优化,使代码更加高效;
后端则是将已经优化的中间代码转化为针对各自平台的机器代码。
作为一个移动端开发,日常用到最多的 C++编译器是 GCC、Clang。
GCC(GNU Compiler Collection,GNU 编译器套装),是一套由 GNU 开发的编程语言编译器。GCC 原名为 GNU C 语言编译器,因为它原本只能处理 C 语言。GCC 快速演进,变得可处理 C++、Fortran、Pascal、Objective-C、Java 以及 Ada 等他语言。
Clang 是以 LLVM(Low Level Virtual Machine,底层虚拟机)为后端的一款高效易用,并且与 IDE 结合很好的编译前端。Clang 只支持 C,C++ 和 Objective-C 三种语言。
虽然 Windows 上也有 Cygwin、MinGW、TDM-GCC 等 GCC 移植版本,但我们还是选微软官方的 MSVC 系列编译器。它与 Visual Studio 集成发布,微软自己的编译器,VS 是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如 UML 工具、代码管控工具、集成开发环境(IDE)等等。所写的目标代码适用于微软支持的所有平台,包括 Microsoft Windows、Windows Mobile、Windows CE、.NET Framework、.NET Compact Framework 和 Microsoft Silverlight 及 Windows Phone。
3、Windows 平台开发 Flutter 桌面应用
3.1 环境安装
Flutter 2.10 开始,对 Windows 的支持已进入 stable
渠道。要开发 Windows 应用除了安装 Flutter SDK,还需要安装微软提供的 Visual Studio22 或者是 Visual Studio 2022 生成工具。在安装时要选择”使用 C++的桌面开发“,它包含了所有默认组件(必要的 C++工具链和 Windows SDK 的头文件)。
3.2 配置 C++编译脚本
直接在 windows 目录下创建 CMakeLists.txt 文件,在 CMakeLists.txt 中直接添加编译信息:
也可以添加子目录方式添加对应模块:
3.3 遇到问题
项目里面有几个
.cpp
文件还有一个.c
文件,这样配置后运行flutter run
,一直报错,提示连接 C 文件里的函数失败,查看了编译时中间文件,发现 C 文件没有被执行编译,最后发现是 CMakelist.txt 中指定了project(${PROJECT_NAME} LANGUAGES CXX)
编译语言导致 C 文件没有执行编译,其他平台都没问题,Windows 上报错。运行时 FFI 查找 C 函数时提示找不到,将编译出的 DLL 文件放到指定路径,通过指定路径加载也同样失败,而且 debug 查看,动态库已经成功加载,就是找不到函数。向外暴露的函数通过
#define EXPORT_API __attribute__ ((visibility ("default")))
定义的 EXPORT 修饰:EXPORT_API void* init(const char* path);
,windows 编译时 EXPORT_API 修饰报错,以为这个修饰没有用,直接删除掉了,导致找不到函数。最后通过:
来支持不同平台接口。
3.4 应用打包
我们一般安装 windows 程序都提供了一个安装包,我们执行安装,然后释放资源和可执行文件,同时应用程序发布到微软商店前必须要打包。有效的格式是 .msix、.msixbundle、.msixupload、.appx、 .appxbundle、.appxupload 和 .xap。Flutter 提供了打包 msix 程序的工具。MSIX 是微软提供的新的 Windows 应用程序包格式,它提供了一种现代的打包格式和安装程序。这种格式既可以用于将应用程序发布到 Windows 上的 Microsoft Store,也可以直接分发应用程序安装程序。
Flutter 提供了 MSIX pub 打包方式。打包时需要配置.pfx 证书:
请下载 OpenSSL 工具包来生成证书。
进入 OpenSSL 的安装路径,例如
C:\Program Files\ OpenSSL- win64 \bin
。为方便使用我们设置一个环境变量,这样可以从任何地方访问 OpenSSL。生成私钥:
Openssl genrsa -out mykeyname.key 2048
。使用私钥生成证书签名请求(CSR)文件:
Openssl req -new -key mykeyname.key -out mycsrname.csr
使用私钥和 CSR 文件生成已签名的 CRT 文件:
openssl x509 -in mycsrname.csr -out mycrtname.crt -req -signkey mykeyname.key -days 10000
使用私钥和 CRT 文件生成。pfx 文件:
openssl pkcs12 -export -out CERTIFICATE.pfx -inkey mykeyname.key -in mycrtname.crt
在安装应用程序的机器上安装.pfx 证书,配置作为受信任的根证书颁发机构。
Flutter 可执行文件.exe
可以在我们的项目build\windows\runner\<build mode>\
下找到。除了.exe
可执行文件,您还需要以下文件:
统一目录上所有的
.dll
文件data 目录
拷贝依赖文件:
msvcp140.dll
,vcruntime140.dll
,vcruntime140_1.dll
最终目录结构:
3.5 Flutter 插件
我们代码里面写死了加载.dll
文件路径,打包后解压安装后加载路径不好找,Flutter 提供了插件支持,我们只需要创建 Native 插件即可,不用再考虑加载路径的问题。
flutter create --template=plugin_ffi hello
创建插件;pubspec.yaml
配置 FFI plugins:
这样在插件里面实现本地代码,应用工程中调用插件代码即可。
参考:
https://zhuanlan.zhihu.com/p/458488070
Flutter Packages 的开发和提交 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
4、性能优化
运行时效果不是很理想,使用的 thinkpad,2.8G 主频 8 核,24G 内存,SSD,推理速度不是很快,开启编译优化:
并没有很快的速度提升,具体优化还得持续研究。
5、总结
本文介绍了 Windows 上的 MSVC C++编译器以及 Flutter 创建桌面应用的步骤及应用程序打包方式,并分享了 FFI 集成本地代码遇到的问题和解决办法。
版权声明: 本文为 InfoQ 作者【轻口味】的原创文章。
原文链接:【http://xie.infoq.cn/article/a0b086b20aabd229e57a9811f】。文章转载请联系作者。
评论