声明式 Gradle - 2024 年 11 月更新
目录
简介 #
一年前,我们宣布了一个名为声明式 Gradle 的新实验性项目。那篇博文介绍了我们对 Gradle 声明式模型的愿景。它还介绍了我们以开发者为中心的软件定义的概念。随后在 2024 年 7 月发布了第一个早期访问预览版,并附带了声明式 Gradle 初探博文。第一个 EAP 引入了一个名为软件类型的配置模型、一种新的声明式配置语言 (DCL),并展示了工具改进和更好的 IDE 支持的潜力。
现在可以更轻松地试用声明式 Gradle。第一个 EAP 基于单独的声明式 Gradle 原型插件。这些原型插件实现了软件类型,封装了现有的插件,如 Android Gradle Plugin (AGP) 和 Kotlin Multiplatform (KMP),从而使其可以从 DCL 使用。从那时起,我们与 Android Studio 团队合作,将 Android Gradle Plugin 的现有模型作为软件类型直接在 DCL 中公开,以在具有精细 DSL 的真实插件上演示声明式 Gradle。我们还尝试了其他 IDE,并增强了 gradle init
以生成使用 DCL 的入门项目。随着这些努力的完成,我们很高兴地宣布第二个 EAP 版本的发布!
这篇博文提供了有关项目进度的更新,并概述了您如何提供反馈并影响我们的后续步骤。
声明式 Gradle 仍处于实验阶段,尚未准备好用于生产环境。我们提供第二个早期访问预览版,以收集更多来自社区的反馈。我们邀请您试用示例和演示应用程序,并分享您的反馈。
官方 Android 软件类型预览 #
我们与 Android Studio 团队合作,使 Android Gradle Plugin (AGP) 能够将其现有模型(即 Project
扩展)直接作为软件类型公开,以便在 DCL 中使用。新的 AGP 生态系统插件现在公开了 androidApp
和 androidLibrary
软件类型,您可以使用它们快速定义项目
build.gradle.dcl
androidApp {
compileSdk = 35
defaultConfig {
minSdk = 29
targetSdk = 35
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
这意味着现有的 AGP 模型可以受益于所有 DCL 特性。构建定义是声明式的,通用配置可以通过声明式设置文件表达,IDE 支持按预期工作,工具可以与构建定义一起工作。
以下示例展示了如何在 DCL 设置文件中声明通用配置
settings.gradle.dcl
// [SNIP] pluginManagement { repositories }
plugins {
id("com.android.ecosystem").version("8.9.0-dev")
}
defaults {
androidLibrary {
compileSdk = 35
}
androidApp {
compileSdk = 35
defaultConfig {
minSdk = 29
targetSdk = 35
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
}
以及子项目如何在它们的 DCL 文件中声明特定配置
lib/build.gradle.dcl
androidLibrary {
namespace = "com.example.lib"
}
app/build.gradle.dcl
androidApp {
namespace = "com.example.app"
}
请注意,这在常规 AGP 版本中不可用。要使用此功能,您需要使用特殊的 AGP nightly 版本。另请注意,AGP 模型的某些部分尚不可用于 DCL 配置。请参阅下文了解如何自行尝试。
新的 DCL 语言特性 #
我们通过两个新特性改进了 DCL 语言:枚举属性和容器。
现在,软件类型可以公开具有枚举值的属性,并在 DCL 文件中简洁地赋值。这项新特性基于 Kotlin 的 KEEP-379 使用预期类型改进解析。枚举值到属性的赋值使用非限定引用。显式不支持限定引用。以下是它的外观
lib/build.gradle.dcl
androidLibrary {
compileOptions {
// Unqualified reference to JavaVersion.VERSION_17 in property assignment
sourceCompatibility = VERSION_17
}
}
同样,现在软件类型可以公开 NamedDomainObjectContainer<T>
嵌套对象,并在 DCL 文件中配置它们的元素。在 DCL 中,只有一种方法可以配置容器的元素,即使用具有“注册或配置”语义的函数。以下是在 Android 构建类型的 AGP 模型上的外观
lib/build.gradle.dcl
androidLibrary {
buildTypes {
buildType("debug") {
isMinifyEnabled = false
}
buildType("release") {
isMinifyEnabled = true
}
}
}
更新的 IDE 支持
Android Studio 团队还为 Android Studio 带来了对这两个特性的支持。语法高亮和代码补全按预期工作,如下面的截屏视频所示
在上面的视频中,您可以看到,由于 DCL 的严格性,IDE 辅助功能没有噪音。代码补全仅建议当前作用域中可用的属性和嵌套块。
JetBrains 的 IntelliJ IDEA 团队也将相同的 DCL 支持集成到他们的 IDE 中。
从 Kotlin DSL 配置软件类型 #
软件类型是以开发者为中心的声明式构建定义的基石,允许作者为 Java 库或 Android 应用程序等常见交付物简化配置。此特性收到了来自社区的大量反馈,作为一项实验,我们希望使其可用于通过 Kotlin DSL 定义的构建脚本。
在这个第二个 EAP 中,我们使从 Gradle 的 Kotlin DSL 配置软件类型成为可能。鉴于 DCL 语言是 Kotlin 语言的严格子集,因此声明软件类型配置的 Kotlin DSL 文件看起来与声明相同配置的 DCL 文件完全相同,这并不令人惊讶
build.gradle.kts
javaApplication {
mainClass = "com.example.Main"
dependencies {
implementation("com.google.guava:guava:31.0-jre")
}
}
build.gradle.dcl
javaApplication {
mainClass = "com.example.Main"
dependencies {
implementation("com.google.guava:guava:31.0-jre")
}
}
使用 Kotlin DSL,您仍然可以在软件类型声明周围添加一些命令式自定义构建逻辑。如果 .gradle.kts
文件纯粹以声明方式配置软件类型,则 Gradle 将使用 DCL 解释器来评估该文件。否则,将使用 Kotlin 编译器,并像往常一样执行编译后的脚本。
要在 Kotlin DSL 脚本中启用软件类型和 DCL 支持,您需要在 gradle.properties
文件中设置 Gradle 属性
gradle.properties
org.gradle.kotlin.dsl.dcl=true
添加此功能对于将来逐步迁移到软件类型和 DCL 至关重要。我们计划在未来为我们的 Groovy DSL 添加相同的功能。
示例 - Now In Android
利用这项新功能,我们重构了我们的 NowInAndroid 示例应用程序构建的分支,以便在其所有项目中使用软件类型。它的一些项目是完全声明式的,并使用来自 DCL 语言的软件类型;其他一些项目仍然需要在声明式部分之上添加一些自定义构建逻辑,则使用来自 Kotlin DSL 构建脚本的软件类型。
以下是一个 Kotlin DSL 脚本的示例,该脚本以声明方式配置 androidLibrary
软件类型,但也以命令方式定义和注册了一个临时的任务
core/datastore-proto/build.gradle.kts
androidLibrary {
namespace = "com.google.samples.apps.nowinandroid.core.datastore.proto"
protobuf {
enabled = true
option = "lite"
}
}
// Define and register a misc one-off task imperatively
abstract class PrintProtobufTasks : DefaultTask() {
@get:Input abstract val protoTasks: Property<String>
@TaskAction
fun printTasks() {
println("Protobuf tasks report:\n${protoTasks.get()}")
}
}
tasks.register("protobufTasks", PrintProtobufTasks::class) {
protoTasks = tasks.filter { task ->
task.name.lowercase().contains("proto")
}.joinToString("\n")
}
您可以更详细地查看 NowInAndroid 存储库中的 core/datastore-proto/build.gradle.kts 文件,了解如何配置 DCL 尚不支持的 Android Gradle Plugins 选项。
展望未来,我们将研究如何使迁移尽可能无缝,如何调整 IDE 支持以使其在此过程中有所帮助,以及如何借助 Kotlin DSL 对软件类型的支持,保留直接在构建文件中快速原型化命令式构建逻辑的灵活性。
对 VS Code 和 Eclipse IDE 的支持 #
在 Android Studio 和 IntelliJ IDEA 中提供 DCL 支持固然很好,但我们希望声明式 Gradle 在所有现代 IDE 中获得一流的支持。因此,我们使用 Language Server Protocol (LSP) 开发了 DCL 的语言服务器 - 一种其他 IDE 和开发者工具可以使用的标准协议。此外,我们还为 Visual Studio Code (VS Code) 和 Eclipse IDE 构建了集成。
如上所示,VS Code 和 Eclipse 集成都支持与 Android Studio 或 IntelliJ IDEA 相同级别的语法高亮、语义错误和代码补全。VS Code 集成还支持我们的构建定义突变框架,我们在 7 月份使用演示客户端应用程序对其进行了演示。可用的突变在 IDE 编辑器中显示为用户可以直接对 DCL 文件执行的操作。
以下是 VS Code 中 DCL 语言支持的截屏视频
以下是 Eclipse IDE 中 DCL 语言支持的截屏视频
生成声明式构建 #
为了让您更轻松地试用声明式 Gradle,您现在可以使用软件类型和 DCL 通过 gradle init
生成您自己的应用程序或库项目。
已向 Gradle 添加了一个实验性系统属性,以添加 gradle init 可以生成的新内容。与本文一起,我们发布了基于我们的原型插件的 Java、Kotlin 和 Android 项目的生成器。
继续阅读以获取有关如何使用它的说明。
立即试用声明式 Gradle #
您可以通过以下方式立即试用以上所有内容:使用 gradle init
生成新的声明式 Gradle 构建、查看示例存储库,并安装特殊版本的 Android Studio 或 IntelliJ IDEA、声明式 Gradle Eclipse IDE 的实验性功能,或者我们的声明式 Gradle Visual Studio Code 扩展。您可以在 declarative.gradle.org 网站上找到有关执行所有这些操作的说明。
在您试用之后,如果您可以提交您的反馈,我们将不胜感激。这应该只需要几分钟,并且是匿名的,除非您选择提供您的电子邮件地址。
下一步是什么? #
我们的目标是在 2025 年将软件类型和声明式配置语言 (DCL) 孵化为核心 Gradle 功能。在此之前,我们计划在 2025 年初发布另一个 EAP,以解决早期采用者的反馈。现在是分享您的反馈的好时机!请参阅公开的声明式 Gradle 路线图,了解有关目标里程碑的更多信息。
在接下来的几个月中,我们将通过实施多个用例来验证软件类型概念和相关的 API。我们的重点是软件类型的可扩展性和可组合性,以添加新特性。Gradle 插件应该能够扩展现有的软件类型并相互协作。例如,Jacoco Gradle 插件将增强基础 JVM 插件以添加代码覆盖率功能和配置,Compose 插件将增强 Android 插件以添加 Jetpack Compose 功能和配置。
我们的目标是尽快使声明式 Gradle 可在实际项目中使用,以便在仍保持实验性的同时实现高质量的反馈。目前,存在一些主要的缺失功能,阻碍您在实际项目中使用声明式 Gradle,例如能够添加和配置测试。我们正在努力添加此类缺失的功能。同样,我们正在推进对现有 AGP 模型的支持,以确保以声明方式使用它的项目完全正常运行。目标是能够在下一个 EAP 中使用声明式 Gradle 构建可以发布到 Google Play 商店的 Android 应用程序。这包括添加测试支持和扩展 DCL 语言特性。
了解更多 #
- 声明式 Gradle 网站
- 声明式 Gradle 介绍和项目宣言
- 声明式 Gradle 初探 (EAP1 版本发布)