Gradle 构建生命周期的初始化阶段使用 settings 文件查找根项目和包含在您的项目根目录中的子项目。

author gradle 6

然后,对于 settings 文件中包含的每个项目,Gradle 创建一个 Project 实例。

然后,Gradle 查找相应的构建脚本文件,该文件在配置阶段使用。

构建脚本

每个 Gradle 构建包含一个或多个项目;一个项目和子项目

项目通常对应于需要构建的软件组件,例如库或应用程序。它可能代表一个库 JAR、一个 Web 应用程序或从其他项目生成的 JAR 组装而成的发行版 ZIP。

另一方面,它可能代表要完成的事情,例如将您的应用程序部署到暂存或生产环境。

Gradle 脚本可以使用 Groovy DSL 或 Kotlin DSL(领域特定语言)编写。

构建脚本配置一个项目,并与 Project 类型的对象关联。

Build

当构建脚本执行时,它会配置 Project

构建脚本可以是 Groovy 中的 *.gradle 文件,也可以是 Kotlin 中的 *.gradle.kts 文件。

构建脚本配置 Project 对象及其子对象。

Project 对象

Project 对象是 Gradle API 的一部分

  • 在 Groovy DSL 中,Project 对象文档可以在这里找到。

  • 在 Kotlin DSL 中,Project 对象文档可以在这里找到。

构建脚本中的许多顶层属性和块都是 Project API 的一部分。

例如,以下构建脚本使用 Project.name 属性打印项目名称

build.gradle.kts
println(name)
println(project.name)
build.gradle
println name
println project.name
$ gradle -q check
project-api
project-api

两个 println 语句都打印相同的属性。

第一个使用对 Project 对象的 name 属性的顶层引用。第二个语句使用任何构建脚本可用的 project 属性,该属性返回关联的 Project 对象。

标准项目属性

Project 对象在您的构建脚本中公开一组标准属性。

下表列出了一些常用属性

名称 类型 描述

name

String

项目目录的名称。

path

String

项目的完全限定名称。

description

String

项目的描述。

dependencies

DependencyHandler

返回项目的依赖处理程序。

repositories

RepositoryHandler

返回项目的仓库处理程序。

layout

ProjectLayout

提供对项目几个重要位置的访问。

group

Object

此项目的组。

version

Object

此项目的版本。

下表列出了一些常用方法

名称 描述

uri()

将文件路径解析为 URI,相对于此项目的项目目录。

task()

使用给定名称创建一个 Task 并将其添加到此项目。

构建脚本结构

构建脚本由 { …​ } 组成,它是 Groovy 和 Kotlin 中的一个特殊对象。此对象在 Kotlin 中称为 lambda,在 Groovy 中称为 closure

简而言之,plugins{ } 块是一个方法调用,其中 Kotlin lambda 对象或 Groovy closure 对象作为参数传递。它是以下形式的简写

plugins(function() {
    id("plugin")
})

块映射到 Gradle API 方法。

函数内部的代码针对一个 this 对象执行,该对象在 Kotlin lambda 中称为 receiver,在 Groovy closure 中称为 delegate。Gradle 确定正确的 this 对象并调用正确的相应方法。方法调用 id("plugin") 对象的 this 类型为 PluginDependenciesSpec

构建脚本本质上由构建在 DSL 之上的 Gradle API 调用组成。Gradle 逐行从上到下执行脚本。

让我们看一个示例并分解它

build.gradle.kts
plugins {   (1)
    id("application")
}

repositories {  (2)
    mavenCentral()
}

dependencies {  (3)
    testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
    implementation("com.google.guava:guava:32.1.1-jre")
}

application {   (4)
    mainClass = "com.example.Main"
}

tasks.named<Test>("test") { (5)
    useJUnitPlatform()
}

tasks.named<Javadoc>("javadoc").configure {
    exclude("app/Internal*.java")
    exclude("app/internal/*")
}

tasks.register<Zip>("zip-reports") {
    from("Reports/")
    include("*")
    archiveFileName.set("Reports.zip")
    destinationDirectory.set(file("/dir"))
}
build.gradle
plugins {   (1)
    id 'application'
}

