一次编译到底要经过哪些task?
很多人可能很疑惑,一次android的编译过程到底要经过哪些task,谁先谁后? 不同的agp版本 这些task 又有什么异同?理解这个概念很关键,因为当你想对编译过程做一些 干预或者修改的时候 你必须十分清楚这个过程,否则 根本无从下手
收看下这个命令:
/gradlew :app:assembleDebug --dry-run
注意我这个agp版本是3.3
大家可以看下在agp3.3 下 ,一次编译要经过哪些task
红色箭头其实就是表示 我自定义了一个task 将这个task 设置在了 transformNativeLibsWithMergeJniLibsForDebug 与 processDebugJavaRes 之间
再看看 在agp 7.x 下 一次编译要经过哪些task?
大家可以仔细比较一下 2个版本之间的差异
task的输入输出 来猜测 task的作用
其实agp的编译说来也并不复杂,这些task其实就是头尾相接的链表而已,后一个task有时候会读取前一个task的产物,从而将编译进行下去
举个例子:
比如说agp 7.x 我们都知道andorid编译的过程会将所有的aar 中的so 最终都放到一个libs下面对吧 既然有这个任务 我们其实就可以在编译的过程中 获取到每个so的源文件了
可以看下 下面这张截图:
你看在7.x版本中 我们就可以在路径 app/build/intermediates/merged_native_libs 看到这些so了, 注意文件夹的名字 merged_native_libs
是不是一眼就能猜到这个 文件夹是哪个task 任务生成的?
同样的我们还可以看下 agp 3.3 版本看看这个版本是如何做到的?
是不是有很大的不同? 同样的 我们根据这个路径 再通过之前的dry run 命令 是不是也可以猜测到 在agp3.3中 这个 task是哪个?
很容易就猜到 是 :app:transformNativeLibsWithMergeJniLibsForDebug 这个task吧
理解Booster中重要的 task 路径以及 task
有了前面的基础 我们就不难理解 Booster中 对task以及对应产物的 重要抽象了
比方说 在深入理解Booster 二中 我们 初步了解了cwebp压缩的逻辑
大家应该对这2个扩展函数/属性 有印象
首先看这个
variant.mergedRes
他其实就是对下图的文件夹下的所有文件做了一个collection 从而方便开发者 去直接获取文件
他的架构实现做的其实也很简单 稍微跟一跟代码:
重要的就是在这里了
我们看下7.0的吧
其实到这里就是在用agp本身的函数了
Booster好用的地方就在于 插件开发者只要关注这个就可以扩展属性或者扩展函数就可以了,其内部的实现都帮你做好了,比如不同版本的文件夹路径 真的都一样吗? 其实也未必,大家有兴趣可以自行探索下 其他扩展函数
同样的我们再看看这个
variant.mergeResourcesTaskProvider
他的作用就是方便你直接取 mergeRes 这个task,这样你可以方便的将任务插在 这个task之后或者之前
从而不用关心不同的agp版本 mergeRes的取得方式
可以稍微看下源码:
注意看下这个task name 他其实也是agp本身的函数了
一般而言 一个重要的build路径 总是要伴随着对应的task的。
了解上面booster 对task的 扩展 会对你对booster的掌握很有帮助
如何调试booster源码
之前有人问到 自己如何调试booster源吗呢, 这里介绍个简单的方式
首先 改下版本号
然后把根目录下面的build文件 做一下修改 注释掉部分语句
然后就就可以publishToMavenLocal啦
直接执行这个任务即可
最后就是你自己的demo 宿主工程中 引入你这个版本号的booster即可
注意有的task 不会带到 agp编译的过程中,需要你手动去触发他
./gradlew tasks --all
可以通过上面这个命令来获取全部的task