起因
因为我开发的ROneBot框架需要一个项目模板生成器, 之前是Jvm的ktor但是因为项目已经迁移到了Multiplatform所以还得单独为这个模块设置Jvm的Kotlin插件这样写起来很不美观,于是我就搜索了一下
在native二进制文件中嵌入资源的东西,然后就找到了kMBed这个插件, 但是这个插件作者的maven仓库被墙了,我把项目拉下来自己发布到自己的仓库但是不生效, 我恍然大悟原来可以开发一个gradle插件
然后识别resources内的资源文件将其作为byteArrayOfkotlin源码最后经过kotlin编译器编译生成的代码来实现"嵌入"到二进制文件内。
gradle插件
首先就是gradle插件了,由于只是获取resources内的资源文件并不需要扫描源码所以就不用ksp或者kcp了,创建一个设置里面可以设置kmp不同源码集的resources路径, 然后注册一个任务,将这些路径内的资源文件全部生成为.kt文件源码,说白了就是简单的源码生成器
运行时
既然生成了一个资源map,那肯定得提供一个简单的API来将其快捷的转换成字符串或者ByteArray, 当然如果所有东西都在内存操作的话是不需要额外的io库的,下面是Resource类的具体实现
public class Resource(uSource: UByteArray, private val compressed: Boolean = false) {
private val source = uSource.toByteArray()
public fun asByteArray(): ByteArray = if (compressed) source.zlibDecompress() else source
public fun asString(): String {
return asByteArray().decodeToString()
}
}
gradle插件会生成一个Map,map的键就是resources下的路径+文件名,值就是Resource对象, 当然也可以配置zlib压缩, 这个zlib压缩的库是我自己实现的使用到了posix + cinterop的API
这里是zlib的仓库地址 https://github.com/RTAkland/kzlib 这个库除了android(native) 、 js 、wasmJs不支持外其余所有的target都是支持的
gradle插件除了会生成一个map还会附带一个方法 这个方法的签名如下
public fun getResource(path: String): Resource
传入路径即可获取Resource对象, 再调用Resource内的两个方法即可转换成不同的类型
文件系统运行时
如果还想将这个资源文件保存到文件系统来减少内存占用可以引入这个模块,此模块由kotlinx-io驱动,
对Resource对象添加了一个拓展函数
public fun Resource.saveTo(path: Path)
最后
这个插件的仓库地址是 https://github.com/RTAkland/KEmbeddableResources 具体如何配置的话看README即可, 使用非常简单
1.本站大部分内容均收集于网络!若内容若侵犯到您的权益,请发送邮件至:xiaoman1221@yhdzz.cn,工作室将第一时间处理!
2.资源所需价格并非资源售卖价格,是收集、整理、编辑详情以及本站运营的适当补贴,并且本站不提供任何免费技术支持。
3.所有资源仅限于参考和学习,版权归原作者所有。



居然真有人愿意折腾KN构建链,respect
想问下这个和externalResource比有啥优势啊
如果资源文件特别多,编译速度影响大不大?
之前用kMBed被墙搞怕了,楼主这自建方案靠谱👍
iOS模拟器支持吗?看target列表有点懵
zlib自己实现确实稳,回头研究下posix调用细节
这个方案比硬编码优雅多了,省了不少事
能不能支持按build type嵌不同资源啊,debug模式不想带大文件
debug模式能关掉资源嵌入吗?打包快一点
666 居然真有人愿意碰Kotlin Native的构建链
这个Resource API设计得蛮干净,没啥多余的东西
之前用Java那边的resource打包习惯了,转native真不适应
蹲个更新,最好加个sample项目,新手友好点
写的啥啊说了半天没讲清楚怎么引入依赖
啊嘛呢吧,又是KMP各种适配,头都大了
那要是想换别的压缩算法呢,比如lz4,能扩展吗?
感觉比kMBed靠谱,至少仓库能访问,文档也清楚
刚试了下Android和macOS都正常,iOS真机待测,先收藏一波
这个saveTo拓展好贴心,终于不用自己写输出流了
话说如果资源特别大,编译出来包体积膨胀严重吗?求个实测数据
不是吧,又来一个gradle插件?配置一次能用一年还是算了吧
楼主这个zlib实现看着稳,回头去翻翻源码学习下posix调用
我之前也整过类似的,用cinterop直接绑二进制段,结果跨平台全跪了😭
听说kotlin native内存管理挺 tricky 的,这样塞一堆资源会不会容易炸?
这方法绝了,比搞一堆externalResource舒服多了
那如果是动态加载资源呢?还是只能编译时嵌进去?
我之前也踩过kMBed仓库被墙的坑,楼主这方案靠谱👍
说白了就是把文件转成byteArray塞进代码里呗,但确实实用
蹲个后续,打算用在自己的项目里试试
又是gradle插件…每次配都头大,有没有更傻瓜的方式?
现在确实只能编译时嵌入,动态加载得另搞套机制,比如远程拉取或者本地文件读取
感觉还行,比硬编码舒服多了
zlib自己实现的?牛啊,不过posix兼容性咋样
前几天刚折腾KMP资源嵌入,要是早看到这个就好了🤔
同踩过这坑,折腾了一整天才发现资源路径大小写敏感问题,气死
求问支持iOS模拟器吗?看target列表有点懵
支持的,iOS模拟器用的是x64目标,插件里已经包含这个target了,放心用
这插件思路挺巧的,省得搞外部资源了