repositories {  (2)
    mavenCentral()
}

dependencies {  (3)
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    implementation 'com.google.guava:guava:32.1.1-jre'
}

application {   (4)
    mainClass = 'com.example.Main'
}

tasks.named('test', Test) { (5)
    useJUnitPlatform()
}

tasks.named('javadoc', Javadoc).configure {
    exclude 'app/Internal*.java'
    exclude 'app/internal/*'
}

tasks.register('zip-reports', Zip) {
    from 'Reports/'
    include '*'
    archiveFileName = 'Reports.zip'
    destinationDirectory = file('/dir')
}
1 将插件应用于构建。
2 定义可以找到依赖项的位置。
3 添加依赖项。
4 设置属性。
5 注册和配置任务。

1. 将插件应用于构建

插件用于扩展 Gradle。它们也用于模块化和重用项目配置。

可以使用 PluginDependenciesSpec 插件脚本块应用插件。

首选 plugins 块

build.gradle.kts
plugins {   (1)
    id("application")
}
build.gradle
plugins {   (1)
    id 'application'
}

在示例中,已应用 Gradle 自带的 application 插件,将我们的项目描述为 Java 应用程序。

2. 定义可以找到依赖项的位置

一个项目通常有许多完成其工作所需的依赖项。依赖项包括 Gradle 必须下载才能成功构建的插件、库或组件。

构建脚本让 Gradle 知道在哪里查找依赖项的二进制文件。可以提供多个位置

build.gradle.kts
repositories {  (2)
    mavenCentral()
}
build.gradle
repositories {  (2)
    mavenCentral()
}

在示例中,guava 库和 JetBrains Kotlin 插件 (org.jetbrains.kotlin.jvm) 将从 Maven Central Repository 下载。

3. 添加依赖项

一个项目通常有许多完成其工作所需的依赖项。这些依赖项通常是在项目源代码中导入的预编译类库。

依赖项通过配置进行管理,并从仓库中检索。

使用 Project.getDependencies() 方法返回的 DependencyHandler 管理依赖项。使用 Project.getRepositories() 方法返回的 RepositoryHandler 管理仓库。

build.gradle.kts
dependencies {  (3)
    testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
    implementation("com.google.guava:guava:32.1.1-jre")
}
build.gradle
dependencies {  (3)
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    implementation 'com.google.guava:guava:32.1.1-jre'
}

在示例中,应用程序代码使用 Google 的 guava 库。Guava 为集合、缓存、原始类型支持、并发、通用注释、字符串处理、I/O 和验证提供了实用方法。

4. 设置属性

插件可以使用扩展向项目添加属性和方法。

Project 对象有一个关联的 ExtensionContainer 对象,其中包含已应用于项目的所有插件的设置和属性。

在示例中,application 插件添加了一个 application 属性,用于详细说明我们的 Java 应用程序的主类

build.gradle.kts
application {   (4)
    mainClass = "com.example.Main"
}
build.gradle
application {   (4)
    mainClass = 'com.example.Main'
}

5. 注册和配置任务

任务执行一些基本的工作,例如编译类、运行单元测试或压缩 WAR 文件。

虽然任务通常在插件中定义,但您可能需要在构建脚本中注册或配置任务。

注册任务会将任务添加到您的项目。

您可以使用 TaskContainer.register(java.lang.String) 方法在项目中注册任务

build.gradle.kts
tasks.register<Zip>("zip-reports") {
    from("Reports/")
    include("*")
    archiveFileName.set("Reports.zip")
    destinationDirectory.set(file("/dir"))
}
build.gradle
tasks.register('zip-reports', Zip) {
    from 'Reports/'
    include '*'
    archiveFileName = 'Reports.zip'
    destinationDirectory = file('/dir')
}

您可能已经看到 TaskContainer.create(java.lang.String) 方法的使用,应避免使用

tasks.create<Zip>("zip-reports") { }
register() 启用了任务配置避免,优于 create()

您可以使用 TaskCollection.named(java.lang.String) 方法找到要配置的任务

build.gradle.kts
tasks.named<Test>("test") { (5)
    useJUnitPlatform()
}
build.gradle
tasks.named('test', Test) { (5)
    useJUnitPlatform()
}

