告别无效重建:Gradle 9.6.0 解决 CI 构建缓存失效痛点告别无效重建:Gradle 9.6.0 解决 CI 建筑缓存失效痛点

前言

CI 上经常会给 Gradle 传一些临时参数,比如版本号、渠道号、构建开关。

CI 上经常会授予 Gradle 传输一些临时参数、比如版本号、渠道号、建设开关。

这些参数如果只是 task 执行阶段才用,本来不应该影响配置缓存。但在旧版本里,通过 -Dorg.gradle.project.*ORG_GRADLE_PROJECT_* 传进来的项目属性,只要值变了,就可能让 Configuration Cache 重新计算。

这些参数如果只是任务执行阶段才用的,本不应该影响配置缓存。但在旧版本本里,通过-Dorg.gradle.project。* 或 ORG_GRADLE_PROJECT_* 传统项目属性,只需要更改值,就可以进行配置缓存重新计算。

Gradle 9.6.0最值得看的就是这个配置缓存修正。CI 参数多的 Android 项目,会比单模块本地构建更容易感知到。

Gradle 9.6.0 最有价值的看点就是这个部署缓存修正。CI 参数多的 Android 项目,会比单模块本地结构建更容易感知到。

参数变了,缓存没必要失效

Gradle 的 Configuration Cache 缓的是配置阶段结果。以前有一个比较烦的点:项目属性通过系统属性或环境变量传进来时,只要这些值变化,就可能让配置缓存失效,即使这个属性并没有在配置阶段被读取。

Gradle 的配置缓存的缓慢是配置阶段的结果。以前有一个比较麻烦的点:项目属性通过系统属性或环境变量传入时,只需要这些值的变化,就可以使配置缓存失效,即使这个属性并没有在配置阶段被读取。

先看一个最小例子:

bash 复制代码
tasks.register("printValue") {
    val value = providers.gradleProperty("value").orElse("N/A")



    doLast {


        println("value: ${value.get()}")


    }

}

这里的 value 是在 task 执行阶段读取,不是在配置阶段读取。

这里的值是在任务执行阶段读取,而不是在部署阶段读取。

旧版本里,如果通过 -Dorg.gradle.project.value=1ORG_GRADLE_PROJECT_value=1 传值,下一次改成别的值,Gradle 可能会认为缓存不可复用。

旧版本本里,如果通过-Dog.gradle.project.value=1 或 ORG_GRADLE_PROJECT_value=1 传值,下一次改造别的值,Gradle 可能会认可为缓存,不可复用。

Gradle 9.6.0 会识别这个属性没有参与配置阶段,所以下面这种命令可以继续复用配置缓存:

Gradle 9.6.0 会识别这个属性没有参与配置阶段,所以下面这种命令可以继续续用于配置缓存:

bash 复制代码
./gradlew --configuration-cache printValue -Dorg.gradle.project.value=2

ORG_GRADLE_PROJECT_value=3 ./gradlew --configuration-cache printValue

对 Android 项目来说,典型场景就是 CI 构建号、渠道包参数、是否上传 mapping、是否开启某个发布动作。这些值经常每次构建都不同,但很多时候只在 task action 里用。

如果只是执行阶段读取,Gradle 9.6.0 不会因为值变了就重新算 task graph。

这个优化不会帮项目自动修好所有配置缓存问题。自定义 task 如果在配置阶段读取环境变量,或者插件在配置阶段做了 I/O,缓存还是会失效。9.6.0 修的是"没有被配置阶段读取的项目属性被过度追踪"这个点。

CI 命令别等输入

另一个和 CI 直接相关的改动是 --non-interactive。这个参数会关闭交互式控制台提示,适合没有用户输入的流水线和脚本。

在 CI 里可以这样写:

bash 复制代码
./gradlew --non-interactive --configuration-cache :app:assembleRelease

它解决的不是构建速度,而是自动化环境里的卡住问题。构建命令如果进入等待输入的状态,CI 上通常只会表现成超时,日志里还不一定能第一时间看出原因。

