我有一个具有以下结构的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”任务及其依赖项吗?
答案 0 :(得分:1)
Gradle的增量构建不仅仅基于时间戳(这些天甚至可能不考虑时间戳),因此它对您尝试执行的操作没有帮助。最重要的是,我敢肯定,即使以这种方式配置了make
,任务A-> C也将始终运行。 make
必须首先确保其依赖项已运行或已经更新。
鉴于此,我认为您可能需要在onlyIf()
检查中使用专用的时间戳检查。像这样:
make.onlyIf { inputFile.lastModified() > outputFile.lastModified() }
其中inputFile
和outputFile
是相关文件的路径(例如,使用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