下面的示例配置 Javadoc 任务以从 Java 代码自动生成 HTML 文档

build.gradle.kts
tasks.named<Javadoc>("javadoc").configure {
    exclude("app/Internal*.java")
    exclude("app/internal/*")
}
build.gradle
tasks.named('javadoc', Javadoc).configure {
    exclude 'app/Internal*.java'
    exclude 'app/internal/*'
}

构建脚本编写

构建脚本由零个或多个语句和脚本块组成

println(project.layout.projectDirectory);

语句可以包括方法调用、属性赋值和局部变量定义

version = '1.0.0.GA'

脚本块是一个方法调用,它将 closure/lambda 作为参数

configurations {
}

closure/lambda 在执行时配置一些委托对象

repositories {
    google()
}

构建脚本也是 Groovy 或 Kotlin 脚本

build.gradle.kts
tasks.register("upper") {
    doLast {
        val someString = "mY_nAmE"
        println("Original: $someString")
        println("Upper case: ${someString.toUpperCase()}")
    }
}
build.gradle
tasks.register('upper') {
    doLast {
        String someString = 'mY_nAmE'
        println "Original: $someString"
        println "Upper case: ${someString.toUpperCase()}"
    }
}
$ gradle -q upper
Original: mY_nAmE
Upper case: MY_NAME

它可以包含 Groovy 或 Kotlin 脚本中允许的元素,例如方法定义和类定义

build.gradle.kts
tasks.register("count") {
    doLast {
        repeat(4) { print("$it ") }
    }
}
build.gradle
tasks.register('count') {
    doLast {
        4.times { print "$it " }
    }
}
$ gradle -q count
0 1 2 3 

灵活的任务注册

使用 Groovy 或 Kotlin 语言的功能,您可以在循环中注册多个任务

build.gradle.kts
repeat(4) { counter ->
    tasks.register("task$counter") {
        doLast {
            println("I'm task number $counter")
        }
    }
}
build.gradle
4.times { counter ->
    tasks.register("task$counter") {
        doLast {
            println "I'm task number $counter"
        }
    }
}
$ gradle -q task1
I'm task number 1

Gradle 类型

在 Gradle 中,类型属性提供器是管理和配置构建逻辑的基础

  • 类型:Gradle 定义类型(如 TaskConfigurationFile 等)来表示构建组件。您可以扩展这些类型以创建自定义任务或域对象。

  • 属性:Gradle 属性(例如,Property<T>ListProperty<T>SetProperty<T>)用于构建配置。它们允许延迟求值,这意味着它们的值仅在需要时才计算,从而提高灵活性和性能。

  • 提供器Provider<T> 表示延迟计算或检索的值。提供器通常与属性一起使用,以将值计算推迟到必要时。这对于将动态运行时值集成到您的构建中尤其有用。

您可以在理解 Gradle 类型中了解更多信息。

声明变量

构建脚本可以声明两个变量:局部变量额外属性

局部变量

使用 val 关键字声明局部变量。局部变量仅在声明它们的作用域中可见。它们是底层 Kotlin 语言的一个特性。

使用 def 关键字声明局部变量。局部变量仅在声明它们的作用域中可见。它们是底层 Groovy 语言的一个特性。

build.gradle.kts
val dest = "dest"

tasks.register<Copy>("copy") {
    from("source")
    into(dest)
}
build.gradle
def dest = 'dest'

tasks.register('copy', Copy) {
    from 'source'
    into dest
}

额外属性

Gradle 的增强对象,包括项目、任务和源集,可以保存用户定义的属性。

通过拥有对象的 extra 属性添加、读取和设置额外属性。或者,您可以使用 by extra 通过 Kotlin 委托属性访问额外属性。

通过拥有对象的 ext 属性添加、读取和设置额外属性。或者,您可以使用 ext 块同时添加多个属性。

build.gradle.kts
plugins {
    id("java-library")
}

val springVersion by extra("3.1.0.RELEASE")
val emailNotification by extra { "build@master.org" }

sourceSets.all { extra["purpose"] = null }

