在过去的几周里,我根据 Xlog 和 Loagan 的设计思路,使用 Rust 写了一个移动端的跨平台日志库EZLog。
在我实现这个库的过程中,查阅了大量的问答和博客。因为这些开发者的分享,节省了我大量的时间。所以我把我的经历也分享出来。
如果以下任何一个点你感兴趣,不要划走。
- 当下(2022)Rust 在移动端的开发体验如何
- 没有 Java/Kotlin 代码,不使用 AndroidStudio 和 Gradle, 秒级编译并打包 Apk 运行
- Rust 编译静态库打包到 XCFramework, 发布 Cocoapods
起因
22 年初,我有一个游戏需求,要在 android 上实现匀速的贝塞尔曲线路径移动。依赖 kurbo写了一个生成贝塞尔曲线 LUT 的命令行工具,体验很好。于是想尝试一下,发挥 Rust 的优势,在移动端写一个对性能有要求的开源库,第一个想到的就是日志。
可行性调查
大型公司在移动端使用 Rust
- Google 在 2021 年将 Rust 引入 Android Rust in the Android platform
- Mozilla 使用 Rust 编写跨平台应用服务组件Firefox Application Services
- 飞书客户端非 UI 部分使用 Rust 跨平台实现
个人开发者在移动端的尝试 Rust 的案例
- Rust & cross-platform mobile development
- RustDesk 远程桌面应用
- 深度探索:前端中的后端
- Publish game on Android with Macroquad
- Rust on iOS and Mac Catalyst: A Simple, Updated Guide
更多的案例收录,可以参看这篇Rust 移动开发与跨平台模式探究。
从以上的例子来看,大概率是可行的,还要对具体的需求进行验证。
项目简述
主要功能
- 使用 mmap 做文件映射
- 认证加密
- zlib 压缩
- 日志回捞
- 日志清理
- 命令行解析工具
可行性验证
先查找主要功能是否有对应的 Rust 开源实现。
开源社区早已实现好了:)
复制开源库中的示例,借助android-ndk-rs。在 android 真机运行,查看日志输出,符合预期。
项目中使用android ndk rs
的例子,可以查看examples/android_preview
cargo apk run -p ezlog_android_preview
Compiling ezlog v0.1.2 (ezlog/ezlog-core)
Compiling ezlog_android_preview v0.1.0 (ezlog/examples/android_preview)
Finished dev [unoptimized + debuginfo] target(s) in 2.39s
'lib/arm64-v8a/libezlog_android_preview.so'...
Verifying alignment of ezlog/target/debug/apk/ezlog_android_preview.apk (4)...
49 AndroidManifest.xml (OK - compressed)
1020 lib/arm64-v8a/libezlog_android_preview.so (OK)
Verification succesful
Performing Incremental Install
Serving...
All files should be loaded. Notifying the device.
Success
Install command complete in 949 ms
Starting: Intent {
act=android.intent.action.MAIN cmp=rust.ezlog_android_preview/android.app.NativeActivity }
项目结构
├── android
│ ├── app # android 示例工程
│ └── lib-ezlog # EZLog android 库
├── examples # rust 示例
├── ezlog-cli # 命令行工具
├── ezlog-core # 核心库
├── ios
│ ├── EZLog # EZLog iOS 库
│ ├── demo # iOS 示例工程
│ └── framework # EZLog XCFramework
开发中碰到的问题及解决
iOS
iOS 端的开发流程为
- Rust 编码
- 通过 cbindgen 生成头文件
- 编译多平台静态库
- 把静态库和头文件打包成 XCFramework,并依赖
- 实现 Swift 绑定
- 测试,发布
在对比了多种依赖静态库的方式之后,发现XCFramework对多平台的支持,更适合这个项目。更多 XCFramework 的相关资料可以看这几篇文章distributing universal ios frameworks as xcframeworks using cocoapods,
Static libraries into XCFramework,From Rust To Swift。在项目中的构建使用,可以参看ios/b_ios.sh
脚本。
Swift 与 C 的互相调用,很多概念需要了解。在被Unmanaged
, @escaping
,@convention
,UnsafePointer
,UnsafeBufferPointer
,
UnsafeMutableRawPointer
折磨许久之后,终于可以在 Swift 中拿到 Rust 的回调了。
Cocoapods 支持 XCFramework,尝试了 SPM,找不到符号的问题没有解决。暂时放一放。在花费了以天计的时间成本之后,终于在 Cocoapods 成功发布。
对比一下三个包管理工具的从注册到发布的时间成本&#x