Gradle教程系列 —— 增量构建

内置任务(如JavaCompile)声明了输入集合(Java源文件)和输出集合(class文件)。Gradle使用此信息来确定任务是否是最新的并且是否需要执行任何工作。如果没有任何输入或输出发生更改,Gradle可以跳过该任务。总之,我们将这种行为成为Gradle增量构建

为了利用增量构建支持,我们需要向Gradle提供有关任务的输入和输出的信息。也可以将任务配置为只有输出。在执行这个任务之前,Gradle会检查输出,如果输出结果没有改变,则跳过这个任务。在实际的构建过程中,任务通常也有输入 - 包括源文件,资源和属性。Gradle在执行任务之前,会检查任务的输入和输出有没有改变。

通常一个任务的输出是作为另一个任务的输入。获得任务之间的执行顺序是至关重要的。Gradle不依赖于在构建脚本中定义任务的顺序,而是通过dependsOn定义任务的依赖关系,明确告诉Gradle两个任务之间的执行顺序。

声明任务依赖

在这一节,我们看一个简单的例子。在这个项目中,我们需要创建一个zip文件。generator任务创建文件的方式并不重要 - 它生成包含递增数字的文件。

build.gradle

apply plugin: 'base'

task generator() {
    doLast {
        def generatedFileDir = file("$buildDir/generated")
        generatedFileDir.mkdirs()
        for (int i=0; i<10; i++) {
            new File(generatedFileDir, "${i}.txt").text = i
        }
    }
}

task zip(type: Zip) {
    dependsOn generator
    from "$buildDir/generated"
}

这个脚本是可以工作的,但是它还有一些问题。zip任务中重复generator任务的输出目录,并使用dependsOn显式设置zip任务的依赖关系。Gradle似乎每次都执行generator任务,但不执行zip任务。现在是时候指出Gradle的最新检查与其他工具不同,例如Make。即Gradle会比较输入和输出的校验和,而不仅仅是文件的时间戳。虽然每次运行generator任务并覆盖其所有输出文件,但内容不会更改,并且zip任务不需要再次运行。zip任务输入的校验和没有改变。跳过最新任务可让Gradle避免不必要的工作,从而加快构建速度。

声明任务的输入和输出

现在,让我们看一下为什么generator任务每次都会执行。我们可以通过添加--info参数查看原因。

It is not up-to-date because:Task has not declared any outputs.

我们从打印的信息可以看到,Gradle不知道任务产生任何输出。默认情况下,如果一个任务没有任何输出,它会被认为是out-of-date。任务的输出可以使用TaskOutputs声明。任务的输出可以是文件也可以是输出。outputs使用如下所示:

build.gradle

task generator() {
    def generatedFileDir = file("$buildDir/generated")
    outputs.dir generatedFileDir
    doLast {
        generatedFileDir.mkdirs()
        for (int i=0; i<10; i++) {
            new File(generatedFileDir, "${i}.txt").text = i
        }
    }
}

如果我们连续运行两次修改后的任务,我们可以看到,在第二次运行后的信息是:generator任务是up-to-date(最新的)。我们在运行时添加--info参数,可以看到如下信息。

Skipping task ':generator' as it is up-to-date (took 0.001 secs).

当任务的输入和输出都没有改变时,Gradle会跳过这个任务。在大型项目中,可以节省很多的项目构建时间。

总结

增量构建是通过检验输入和输出是否发生更改,确定是否跳过该任务的执行,从而加快构建速度。在编写Gradle脚本时,我们可以善于利用Gradle增量构建的概念,声明任务的输入和输出,进一步提高项目的构建速度。

你可能感兴趣的:(Gradle教程系列 —— 增量构建)