gradle仅重编译直/间接依赖变更模块且满足增量条件的子模块。原因包括:任务输入输出定义、依赖声明方式(api/implementation)、构建缓存状态、源码变更类型(如public签名修改)及配置错误(如api滥用、注解处理器路径未隔离)。

Gradle 能自动判断哪些模块需要重新构建,但前提是依赖声明正确、任务输入输出定义清晰。如果你改了公共模块(比如 common-utils),实际触发重编译的模块取决于「谁直接或间接依赖它」以及「是否命中增量构建条件」。
为什么不是所有依赖它的模块都重编译?
Gradle 的增量构建机制只在以下情况才真正触发子模块重编译:
- 该子模块的编译任务(
compileJava或compileKotlin)将公共模块的输出(如classes目录或jar)列为输入; - 公共模块的源码、资源、或其
build.gradle中影响编译逻辑的部分(如sourceSets配置)发生了变更; - 子模块没有启用构建缓存(
buildCache),或缓存中不存在对应输入哈希的产物; - 子模块未使用
implementation而误用了api暴露公共模块的 API —— 这会导致更多下游模块被标记为“可能受影响”,哪怕它们没用到新改动的类。
如何快速验证某个模块会不会被拉进重构建?
执行带 --info 或 --scan 的构建命令,观察 Gradle 输出的任务跳过(SKIPPED)或执行(EXECUTED)状态:
./gradlew :app:assembleDebug --info
重点关注这几类日志行:
-
Task ':common-utils:compileKotlin' is not up-to-date because:→ 公共模块自身确实被重编译; -
Task ':feature-login:compileJava' is not up-to-date because input file has changed:→ 该模块因依赖变更被强制重编译; -
Task ':feature-home:compileJava' is UP-TO-DATE→ 即使它依赖common-utils,只要没用到被修改的类/签名,就不会重编译。
常见导致“不该重编”的模块也被重建的原因
这不是 Gradle 判断错了,而是项目配置放大了影响范围:
- 在
common-utils的build.gradle中用了api声明了本该是内部的依赖(比如把guava通过api暴露出去),导致所有依赖它的模块都把guava当作编译期 API,一旦common-utils版本号变,下游模块的 classpath 就算“不一致”,被迫重编译; - 公共模块里修改了
public类的字段名、方法签名、或const值 —— 这些会直接写入调用方的字节码,必须重编译; - 子模块用了
compileOnly或annotationProcessor引入公共模块,但没配annotationProcessorClasspath隔离,导致注解处理器路径变化,触发全量重处理; - 启用了
configureOnDemand = true(已废弃)或错误配置了dependencyLocking,让 Gradle 无法准确追踪依赖图。
最易被忽略的一点:Gradle 不分析 Java/Kotlin 源码语义,它只看文件时间戳和任务输入输出声明。所以即使你只改了一个 private 方法,只要该模块的 classes 目录被标记为“已变更”,所有直接依赖它的模块就可能被拉进来——除非你用 implementation + 正确的 sourceSets 划分,把实现细节彻底隔离开。











