gradle - 运行依赖项时如何使Gradle重新运行任务?

标签 gradle

假设我有一个任务“main”,它依赖于另一个任务“dependency”。我希望“main”在其依赖项(或其依赖项的依赖项)被重建的任何时候都可以重新运行,因为“main”依赖于“dependency”(或“dependency”的依赖项)产生的 Artifact 。

包含我正在处理的示例的build.gradle文件如下:

defaultTasks 'main'

task baseDependency {
    outputs.file 'deps.out'
    outputs.upToDateWhen { false }
    doLast {
        exec {
            commandLine 'bash', '-c', 'echo hello world > deps.out'
        }
    }
}

task dependency(dependsOn: baseDependency)

task main(dependsOn: dependency) {
    outputs.file 'main.out'
    doLast {
        exec {
            commandLine 'bash', '-c', 'echo hello world > main.out'
        }
    }
}

第一次执行gradle:
:baseDependency
:dependency
:main

BUILD SUCCESSFUL

Total time: 0.623 secs

再次执行:
:baseDependency
:dependency
:main UP-TO-DATE

BUILD SUCCESSFUL

Total time: 0.709 secs

如果必须重新构建其依赖项,如果“main”是而不是标记为“UP-TO-DATE”,我真的很喜欢。这似乎很重要。您如何确定是这种情况?

最佳答案

在任务之间specify dependency的标准方法是通过任务的输入和输出。这可以是任何文件,文件集或目录。
在您的情况下,您应该修改main任务,并将inputs.file 'deps.out'添加到其定义中。

请注意,在您提供的简单示例中,gradle进行了优化,可能会导致意外行为。

Before a task is executed for the first time, Gradle takes a snapshot of the inputs. This snapshot contains the set of input files and a hash of the contents of each file. Gradle then executes the task. If the task completes successfully, Gradle takes a snapshot of the outputs. This snapshot contains the set of output files and a hash of the contents of each file. Gradle persists both snapshots for the next time the task is executed.

Each time after that, before the task is executed, Gradle takes a new snapshot of the inputs and outputs. If the new snapshots are the same as the previous snapshots, Gradle assumes that the outputs are up to date and skips the task. If they are not the same, Gradle executes the task. Gradle persists both snapshots for the next time the task is executed.



因此,即使您在生成相同文件的简单示例中指定了正确的输入,在第二次及以后的运行中,相关任务也会被标记为最新。

如果您不希望或无法对文件进行硬编码依赖性,则可以根据此任务的dependencies及其state覆盖相关任务的upToDateWhen并计算条件(如果该任务是最新的):
outputs.upToDateWhen { task ->
   task.taskDependencies.inject(true) { r, dep ->
     r && dep.values.inject(true) { res, v ->
        res && (!(v instanceof Task) || v?.state.getSkipped())
     }
   }
}

如果根本不应该运行此任务,则upToDateWhen应该返回true(因为它的输出已经是最新的)。在没有运行任何依赖任务的情况下就是这种情况(gradle文档对此有点含糊,我必须承认,但是getSkipped似乎按预期工作了)。

关于gradle - 运行依赖项时如何使Gradle重新运行任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34277839/

相关文章:

Gradle 6 settings.gradle.kts 属性问题

java - Gradle运行时找不到Java "./gradlew shadowJar"

android - 可以构建自动生成的调试构建变体apk,但不能构建自定义构建变体apk

oracle - gradle jettyrun oracle 找不到合适的驱动程序

java - Activiti + Spring Boot + Gradle 构建挂起,而 gradle clean 测试

android - Gradle依赖项Groovy关闭语法

android - 如何注册与 MP3 的新文件类型关联

java - 使用 gradle 将 jar 包含到集成测试中

Gradle processResources - 文件包含 $ 字符

android - api19上的android.content.res.Resources $ NotFoundException