如果该任务是最新的,则跳过 Gradle 任务依赖项

Posted

技术标签:

【中文标题】如果该任务是最新的,则跳过 Gradle 任务依赖项【英文标题】:Skipping Gradle task dependencies if that task is up to date 【发布时间】:2019-09-27 18:53:48 【问题描述】:

我正在尝试将构建迁移到 gradle,但有一个问题让我无法使用构建缓存。我有一组依赖任务用于:

设置嵌入式 mysql 服务器 使用 Flyway 迁移该服务器中的架构 从该架构生成 Jooq 代码 停止嵌入式 MySQL 服务器 用我们的应用程序代码编译生成的代码

整个过程运行良好,但我想了解构建缓存以及它是如何工作的。我的 build.gradle 的相关部分如下所示:

plugins 
    id 'java'
    id 'nu.studer.jooq' version '2.0.11'
    id "org.flywaydb.flyway" version "5.2.4"
    id 'com.github.michaelruocco.embedded-mysql-plugin' version '2.1.10'


embeddedMysql 
    url = 'jdbc:mysql://127.0.0.1:3308/jooqGeneration'
    username = 'user'
    password = 'password'
    version = 'v5_7_latest'

startEmbeddedMysql.inputs.files(project.fileTree(dir: "src", include: "**/*.sql"))
startEmbeddedMysql.outputs.dir('build/generated-src/jooq/')

flyway 
    url = 'jdbc:mysql://127.0.0.1:3308/jooqGeneration'
    user = 'user'
    password = 'password'
    schemas = ['jooqGeneration']

flywayMigrate.dependsOn 'startEmbeddedMysql'
flywayMigrate.outputs.upToDateWhen  !startEmbeddedMysql.didWork 

jooq 
    sample(sourceSets.jooqSchemaGeneration) 
        jdbc 
            driver = 'org.mariadb.jdbc.Driver'
            url = 'jdbc:mysql://127.0.0.1:3308'
            user = 'user'
            password = 'password'
        
        generator 
            name = 'org.jooq.util.DefaultGenerator'
            database 
                name = 'org.jooq.util.mysql.MySQLDatabase'
                includes = '.*'
                excludes = ''
                inputSchema = 'jooqGeneration'
            
        
    

generateSampleJooqSchemaSource.dependsOn 'flywayMigrate'
generateSampleJooqSchemaSource.finalizedBy 'stopEmbeddedMysql'
generateSampleJooqSchemaSource.outputs.upToDateWhen  !flywayMigrate.didWork 

compileJava.dependsOn 'generateSampleJooqSchemaSource'

我的问题是这里的整个构建链是高度耦合的。对于依赖链中的每一步,我都必须管理该步骤是否是最新的。

这一切似乎源于这样一个事实,即即使一个任务是最新的,该任务所依赖的任务仍然在运行。如果我向generateSampleJooqSchemaSource 任务添加一些输入和输出,它将正确确定它是否是最新的,但即使任务是最新的,dependsOn 任务仍然会运行。这意味着当我们运行时,我需要去每个相关的步骤并处理。我通过查看每个相关步骤是否有任何工作解决了这个问题,然后将正在更新的文件添加到我启动嵌入式 MySQL 服务器的第一个任务中。

有没有办法将所有决策转移到最终的generateSampleJooqSchemaSource,这样dependsOn 任务仅在generateSampleJooqSchemaSource 不是最新的情况下运行?

这将允许我将其中一些步骤重新用于其他用途。例如,我可以将嵌入式 MySQL 服务器重新用于一些数据库集成测试,而无需设置另一个单独的任务。

我主要只是想了解 Gradle 构建缓存,以及它如何决定运行这些任务。

【问题讨论】:

最新检查基于每个任务并在任务开始之前执行。所以当一个任务的依赖被执行时,你不知道这个任务以后是否会是最新的。在另一个方向,您可以使用onlyIf 条件来检查之前的任务是否完成了任何工作。 【参考方案1】:

任务关系和排序发生在 Gradle 确定要运行的内容时,此时还没有最新的概念。

计算完任务图后,Gradle 将按适当的顺序执行所有任务,现在检查是否需要为它们做任何事情。

解决您的问题的一种方法是确保使您的 generateSampleJooqSchemaSource 任务保持最新的任何原因也导致其依赖项也是最新的。

或者您可以添加所有这些任务所依赖的任务,然后将输出一些内容供链中后续任务使用作为其最新检查,从而导致它们被跳过。

【讨论】:

以上是关于如果该任务是最新的,则跳过 Gradle 任务依赖项的主要内容,如果未能解决你的问题,请参考以下文章

在 ssis 控制流中选择性地执行任务

如果函数内部的条件失败,则跳过 bash while 循环

Android Gradle 插件自定义 Gradle 任务 ⑤ ( 为自定义 Gradle 任务添加依赖任务 | Gradle 任务依赖执行顺序控制 )

Android Gradle 插件自定义 Gradle 任务 ⑤ ( 为自定义 Gradle 任务添加依赖任务 | Gradle 任务依赖执行顺序控制 )

Gradle任务依赖

ORACLE查询条件为空,则跳过该条件。