如果输出文件比输入文件新,如何定义自定义gradle任务跳过依赖关系

时间:2018-07-02 15:52:58

标签: gradle

我有一个具有以下结构的gradle项目:

我有一系列任务(我们称它们为taskA,taskB,taskC),它们接收一个输入文件(我们称其为source.tar.gz)并生成一个输出文件(我们将其称为dist.tar.gz) 。假设taskA / taskB / taskC需要运行进程等。

我还有一个任务(称为taskZ),可确保在taskA,taskB,taskC之后进行清理。假设它将停止由第一组任务启动的进程。

我有一个名为“ make”的自定义任务,该任务取决于构建及其完成。像这样:

task make {
    dependsOn taskA, taskB, taskC
    finalizedBy taskZ
}

最后,gradle内置的“汇编”任务取决于我自定义的“制造”任务。

我想让gradle知道make的输入是“ source.tar.gz”文件,输出是“ dist.tar.gz”,因此如果“ dist.tar.gz”不需要运行“ make”比“ source.tar.gz”要新。

我尝试声明“ make”输入和输出,如下所示:

task make {
    dependsOn taskA, taskB, taskC
   finalizedBy taskZ

   inputs.file("$projectDir/src/main/source.tar.gz")
   outputs.file("$buildDir/dist.tar.gz")
}

但是gradle仍然每次都在运行整个过程。

有什么办法可以告诉gradle跳过“ make”任务及其依赖项吗?

2 个答案:

答案 0 :(得分:1)

Gradle的增量构建不仅仅基于时间戳(这些天甚至可能不考虑时间戳),因此它对您尝试执行的操作没有帮助。最重要的是,我敢肯定,即使以这种方式配置了make,任务A-> C也将始终运行。 make必须首先确保其依赖项已运行或已经更新。

鉴于此,我认为您可能需要在onlyIf()检查中使用专用的时间戳检查。像这样:

make.onlyIf { inputFile.lastModified() > outputFile.lastModified() }

其中inputFileoutputFile是相关文件的路径(例如,使用project.file())。我认为这不是绝对可靠,但对于您的用例来说可能就足够了。

或者,如果可以使用适当定义的输入和输出配置这样的任务,则创建一个一起执行B和C的自定义任务。根据提供的信息,我认为这是更好的解决方案。

答案 1 :(得分:0)

我按照@ lu.koerfer的建议解决了我的问题。我将任务taskA,taskB,taskC,make,taskZ设置为具有相同的输入和输出。我还标记了taskB,taskC,taskZ仅在taskA不是UP-TO-DATE时运行。

通过这种配置,仅当gradle使用其自身的机制执行taskA时taskA才会运行,并且只有在gradle未将taskA标记为UP-TO-DATE时,其余的任务才会运行。

task taskA {
    ...
}

task taskB {
    ...
    onlyIf { !taskA.state.upToDate }
}

task taskC {
    ...
    onlyIf { !taskA.state.upToDate }
}

task taskZ {
    ...
    onlyIf { !taskA.state.upToDate }
}

task make {
    dependsOn taskA, taskB, taskC
    finalizedBy taskZ
    ...
}

[taskA, taskB, taskC, taskZ, make].each { t ->
   t.inputs.file("$projectDir/src/main/source.tar.gz")
   t.outputs.file("$buildDir/dist.tar.gz")
}

这按预期工作。有时,最新的gradle机制可能无法正常工作。如果您需要强制运行所有任务,只需运行:

./gradlew make --rerun-tasks