工程信息刷新与恢复
一次成功的完整 Gradle 构建会留下两类状态:模块、variant、依赖、编译参数和输出路径等工程信息,以及 APK、classpath、资源表和生成代码等完整构建产物。Jugg 将两者组合为后续增量编译的起点。
工程信息把源码文件映射到模块、编译输入、输出路径和目标 APK。Jugg 可以在不重新生成 APK 的情况下单独读取这部分信息,但刷新结果只有在仍与现有完整构建产物对应时,才能用于本轮增量编译。
本文所说的工程信息“失效”,不是指文件保存时间较早,而是它已经无法描述当前构建配置,或者无法与现有完整构建产物对应。
工程信息什么时候会失效
工程信息和完整构建产物共同对应某个确定的构建目标。切换 Build Variant、BuildTarget 或 Gradle 编译命令后,两者仍属于上一个目标。
编译目标从 debug 切换到 release
-> 现有工程信息和完整构建产物仍属于 debug
-> 它们无法描述 release 的编译输入与目标 APK
-> Jugg 执行完整 Gradle 构建
-> 新工程信息和新构建产物成为后续增量的起点修改构建脚本、依赖、version catalog、source set 或构建插件也可能改变相同信息。明确的依赖变化可以进入依赖增量判断;无法收窄为局部依赖变化时,需要由 Gradle 重新确认完整构建结果。
刷新如何更新增量输入
工程信息需要更新时,Jugg 使用当前 Gradle 命令和构建目标读取真实构建环境,再与 Android Studio 提供的模块和源码结构合并。Gradle 侧提供实际 variant、依赖、编译参数和 build directory,IDE 侧补充当前工程中的模块与 source root。
发现工程信息需要更新
-> 使用当前 Gradle 命令读取构建信息
-> 合并 IDE 与 Gradle 提供的工程结构
-> build 文件、编译命令和 BuildTarget 均未变化
-> 更新 classpath、输出路径和 APK 归属
-> 本轮可以继续增量编译
-> build 文件、编译命令或 BuildTarget 已变化
-> 新工程信息与现有构建产物不再对应
-> 本轮转完整 Gradle 构建
-> 使用新工程信息和新构建产物重建基线明确识别为依赖库增删改、并经用户确认的 build 文件变化,可以进入依赖增量流程。该流程使用依赖差异临时调整本轮编译输入,不会把一次普通工程信息刷新直接作为新的完整构建基线。
读取发生在当前工程的 Gradle 环境中,因此能够跟随 AGP variant API、Kotlin 编译任务和自定义 build directory 的实际变化。Jugg 会对已知版本差异使用匹配的读取方式;这一步只更新工程信息,不会生成 APK、资源表、生成代码或其它 Gradle task 产物。
工程信息包含哪些字段、IDE 与 Gradle 数据如何合并,见工程上下文获取。
工程信息缺失时如何收口
工程信息文件缺失、损坏或无法反序列化时,Jugg 会启动一次后台读取。仍准备执行增量编译的任务会等待这次工程信息重建完成,再重新检查增量条件。
发现工程信息缺失或无效
-> 启动 Gradle 工程信息读取
-> 增量任务等待本轮重建结束
-> 读取成功且仍与现有基线对应:继续本轮增量
-> 读取失败或无法与现有基线对应:转完整 Gradle已经确定需要完整 Gradle 构建的路径不依赖这次后台读取完成,可以直接开始构建。这样,工程信息恢复只阻塞需要它的增量路径,不会把局部维护任务扩大成所有构建流程的等待条件。
远端编译命令变化时,Jugg 会用新命令刷新本地工程信息,并与远端完整构建并行执行。远端构建完成后,初始化下一轮增量只等待这次明确关联的刷新;IDE Sync 或依赖恢复触发的其它后台读取不会额外阻塞远端初始化。
刷新结果什么时候可以直接使用
| 工程状态变化 | Jugg 的处理 |
|---|---|
| build 文件、编译命令和 BuildTarget 均未变化 | 刷新工程信息,成功后继续复用现有完整构建基线 |
| 工程信息文件缺失或无效,但构建配置未变化 | 重建工程信息,成功后可用于本轮增量 |
| Android Studio Sync 更新模块结构,构建输入未变化 | 合并新的 IDE 信息,Gradle 信息缺失时异步补读 |
| build 文件变化 | 默认执行完整 Gradle;明确确认的依赖变化可进入依赖增量流程 |
| 远端编译命令变化 | 用当前命令刷新本地工程信息,同时执行远端完整构建 |
| Build Variant、BuildTarget 或编译命令变化 | 执行完整 Gradle 构建,为新目标建立基线 |
| 插件、task graph、source set 或工具链变化 | 由完整 Gradle 构建重新确认输入和产物 |
| included build 本轮信息缺失 | 有上次有效副本时保留,没有历史副本时跳过 |
复合构建的恢复遵循 Best-effort 原则:某个 included build 本轮没有生成工程信息时,只复用已经成功读取过的旧副本,不伪造新的模块或依赖。下一次读取成功后会用新结果替换旧副本。