Skip to content

依赖库增量编译

构建文件变化通常会让 Jugg 回到 Gradle。依赖库升级是其中一个受控例外:在用户确认后,变化的依赖库可以复用增量编译链,而不必每次都走完整 Gradle 构建。

构建文件变化无法自动判定安全

Gradle 配置能影响 task、source set、variant、依赖解析、代码生成和插件行为。Jugg 不可能穷举所有构建信息的变化形态;维护成本太高,也无法覆盖每个工程的自定义配置。一旦漏判 build 文件里的非依赖改动,本轮编译就会基于错误上下文运行。

默认策略是保守的:build 文件变化先回到 Gradle 重建基线。依赖库版本升级是开发中高频出现、且可以由用户确认 diff 的例外场景;这类改动每次都全量构建并不划算。

两步确认与库内文件 diff

Jugg 把依赖库升级从「自动判定」改为「用户确认」,把判断拆成两步:

text
检测到 build 文件变化
  -> 展示 build 文件 diff
  -> 用户选择查找变化依赖或回退 Gradle
  -> 通过 Gradle 读取当前依赖信息
  -> 与上次基线依赖信息对比
  -> 展示变化库结果
  -> 用户确认后进入增量编译

非回退操作带倒计时确认,降低误点风险;用户也可以直接选择 Gradle 回退重建完整基线。依赖 diff 依赖两份数据:Gradle 构建完成时保存的基线依赖信息,以及用户选择查找变化时重新读取的当前依赖信息,二者对比得出新增、升级、降级或删除的库。

确认变化后,优化点在于不整库重编。依赖库内容主要是 jar、资源和 assets,这些输入与 Jugg 已有的源码、资源、assets 编译链相同。Jugg 先比较升级前后的库文件,只把变化文件送进对应编译链:

text
变化的依赖库
  -> 与基线库做文件 diff
  -> jar 变化进入源码 / DEX 编译
  -> res 变化进入资源编译
  -> assets 变化进入 asset overlay
  -> 产物交给部署阶段

历史测试数据中,直接编译一个约 20 MB 的协议库约需 2 分钟;做库内文件 diff 后,依赖库编译耗时约 5 秒。需要说明的是,查找依赖变化本身要执行一次 Gradle,整体流程的主要耗时在这个阶段,常见范围为 40~80 秒。

部署侧不只处理升级,还要让设备状态与当前依赖库内容一致:

场景处理方式
正常升级且文件有变化编译变化文件并部署增量产物
新增依赖库新库文件进入本轮增量编译和部署判断
删除依赖库作为移除的库进入部署数据判断
升级后又回退版本移除对应增量部署,避免设备保留错误产物
再次升级但内容回退同样移除已不应存在的增量部署

何时改用 Gradle 回退

依赖库增量只覆盖「确认安全」的升级,超出这个范围就应该回到完整构建。以下情况更适合 Gradle 回退,而不是依赖库增量:

  • build 文件里除了依赖库,还改了会影响 APK 的配置。
  • 修改了 Gradle 插件、source set、variant、注解处理器或 Kotlin 编译器插件配置。
  • 依赖变化后出现源码解析失败,更新编译上下文后仍无法恢复。
  • 用户无法确认展示的依赖变化是否符合预期。

如果用户确认 build 文件变化对当前开发没有影响,也可以选择忽略;忽略后 Jugg 会恢复增量状态、把本次 build 文件变化当作未发生处理,后续仍可手动回退 Gradle 重建基线。

相关页面