Gradle升级避坑实战资料 - 第2节
Gradle 版本演进与重要里程碑
讲升级避坑之前,咱得先摸清楚 Gradle 这些年都干了啥。我入行那会儿还在用 Gradle 1.x,那时候国内 Android 开发刚转 Gradle 不久,各种脚本写出来跟天书似的。后来版本一个接一个往外蹦,每个版本都带来新惊喜(和新坑)。
说白了,Gradle 的演进史就是一部「从慢到快、从纯 Groovy 到多语言、从单模块到大规模」的血泪史。你想想看,如果你从 Gradle 3.x 直接跳到 8.x,中间那些断崖式变化不提前了解,升级完大概率编译就炸了。
所以我专门把这部分拎出来当一章,带你过一遍关键里程碑。不会每个小版本都讲,只挑那些「你不注意就要翻车」的节点。
Gradle 1.x – 开天辟地
2012 年发布,基于 Groovy 的 DSL,主要解决 Maven 和 Ant 的痛点。说实话,那时候功能很简陋,连多模块构建都费劲。我当时在一个遗留项目里试过 1.6,配置里全是坑,比如 startParameter 和现在的完全不一样。
- 里程碑:引入构建可编程能力(Task、Plugin)
- 避坑:别想了,没人用 1.x 升级,直接跳到 2.0+
Gradle 2.x – 性能觉醒
2014 年发布,重点优化了增量编译和并行任务执行。我记得当时升级到 2.1 后,编译时间从 3 分钟降到 40 秒,吓得我反复检查是不是配置写错了。
- 引入
--parallel标志和守护进程(长期驻留 JVM) - 废弃了一些旧 API,比如
org.gradle.api.internal下的类
--warning-mode all 检查废弃警告。
Gradle 3.x – 构建缓存(划重点)
2016 年发布,核心亮点是构建缓存。为什么说它重要?因为你本地 build 变化后,编译器可以复用之前成功的 task 输出,尤其对 CI/CD 提升巨大。
// 启用本地构建缓存(gradle.properties)
org.gradle.caching=true
但这里有个坑:早期版本的缓存键计算很粗糙,容易命中错误结果。我有个朋友(别问是谁)就因为缓存命中错误,把 release 包签名信息弄混了,线上 Crash 炸了一周才找到原因。
- 里程碑:Task 输入输出注解规范化(@Input/@Output)
- 新增
buildCache块支持远程缓存(HTTP/S3)
Gradle 4.x – 多模块与 Java 9
2017 年发布,主要服务大型多模块项目。新增复合构建(Composite Builds)和Java 模块系统支持。
我个人最喜欢的是 --build-file 和 --settings-file 可以同时加载多个项目。做微服务拆分的时候特别爽。
include ':module-a' 改成 includeBuild('../library') 来引入外部库,比传统 jar 依赖灵活多了。
Gradle 5.x – 拥抱 Kotlin DSL
2018 年发布,正式支持Kotlin DSL 作为一等公民。不过说实话,当时 Kotlin DSL 的 IDE 提示还很弱,很多人尝鲜后又被 Groovy DSL 劝退。
// build.gradle.kts 示例
plugins {
id("com.android.application") version "8.0.0"
}
android {
compileSdk = 33
}
我想想——你是不是也遇到过 val 和 var 在闭包里报错的诡异问题?那是因为 Kotlin DSL 的 lambda 接收器类型和 Groovy 完全两码事。要是你用 5.x 版本,尽量先在 buildSrc 里用纯 Kotlin 写逻辑,主构建脚本缓缓再切。
Gradle 6.x – 配置缓存(终于出来了)
2019 年发布,配置缓存(Configuration Cache)正式 GA。它的目标:让「配置阶段」的结果也能缓存,大幅减少大型项目的配置时间。
// 在 gradle.properties 中开启
org.gradle.configuration-cache=true
- 注意:很多插件(比如老版 ButterKnife、Dagger 编译器)会在配置阶段读取文件或系统属性,配置缓存会标记为不稳定,然后降级回退。
- 我踩过的坑:用了某个 Room 代码生成插件,开启配置缓存后,每次改实体类都要 clean 后才生成 DAO 代码。后来发现是插件没有正确声明输出文件。
Gradle 7.x – 性能大跃进
2020 年发布:文件系统监控(File System Watching)、并行下载依赖、Kotlin DSL 1.0。AGP(Android Gradle Plugin)也要求最低 Gradle 7.0。
我自己最直观的感受:以前打开 Android Studio 后第一次 build 要等得泡茶,7.0 之后因为文件系统监控,热启动基本秒开。
@OutputFiles 和 @InputFiles 是否合理。Gradle 7 对校验更严格,哪怕漏掉一个输入声明,可能就会导致 up-to-date 判断出错。
Gradle 8.x – Kotlin DSL 默认,配置缓存稳定
2022 年底发布:Kotlin DSL 成为默认构建脚本语言,配置缓存默认开启(可手动关闭),清理了大量废弃 API。也就是说,如果你现在新建一个项目,build.gradle.kts 是标配了。
- 新增
gradle check可以自动检测不安全的配置 - 移除了对 Java 8 之前的支持,最低 Java 17
但注意:很多企业还在用 Java 11,升级 8.x 后可能需要同时升级 JDK 版本。
版本演进对照表
下面这个表是我这些年攒下来的「升级对照清单」。每次接老旧项目升级,我都会先对着它划一遍风险项。
| Gradle 版本 | 核心里程碑 | 踩坑高频点 |
|---|---|---|
| 1.x – 2.x | 增量编译、守护进程 | 内部 API 大幅变动 |
| 3.x | 构建缓存 | 缓存键碰撞,需要显式声明 @Input |
| 4.x | 复合构建,多项目 | settings.gradle 语法变更 |
| 5.x | Kotlin DSL 试验性支持 | 闭包接收器不兼容 Groovy |
| 6.x | 配置缓存(GA) | 插件未适配导致降级 |
| 7.x | 文件监控,性能提升 | Task 校验更严格 |
| 8.x | Kotlin DSL 默认,配置缓存默认开启 | 最低 Java 17,废弃 API 多 |
看到这你可能会问:「这么多版本,我怎么知道我项目该停在哪个版本?」我的建议是:能上 7.x 就别用 6.x,能上 8.x 就别纠结。但前提是检查所有依赖的插件是否已经兼容新版 Gradle API。
gradle build --warning-mode=fail,如果没有任何废弃警告,那基本稳了。如果出现一堆 deprecation warning,可以先降回 7.6 等新版插件发布。
本章小结
Gradle 版本演进的每个关键节点都不是拍脑袋想出来的。从 1.x 到 8.x,它其实一直在回答两个问题:
- 如何让构建更快? → 增量编译、缓存、守护进程、配置缓存
- 如何让构建更清晰? → Kotlin DSL、复合构建、废弃 API 清理
下几章我们会一个个核心特性深挖,到时候你会发现:这些「里程碑」背后映射的,其实就是你每天写 build.gradle 时碰到的那些痛苦。