任务分为两种类型:可操作任务和生命周期任务。
Gradle 中的可操作任务是执行实际工作的任务,例如编译代码。生命周期任务是不执行实际工作的任务。这些任务没有自己的操作,相反,它们捆绑可操作任务并充当构建的目标。

组织良好的生命周期任务设置可以增强构建对新用户的可访问性,并简化与 CI 的集成。
生命周期任务
生命周期任务对于区分用户或机器(CI 与本地)之间的工作特别有用。例如,本地机器上的开发人员可能不希望在每次更改时都运行整个构建。
让我们以一个应用了 base
插件的标准 app
为例。
Gradle base 插件定义了几个生命周期任务,包括 build 、assemble 和 check 。 |
我们通过向 app
构建脚本添加以下几行来将 build
、check
任务和 run
任务分组
tasks.build {
group = myBuildGroup
}
tasks.check {
group = myBuildGroup
description = "Runs checks (including tests)."
}
tasks.named("run") {
group = myBuildGroup
}
tasks.build {
group = myBuildGroup
}
tasks.check {
group = myBuildGroup
description = "Runs checks (including tests)."
}
tasks.named('run') {
group = myBuildGroup
}
如果我们现在查看 app:tasks
列表,我们可以看到这三个任务都可用
$ ./gradlew :app:tasks
> Task :app:tasks
------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------
My app build tasks
------------------
build - Assembles and tests this project.
check - Runs checks (including tests).
run - Runs this project as a JVM application
tasksAll - Show additional tasks.
如果标准生命周期任务足够,这已经很有用了。移动组有助于澄清您希望在构建中使用的任务。
在许多情况下,您需要解决更具体的要求。一个常见的场景是在不运行测试的情况下运行质量检查。目前,:check
任务运行测试和代码质量检查。相反,我们希望一直运行代码质量检查,但不运行耗时的测试。
为了添加一个质量检查生命周期任务,我们引入了一个名为 qualityCheck
的额外生命周期任务和一个名为 spotbugs
的插件。
要添加生命周期任务,请使用 tasks.register()
。您只需要提供一个名称。将此任务放入我们的组中,并使用 dependsOn()
方法连接属于此新生命周期任务的可操作任务
plugins {
id("com.github.spotbugs") version "6.0.7" // spotbugs plugin
}
tasks.register("qualityCheck") { // qualityCheck task
group = myBuildGroup // group
description = "Runs checks (excluding tests)." // description
dependsOn(tasks.classes, tasks.spotbugsMain) // dependencies
dependsOn(tasks.testClasses, tasks.spotbugsTest) // dependencies
}
plugins {
id 'com.github.spotbugs' version '6.0.7' // spotbugs plugin
}
tasks.register('qualityCheck') { // qualityCheck task
group = myBuildGroup // group
description = 'Runs checks (excluding tests).' // description
dependsOn tasks.classes, tasks.spotbugsMain // dependencies
dependsOn tasks.testClasses, tasks.spotbugsTest // dependencies
}
请注意,您不需要列出 Gradle 将执行的所有任务。只需在此处指定您想要收集的目标。Gradle 将确定它需要调用哪些其他任务才能达到这些目标。
在示例中,我们添加了 classes
任务(一个编译所有生产代码的生命周期任务)和 spotbugsMain
任务(检查我们的生产代码)。
我们还添加了一个描述,该描述将显示在任务列表中,有助于更好地区分这两个检查任务。
现在,如果运行 './gradlew :app:tasks',我们可以看到我们的新 qualityCheck
生命周期任务可用
$ ./gradlew :app:tasks
> Task :app:tasks
------------------------------------------------------------
Tasks runnable from project ':app'
------------------------------------------------------------
My app build tasks
------------------
build - Assembles and tests this project.
check - Runs checks (including tests).
qualityCheck - Runs checks (excluding tests).
run - Runs this project as a JVM application
tasksAll - Show additional tasks.
如果我们运行它,我们可以看到它运行 checkstyle 但不运行测试
$ ./gradlew :app:qualityCheck
> Task :buildSrc:checkKotlinGradlePluginConfigurationErrors
> Task :buildSrc:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :buildSrc:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :buildSrc:compilePluginsBlocks UP-TO-DATE
> Task :buildSrc:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :buildSrc:generateScriptPluginAdapters UP-TO-DATE
> Task :buildSrc:compileKotlin UP-TO-DATE
> Task :buildSrc:compileJava NO-SOURCE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:pluginDescriptors UP-TO-DATE
> Task :buildSrc:processResources UP-TO-DATE
> Task :buildSrc:classes UP-TO-DATE
> Task :buildSrc:jar UP-TO-DATE
> Task :app:processResources NO-SOURCE
> Task :app:processTestResources NO-SOURCE
> Task :list:compileJava UP-TO-DATE
> Task :utilities:compileJava UP-TO-DATE
> Task :app:compileJava
> Task :app:classes
> Task :app:compileTestJava
> Task :app:testClasses
> Task :app:spotbugsTest
> Task :app:spotbugsMain
> Task :app:qualityCheck
BUILD SUCCESSFUL in 1s
16 actionable tasks: 5 executed, 11 up-to-date
到目前为止,我们已经查看了单个子项目中的任务,这在您在单个子项目中处理代码时对本地开发很有用。
通过此设置,开发人员只需要知道他们可以使用 :subproject-name:tasks
调用 Gradle 来查看哪些任务可用且对他们有用。
全局生命周期任务
调用生命周期任务的另一个地方是根构建中;这对于持续集成 (CI) 尤其有用。
Gradle 任务在 CI 或 CD 系统中扮演着至关重要的角色,在这些系统中,编译所有代码、运行测试或构建和打包完整应用程序等活动是典型的。为了方便这一点,您可以包含跨多个子项目的生命周期任务。
Gradle 已经存在很长时间了,您会经常在根目录中观察到用于各种目的的构建文件。在较旧的 Gradle 版本中,许多任务是在根 Gradle 构建文件中定义的,导致各种问题。因此,在确定此文件的内容时请谨慎。 |
少数应放置在根构建文件中的元素之一是全局生命周期任务。
让我们继续以 Gradle init
Java 应用程序多项目为例。
这次,我们在根项目中包含一个构建脚本。我们将为我们的全局生命周期任务建立两个组:一个用于与本地开发相关的任务,例如运行所有检查,另一个专门用于我们的 CI 系统。
我们再次将列出的任务缩小到我们的特定组
val globalBuildGroup = "My global build"
val ciBuildGroup = "My CI build"
tasks.named<TaskReportTask>("tasks") {
displayGroups = listOf<String>(globalBuildGroup, ciBuildGroup)
}
def globalBuildGroup = "My global build"
def ciBuildGroup = "My CI build"
tasks.named(TaskReportTask, "tasks") {
displayGroups = [globalBuildGroup, ciBuildGroup]
}
如果您愿意,可以通过更新 displayGroups
来隐藏 CI 任务。
目前,根项目不暴露任何任务
$ ./gradlew :tasks
> Task :tasks
------------------------------------------------------------
Tasks runnable from root project 'gradle-project'
------------------------------------------------------------
No tasks
在此文件中,我们不应用插件! |
让我们添加一个 qualityCheckApp
任务来执行 app
子项目中的所有代码质量检查。类似地,出于 CI 目的,我们实现了一个运行所有测试的 checkAll
任务
tasks.register("qualityCheckApp") {
group = globalBuildGroup
description = "Runs checks on app (globally)"
dependsOn(":app:qualityCheck" )
}
tasks.register("checkAll") {
group = ciBuildGroup
description = "Runs checks for all projects (CI)"
dependsOn(subprojects.map { ":${it.name}:check" })
dependsOn(gradle.includedBuilds.map { it.task(":checkAll") })
}
tasks.register("qualityCheckApp") {
group = globalBuildGroup
description = "Runs checks on app (globally)"
dependsOn(":app:qualityCheck")
}
tasks.register("checkAll") {
group = ciBuildGroup
description = "Runs checks for all projects (CI)"
dependsOn subprojects.collect { ":${it.name}:check" }
dependsOn gradle.includedBuilds.collect { it.task(":checkAll") }
}
所以我们现在可以要求 Gradle 向我们显示根项目的任务,默认情况下,它只会显示 qualityCheckAll
任务(以及可选的 checkAll
任务,具体取决于 displayGroups
的值)。
用户应该清楚需要在本地运行什么
$ ./gradlew :tasks
> Task :tasks
------------------------------------------------------------
Tasks runnable from root project 'gradle-project'
------------------------------------------------------------
My CI build tasks
-----------------
checkAll - Runs checks for all projects (CI)
My global build tasks
---------------------
qualityCheckApp - Runs checks on app (globally)
如果我们运行 :checkAll
任务,我们会看到它编译所有代码并运行代码质量检查(包括 spotbug
)
$ ./gradlew :checkAll
> Task :buildSrc:checkKotlinGradlePluginConfigurationErrors
> Task :buildSrc:generateExternalPluginSpecBuilders UP-TO-DATE
> Task :buildSrc:extractPrecompiledScriptPluginPlugins UP-TO-DATE
> Task :buildSrc:compilePluginsBlocks UP-TO-DATE
> Task :buildSrc:generatePrecompiledScriptPluginAccessors UP-TO-DATE
> Task :buildSrc:generateScriptPluginAdapters UP-TO-DATE
> Task :buildSrc:compileKotlin UP-TO-DATE
> Task :buildSrc:compileJava NO-SOURCE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:pluginDescriptors UP-TO-DATE
> Task :buildSrc:processResources UP-TO-DATE
> Task :buildSrc:classes UP-TO-DATE
> Task :buildSrc:jar UP-TO-DATE
> Task :utilities:processResources NO-SOURCE
> Task :app:processResources NO-SOURCE
> Task :utilities:processTestResources NO-SOURCE
> Task :app:processTestResources NO-SOURCE
> Task :list:compileJava
> Task :list:processResources NO-SOURCE
> Task :list:classes
> Task :list:jar
> Task :utilities:compileJava
> Task :utilities:classes
> Task :utilities:jar
> Task :utilities:compileTestJava NO-SOURCE
> Task :utilities:testClasses UP-TO-DATE
> Task :utilities:test NO-SOURCE
> Task :utilities:check UP-TO-DATE
> Task :list:compileTestJava
> Task :list:processTestResources NO-SOURCE
> Task :list:testClasses
> Task :app:compileJava
> Task :app:classes
> Task :app:compileTestJava
> Task :app:testClasses
> Task :list:test
> Task :list:check
> Task :app:test
> Task :app:spotbugsTest
> Task :app:spotbugsMain
> Task :app:check
> Task :checkAll
BUILD SUCCESSFUL in 1s
21 actionable tasks: 12 executed, 9 up-to-date