Gradle 如果输出文件比输入文件新,如何定义跳过依赖项的自定义渐变任务

Gradle 如果输出文件比输入文件新,如何定义跳过依赖项的自定义渐变任务,gradle,Gradle,我有一个gradle项目,其结构如下: 我有一系列任务,我们称它们为taskA,taskB,taskC,它们接受一个输入文件,我们称之为source.tar.gz,并生成一个输出文件,我们称之为dist.tar.gz。假设taskA/taskB/taskC需要运行进程等 我还有一个名为taskZ的任务,它确保在taskA、taskB、taskC之后进行清理。假设它将停止由第一组任务启动的进程 我有一个名为“make”的自定义任务,它取决于构建及其最终版本。大概是这样的: task make {

我有一个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
}
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的输入是'source.tar.gz'文件,输出是'dist.tar.gz',所以如果'dist.tar.gz'比'source.tar.gz'新,就不需要运行'make'

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

task make {
    dependsOn taskA, taskB, taskC
    finalizedBy taskZ
}
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”任务及其依赖项吗?

gradle的增量构建不完全基于时间戳时间戳现在甚至可能不会被考虑,因此它对您尝试的操作没有帮助。最重要的是,我非常确定任务A->C将始终运行,即使以这种方式配置。make必须首先确保其依赖项已运行或已更新

鉴于此,我认为您可能需要在onlyIf检查中使用专用的时间戳检查。比如:

make.onlyIf { inputFile.lastModified() > outputFile.lastModified() }
其中,inputFile和outputFile是指向相关文件的路径,例如使用project.file。我不认为这是非常可靠的,但它可能足以满足您的用例


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

我根据@lu.koerfer的建议解决了我的问题。我将taskA、taskB、taskC、make和taskZ设置为具有相同的输入和输出。我还将taskB、taskC和taskZ标记为仅在taskA不是最新的情况下运行

在这种配置下,只有当gradle使用自己的机制执行taskA时,taskA才会运行,只有当gradle没有将taskA标记为最新时,其余的任务才会运行

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")
}
这正如预期的那样有效。有时,升级到最新的机制可能不起作用。如果需要强制运行所有任务,只需运行:

./gradlew make --rerun-tasks

如果taskA、taskB和taskC是最新的,则make将是最新的。所以问题是:在这种情况下,为什么这些都不是最新的?假设taskA扩展了tar文件,taskB启动了一个服务器进程,taskC调用服务器进程执行一个操作,taskZ终止了服务器进程。在这种情况下,taskA可能是最新的,但启动进程和终止进程将始终运行。这就是为什么我尝试使用一个单独的任务调用所有这些任务。这会导致与中类似的问题,并且需要一个当前在.@lu.koerfer下讨论的功能,谢谢。你的建议帮助我解决了这个问题。实际上,我并不太在乎时间戳。我同意默认的方法。我想要避免的是触发make任务所依赖的任务。我不能在没有大量工作的情况下合并它们——基本上是自己重新编程。