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

author gradle 6

然后,对于设置文件中包含的每个项目,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()

使用给定名称创建任务并将其添加到此项目。

构建脚本结构

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

简单来说,plugins{ } 块是一种方法调用,其中 Kotlin lambda 对象或 Groovy 闭包 对象作为参数传递。这是以下内容的简写

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

块映射到 Gradle API 方法。

函数内的代码针对一个称为 接收器(在 Kotlin lambda 中)或 委托(在 Groovy 闭包中)的 this 对象执行。Gradle 确定正确的 this 对象并调用正确的相应方法。方法调用 id("plugin") 对象的 thisPluginDependenciesSpec 类型的。

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

我们来看一个示例并对其进行分解

build.gradle.kts
plugins {                                                               (1)
    id("org.jetbrains.kotlin.jvm") version "1.9.0"
    id("application")
}

repositories {                                                          (2)
    mavenCentral()
}

dependencies {                                                          (3)
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
    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()
}
1 将插件应用到构建中。
2 定义可以找到依赖项的位置。
3 添加依赖项。
4 设置属性。
5 注册并配置任务。
build.gradle
plugins {                                                               (1)
    id 'org.jetbrains.kotlin.jvm' version '1.9.0'
    id 'application'
}

repositories {                                                          (2)
    mavenCentral()
}

dependencies {                                                          (3)
    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'
    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') {                                                   (5)
    useJUnitPlatform()
}
1 将插件应用到构建中。
2 定义可以找到依赖项的位置。
3 添加依赖项。
4 设置属性。
5 注册并配置任务。

1. 将插件应用到构建中

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

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

首选插件块

plugins {
    id("org.jetbrains.kotlin.jvm") version "1.9.0"
    id("application")
}

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

Kotlin gradle 插件版本 1.9.0 也已应用。此插件不包含在 Gradle 中,因此必须使用 plugin idplugin version 进行描述,以便 Gradle 可以找到并应用它。

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

一个项目通常需要一些依赖项才能完成其工作。依赖项包括插件、库或组件,Gradle 必须下载这些插件、库或组件才能成功构建。

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

repositories {
    mavenCentral()
    google()
}

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

3. 添加依赖项

一个项目通常需要一些依赖项才能完成其工作。这些依赖项通常是预编译类库,在项目的源代码中导入。

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

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

dependencies {
    implementation("com.google.guava:guava:32.1.1-jre")
}

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

4. 设置属性

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

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

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

application {
    mainClass = "com.example.Main"
}

5. 注册和配置任务

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

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

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

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

tasks.register<Zip>("zip-reports") {
    from 'Reports/'
    include '*'
    archiveName 'Reports.zip'
    destinationDir(file('/dir'))
}

你可能见过 TaskContainer.create(java.lang.String) 方法的用法,但应避免使用

tasks.create<Zip>("zip-reports") {
    from 'Reports/'
    include '*'
    archiveName 'Reports.zip'
    destinationDir(file('/dir'))
}
register() 允许 避免任务配置,优于 create()

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

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

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

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

构建脚本

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

println(project.layout.projectDirectory);

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

version = '1.0.0.GA'

脚本块是将闭包/lambda 作为参数的方法调用

configurations {
}

闭包/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

声明变量

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

局部变量

使用 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 { "[email protected]" }

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 = "[email protected]"
}

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
[email protected]
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("configure") {
    val user = UserInfo().apply {
        name = "Isaac Newton"
        email = "[email protected]"
    }
    doLast {
        println(user.name)
        println(user.email)
    }
}
build.gradle
class UserInfo {
    String name
    String email
}

tasks.register('configure') {
    def user = configure(new UserInfo()) {
        name = "Isaac Newton"
        email = "[email protected]"
    }
    doLast {
        println user.name
        println user.email
    }
}
$ gradle -q greet
Isaac Newton
[email protected]

闭包委托

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

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

默认导入

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

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

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

Gradle 默认导入
import org.gradle.*
import org.gradle.api.*
import org.gradle.api.artifacts.*
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.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.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.buildinit.*
import org.gradle.buildinit.plugins.*
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.*

下一步: 了解如何使用任务 >>