声明式 Gradle - 2024 年 11 月更新

2024 年 11 月,我们发布了声明式 Gradle 的第二个早期访问预览版 (EAP 2)。了解有关此版本的更多信息,试用示例并分享您的反馈!

目录

简介 #

一年前,我们宣布了一个名为声明式 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 仍处于实验阶段,尚未准备好用于生产环境。我们提供第二个早期访问预览版,以收集更多来自社区的反馈。我们邀请您试用示例和演示应用程序,并分享您的反馈

Declarative Gradle - November 2024 Update

官方 Android 软件类型预览 #

我们与 Android Studio 团队合作,使 Android Gradle Plugin (AGP) 能够将其现有模型(即 Project 扩展)直接作为软件类型公开,以便在 DCL 中使用。新的 AGP 生态系统插件现在公开了 androidAppandroidLibrary 软件类型,您可以使用它们快速定义项目

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 StudioIntelliJ IDEA、声明式 Gradle Eclipse IDE 的实验性功能,或者我们的声明式 Gradle Visual Studio Code 扩展。您可以在 declarative.gradle.org 网站上找到有关执行所有这些操作的说明。

试用声明式 Gradle

在您试用之后,如果您可以提交您的反馈,我们将不胜感激。这应该只需要几分钟,并且是匿名的,除非您选择提供您的电子邮件地址。

下一步是什么? #

我们的目标是在 2025 年将软件类型和声明式配置语言 (DCL) 孵化为核心 Gradle 功能。在此之前,我们计划在 2025 年初发布另一个 EAP,以解决早期采用者的反馈。现在是分享您的反馈的好时机!请参阅公开的声明式 Gradle 路线图,了解有关目标里程碑的更多信息。

在接下来的几个月中,我们将通过实施多个用例来验证软件类型概念和相关的 API。我们的重点是软件类型的可扩展性和可组合性,以添加新特性。Gradle 插件应该能够扩展现有的软件类型并相互协作。例如,Jacoco Gradle 插件将增强基础 JVM 插件以添加代码覆盖率功能和配置,Compose 插件将增强 Android 插件以添加 Jetpack Compose 功能和配置。

我们的目标是尽快使声明式 Gradle 可在实际项目中使用,以便在仍保持实验性的同时实现高质量的反馈。目前,存在一些主要的缺失功能,阻碍您在实际项目中使用声明式 Gradle,例如能够添加和配置测试。我们正在努力添加此类缺失的功能。同样,我们正在推进对现有 AGP 模型的支持,以确保以声明方式使用它的项目完全正常运行。目标是能够在下一个 EAP 中使用声明式 Gradle 构建可以发布到 Google Play 商店的 Android 应用程序。这包括添加测试支持和扩展 DCL 语言特性。

了解更多 #

讨论