sourceSets {
    main {
        extra["purpose"] = "production"
    }
    test {
        extra["purpose"] = "test"
    }
    create("plugin") {
        extra["purpose"] = "production"
    }
}

tasks.register("printProperties") {
    val springVersion = springVersion
    val emailNotification = emailNotification
    val productionSourceSets = provider {
        sourceSets.matching { it.extra["purpose"] == "production" }.map { it.name }
    }
    doLast {
        println(springVersion)
        println(emailNotification)
        productionSourceSets.get().forEach { println(it) }
    }
}
build.gradle
plugins {
    id 'java-library'
}

ext {
    springVersion = "3.1.0.RELEASE"
    emailNotification = "build@master.org"
}

sourceSets.all { ext.purpose = null }

sourceSets {
    main {
        purpose = "production"
    }
    test {
        purpose = "test"
    }
    plugin {
        purpose = "production"
    }
}

tasks.register('printProperties') {
    def springVersion = springVersion
    def emailNotification = emailNotification
    def productionSourceSets = provider {
        sourceSets.matching { it.purpose == "production" }.collect { it.name }
    }
    doLast {
        println springVersion
        println emailNotification
        productionSourceSets.get().each { println it }
    }
}
$ gradle -q printProperties
3.1.0.RELEASE
build@master.org
main
plugin

此示例通过 by extraproject 对象添加两个额外属性。此外,此示例通过将 extra["purpose"] 设置为 null 向每个源集添加一个名为 purpose 的属性。添加后,您可以通过 extra 读取和设置这些属性。

此示例通过 ext 块向 project 对象添加两个额外属性。此外,此示例通过将 ext.purpose 设置为 null 向每个源集添加一个名为 purpose 的属性。添加后,您可以像预定义属性一样读取和设置所有这些属性。

Gradle 需要特殊的语法来添加属性,以便它可以快速失败。例如,这允许 Gradle 识别脚本何时尝试设置不存在的属性。您可以在可以访问其拥有对象的任何位置访问额外属性。这使额外属性比局部变量具有更广泛的作用域。子项目可以访问其父项目上的额外属性。

有关额外属性的更多信息,请参阅 API 文档中的 ExtraPropertiesExtension

配置任意对象

示例 greet() 任务显示了一个任意对象配置的示例

build.gradle.kts
class UserInfo(
    var name: String? = null,
    var email: String? = null
)

tasks.register("greet") {
    val user = UserInfo().apply {
        name = "Isaac Newton"
        email = "isaac@newton.me"
    }
    doLast {
        println(user.name)
        println(user.email)
    }
}
build.gradle
class UserInfo {
    String name
    String email
}

tasks.register('greet') {
    def user = configure(new UserInfo()) {
        name = "Isaac Newton"
        email = "isaac@newton.me"
    }
    doLast {
        println user.name
        println user.email
    }
}
$ gradle -q greet
Isaac Newton
isaac@newton.me

Closure 委托

每个 closure 都有一个 delegate 对象。Groovy 使用此 delegate 查找对非局部变量和 closure 参数的变量和方法引用。Gradle 将其用于配置 closure,其中 delegate 对象引用正在配置的对象。

build.gradle
dependencies {
    assert delegate == project.dependencies
    testImplementation('junit:junit:4.13')
    delegate.testImplementation('junit:junit:4.13')
}

默认导入

为了使构建脚本更简洁,Gradle 会自动向脚本添加一组导入语句。

因此,您可以编写 throw new StopExecutionException() 而不是 throw new org.gradle.api.tasks.StopExecutionException()

Gradle 隐式地向每个脚本添加以下导入

