该技能用于诊断 Gradle 中“配置在预期之前被解析”的构建失败。典型报错为:Cannot mutate the dependencies of configuration ':<module>:<someVariant>' after the configuration's child configuration ':<module>:runtimeClasspath' was resolved. 即使只是新增一行普通依赖声明或应用一个新插件,也可能触发。
用途:定位这类报错的根因,并提供排查和规避思路。
主要原因:插件在 apply() 阶段创建按变体、架构或 flavour 划分的配置,并通过 extendsFrom 挂入主配置图;期间某个逻辑提前解析了 runtimeClasspath,使该配置及其所有父配置被冻结,后续依赖声明因此报错。插件在 apply 阶段提前解析的常见路径是:注册带构造参数的任务,Gradle 必须立即实例化该任务,任务的 init 块随之执行,并沿路径访问运行时类路径(例如定位 jar 任务输出)。
排查方法:不要反复改写依赖语法。资料列出的无效尝试包括:把按变体依赖移到更早的 dependencies 块、改用 configurations.named(...).dependencies.add(...)、改用直接 Maven 坐标、仅禁用两个可疑插件之一、修改工具链声明。建议从厂商提供的最小可用模板出发,逐个加回插件做二分:每轮只改一个插件,使用 :<module>:tasks --no-configuration-cache 只运行配置阶段复现,速度快。将可工作模板的插件列表与失败模块对比,可缩小可疑插件范围。
可能的修复:1)调整 plugins {} 应用顺序。某些插件在 apply 时需要已存在产物任务,例如在提供普通 jar 任务的插件之后、在会替换该任务的插件之前应用打包插件。2)使用兄弟配置:创建一个扩展运行时类路径的新配置,让提前解析的消费者解析它,从而把锁定转移到之后无需修改的配置上。
验证与限制:仅运行配置阶段可排除编译因素。使用 --no-configuration-cache 验证修复;配置缓存命中时 Gradle 会重放已存配置结果,可能显示通过但问题仍在,需注意输出是“Configuration cache entry reused”还是“stored”,并强制重跑后再下结论。资料指出,关于同时禁用两个可疑插件是否必要仍是开放问题,相关诊断并未完全闭环。另一相关问题是严格输入输出验证:插件产出的文件被使用但未声明为输入时会报错,报错指向消费任务而非产出插件;可将产出插件固定回声明该输入的版本,并由消费方显式 dependsOn 作为防御。