bash 复制代码
NO_COLOR=1 ./gradlew --non-interactive test

NO_COLOR 也适合放在 CI 里。当环境变量 NO_COLOR 非空时,Gradle 会关闭颜色输出。日志被平台采集后,不会混进太多控制字符。

测试报告也补了一个小功能。Test task 生成的 HTML 报告里,表格列头可以点击排序;测试数、失败数、跳过数、耗时这些数字列默认先按降序,成功率默认先按升序。多模块项目里查慢测试和失败类会省一点时间。

root 变量别再偷读

这次有一个会影响老 Gradle 脚本的废弃项:子工程里隐式查找父工程属性和方法开始报警,Gradle 10 会移除这个行为。

Groovy DSL 里很容易写出这种脚本:

bash 复制代码
// root build.gradle


ext.foo = "hello"



// child/build.gradle

println(foo)

child/build.gradle 里没有定义 foo,Gradle 会往父工程找,最后从 root project 的 ext.foo 解析出来。这个行为过去能跑,但项目大了以后很容易留下隐藏依赖。拼错一个名字,也可能刚好命中父工程里的同名属性。

Gradle 9.6.0 开始,隐式引用和 findProperty()property()hasProperty() 这类 API 如果从父工程解析到值,都会给出废弃警告。

共享配置要挪到明确位置。简单值放到 gradle.properties

bash 复制代码
compileSdk=36
minSdk=26

Kotlin DSL 里通过 Provider 读取:

bash 复制代码
val compileSdkVersion = providers.gradleProperty("compileSdk")


    .map(String::toInt)



android {


    compileSdk = compileSdkVersion.get()

}

更复杂的约定配置放到 convention plugin 里。比如 Android library 模块统一配置 compileSdkminSdk、Kotlin 编译参数,不要靠每个子模块从 root project 隐式拿值。

处理完这些警告后,在 settings.gradle.kts 里提前启用 Gradle 10 行为:

bash 复制代码
enableFeaturePreview("NO_IMPLICIT_LOOKUP_IN_PARENT_PROJECTS")

这条对 Android 老项目比较实用。很多项目早年从单模块拆到多模块,root project 的 extsubprojectsallprojects 里堆了不少变量。Gradle 9.6.0 不会马上让构建失败,但它已经把迁移窗口打开了。

升级方式

升级方式还是改 Wrapper:

bash 复制代码
./gradlew :wrapper --gradle-version=9.6.0
./gradlew :wrapper

执行完成后,gradle/wrapper/gradle-wrapper.properties 会指向新的 Gradle 分发包:

bash 复制代码
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip

兼容性上,Gradle 9.6.0 运行 Gradle 本身需要 JVM 17 到 26。内置 Kotlin 是 2.3.21,Kotlin DSL 的语言版本仍是 2.2。Android 侧,Gradle 9.6.0 已测试的 AGP 范围是 9.09.3.0-alpha06

最后

Gradle的版本你们都升级到多少了?

#Android #Gradle #AGP #CI #构建优化

相关推荐
张风捷特烈2 小时前
Flutter 类库大揭秘#01 | path_provider架构与设计
android·flutter
_阿南_11 小时前
Android文件读写和分享总结
android
通玄20 小时前
Jetpack Compose 入门系列(六):Navigation 3 页面导航
android
rocpp1 天前
Android 多语言切换实战:从 Context 到 Android 13 应用语言适配
android·kotlin
释然小师弟1 天前
Android开发十年:反思与回顾
android·后端·嵌入式
黄林晴1 天前
用了这么久 Koin Scope,原来一直都用错了?
android·kotlin
爱勇宝2 天前
我做了一个只用来搜歌词的小 App
android·前端·后端
众少成多积小致巨2 天前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
Coffeeee2 天前
如何使用Glide和Coil加载WebP动图
android·kotlin·glide