import org.gradle.*
import org.gradle.api.*
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.capability.*
import org.gradle.api.artifacts.component.*
import org.gradle.api.artifacts.dsl.*
import org.gradle.api.artifacts.ivy.*
import org.gradle.api.artifacts.maven.*
import org.gradle.api.artifacts.query.*
import org.gradle.api.artifacts.repositories.*
import org.gradle.api.artifacts.result.*
import org.gradle.api.artifacts.transform.*
import org.gradle.api.artifacts.type.*
import org.gradle.api.artifacts.verification.*
import org.gradle.api.attributes.*
import org.gradle.api.attributes.java.*
import org.gradle.api.attributes.plugin.*
import org.gradle.api.cache.*
import org.gradle.api.capabilities.*
import org.gradle.api.component.*
import org.gradle.api.configuration.*
import org.gradle.api.credentials.*
import org.gradle.api.distribution.*
import org.gradle.api.distribution.plugins.*
import org.gradle.api.execution.*
import org.gradle.api.file.*
import org.gradle.api.flow.*
import org.gradle.api.initialization.*
import org.gradle.api.initialization.definition.*
import org.gradle.api.initialization.dsl.*
import org.gradle.api.initialization.resolve.*
import org.gradle.api.invocation.*
import org.gradle.api.java.archives.*
import org.gradle.api.jvm.*
import org.gradle.api.launcher.cli.*
import org.gradle.api.logging.*
import org.gradle.api.logging.configuration.*
import org.gradle.api.model.*
import org.gradle.api.plugins.*
import org.gradle.api.plugins.antlr.*
import org.gradle.api.plugins.catalog.*
import org.gradle.api.plugins.jvm.*
import org.gradle.api.plugins.quality.*
import org.gradle.api.plugins.scala.*
import org.gradle.api.problems.*
import org.gradle.api.project.*
import org.gradle.api.provider.*
import org.gradle.api.publish.*
import org.gradle.api.publish.ivy.*
import org.gradle.api.publish.ivy.plugins.*
import org.gradle.api.publish.ivy.tasks.*
import org.gradle.api.publish.maven.*
import org.gradle.api.publish.maven.plugins.*
import org.gradle.api.publish.maven.tasks.*
import org.gradle.api.publish.plugins.*
import org.gradle.api.publish.tasks.*
import org.gradle.api.reflect.*
import org.gradle.api.reporting.*
import org.gradle.api.reporting.components.*
import org.gradle.api.reporting.dependencies.*
import org.gradle.api.reporting.dependents.*
import org.gradle.api.reporting.model.*
import org.gradle.api.reporting.plugins.*
import org.gradle.api.resources.*
import org.gradle.api.services.*
import org.gradle.api.specs.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.ant.*
import org.gradle.api.tasks.application.*
import org.gradle.api.tasks.bundling.*
import org.gradle.api.tasks.compile.*
import org.gradle.api.tasks.diagnostics.*
import org.gradle.api.tasks.diagnostics.artifact.transforms.*
import org.gradle.api.tasks.diagnostics.configurations.*
import org.gradle.api.tasks.incremental.*
import org.gradle.api.tasks.javadoc.*
import org.gradle.api.tasks.options.*
import org.gradle.api.tasks.scala.*
import org.gradle.api.tasks.testing.*
import org.gradle.api.tasks.testing.junit.*
import org.gradle.api.tasks.testing.junitplatform.*
import org.gradle.api.tasks.testing.testng.*
import org.gradle.api.tasks.util.*
import org.gradle.api.tasks.wrapper.*
import org.gradle.api.toolchain.management.*
import org.gradle.authentication.*
import org.gradle.authentication.aws.*
import org.gradle.authentication.http.*
import org.gradle.build.event.*
import org.gradle.buildconfiguration.tasks.*
import org.gradle.buildinit.*
import org.gradle.buildinit.plugins.*
import org.gradle.buildinit.specs.*
import org.gradle.buildinit.tasks.*
import org.gradle.caching.*
import org.gradle.caching.configuration.*
import org.gradle.caching.http.*
import org.gradle.caching.local.*
import org.gradle.concurrent.*
import org.gradle.external.javadoc.*
import org.gradle.ide.visualstudio.*
import org.gradle.ide.visualstudio.plugins.*
import org.gradle.ide.visualstudio.tasks.*
import org.gradle.ide.xcode.*
import org.gradle.ide.xcode.plugins.*
import org.gradle.ide.xcode.tasks.*
import org.gradle.ivy.*
import org.gradle.jvm.*
import org.gradle.jvm.application.scripts.*
import org.gradle.jvm.application.tasks.*
import org.gradle.jvm.tasks.*
import org.gradle.jvm.toolchain.*
import org.gradle.language.*
import org.gradle.language.assembler.*
import org.gradle.language.assembler.plugins.*
import org.gradle.language.assembler.tasks.*
import org.gradle.language.base.*
import org.gradle.language.base.artifact.*
import org.gradle.language.base.compile.*
import org.gradle.language.base.plugins.*
import org.gradle.language.base.sources.*
import org.gradle.language.c.*
import org.gradle.language.c.plugins.*
import org.gradle.language.c.tasks.*
import org.gradle.language.cpp.*
import org.gradle.language.cpp.plugins.*
import org.gradle.language.cpp.tasks.*
import org.gradle.language.java.artifact.*
import org.gradle.language.jvm.tasks.*
import org.gradle.language.nativeplatform.*
import org.gradle.language.nativeplatform.tasks.*
import org.gradle.language.objectivec.*
import org.gradle.language.objectivec.plugins.*
import org.gradle.language.objectivec.tasks.*
import org.gradle.language.objectivecpp.*
import org.gradle.language.objectivecpp.plugins.*
import org.gradle.language.objectivecpp.tasks.*
import org.gradle.language.plugins.*
import org.gradle.language.rc.*
import org.gradle.language.rc.plugins.*
import org.gradle.language.rc.tasks.*
import org.gradle.language.scala.tasks.*
import org.gradle.language.swift.*
import org.gradle.language.swift.plugins.*
import org.gradle.language.swift.tasks.*
import org.gradle.maven.*
import org.gradle.model.*
import org.gradle.nativeplatform.*
import org.gradle.nativeplatform.platform.*
import org.gradle.nativeplatform.plugins.*
import org.gradle.nativeplatform.tasks.*
import org.gradle.nativeplatform.test.*
import org.gradle.nativeplatform.test.cpp.*
import org.gradle.nativeplatform.test.cpp.plugins.*
import org.gradle.nativeplatform.test.cunit.*
import org.gradle.nativeplatform.test.cunit.plugins.*
import org.gradle.nativeplatform.test.cunit.tasks.*
import org.gradle.nativeplatform.test.googletest.*
import org.gradle.nativeplatform.test.googletest.plugins.*
import org.gradle.nativeplatform.test.plugins.*
import org.gradle.nativeplatform.test.tasks.*
import org.gradle.nativeplatform.test.xctest.*
import org.gradle.nativeplatform.test.xctest.plugins.*
import org.gradle.nativeplatform.test.xctest.tasks.*
import org.gradle.nativeplatform.toolchain.*
import org.gradle.nativeplatform.toolchain.plugins.*
import org.gradle.normalization.*
import org.gradle.platform.*
import org.gradle.platform.base.*
import org.gradle.platform.base.binary.*
import org.gradle.platform.base.component.*
import org.gradle.platform.base.plugins.*
import org.gradle.plugin.devel.*
import org.gradle.plugin.devel.plugins.*
import org.gradle.plugin.devel.tasks.*
import org.gradle.plugin.management.*
import org.gradle.plugin.use.*
import org.gradle.plugins.ear.*
import org.gradle.plugins.ear.descriptor.*
import org.gradle.plugins.ide.*
import org.gradle.plugins.ide.api.*
import org.gradle.plugins.ide.eclipse.*
import org.gradle.plugins.ide.idea.*
import org.gradle.plugins.signing.*
import org.gradle.plugins.signing.signatory.*
import org.gradle.plugins.signing.signatory.pgp.*
import org.gradle.plugins.signing.type.*
import org.gradle.plugins.signing.type.pgp.*
import org.gradle.process.*
import org.gradle.swiftpm.*
import org.gradle.swiftpm.plugins.*
import org.gradle.swiftpm.tasks.*
import org.gradle.testing.base.*
import org.gradle.testing.base.plugins.*
import org.gradle.testing.jacoco.plugins.*
import org.gradle.testing.jacoco.tasks.*
import org.gradle.testing.jacoco.tasks.rules.*
import org.gradle.testkit.runner.*
import org.gradle.util.*
import org.gradle.vcs.*
import org.gradle.vcs.git.*
import org.gradle.work.*
import org.gradle.workers.*

下一步: 学习如何使用 Tasks >>