【问题标题】:Dynamically created task of type Copy is always UP-TO-DATECopy 类型的动态创建的任务始终是 UP-TO-DATE
【发布时间】:2018-11-15 03:56:10
【问题描述】:

我准备了一个非常简单的脚本,它说明了我在使用 Gradle 1.7 时遇到的问题(需要坚持使用它,因为一些插件还不支持新版本)。

我正在尝试动态创建任务,每个任务对应于项目目录中的一个文件。这很好用,但我创建的任务在我分配它们类型“复制”后就永远不会执行。

这是我的问题build.gradle:

file('templates').listFiles().each { File f ->

    // THIS LINE DOES NOT WORK
    task "myDist-${f.name}" (type: Copy) {

    // NEXT LINE WORKS
    //task "myDist-${f.name}" {
        doLast {
            println "MYDIST-" + f.name
        }
    }
}

task distAll(dependsOn: tasks.matching { Task task -> task.name.startsWith("myDist")}) {
    println "MYDISTALL"
}

defaultTasks 'distAll'

这样,当我简单地调用默认任务调用gradle时,我的任务不会被执行:

MYDISTALL
:myDist-template1 UP-TO-DATE
:myDist-template2 UP-TO-DATE
:distAll UP-TO-DATE

BUILD SUCCESSFUL

如果我从我的动态任务中删除类型 Copy(取消注释上面的行),我的任务就会被执行:

MYDISTALL
:myDist-template1
MYDIST-template1
:myDist-template2
MYDIST-template2
:distAll

BUILD SUCCESSFUL

(您需要在build.gradle所在的同一目录中创建一个文件夹名称templates,并在其中放入几个空文件才能运行测试)

根据调试输出:

跳过任务 ':myDist-template1',因为它没有源文件。

跳过任务 ':myDist-template2',因为它没有源文件。

那么我怎样才能指定源文件并让我的Copy 任务执行呢? 我试过添加

from( '/absolute/path/to/existing/file' ) {
    into 'myfolder'
}

对于任务主体,我尝试分配任务的inputs.source file('/my/existing/file'),但没有成功。 您能否就如何修改我的简单脚本留下动态任务创建并保持Copy 类型的动态任务提出建议?

谢谢!

编辑: 好的,这样任务就被调用了:

file('templates').listFiles().each { File f ->
    task "myDist-${f.name}" (type: Copy) {
        from f
        into 'dist'
        doLast {
            println "MYDIST-" + f.name
        }
    }
}

但看起来我必须始终指定from/into。在 doLast{} 正文中这样做是不够的。

【问题讨论】:

    标签: gradle build.gradle


    【解决方案1】:

    Copy 任务只有在它有要复制的内容时才会被执行。告诉它要复制什么是配置任务的一部分,因此需要在配置阶段完成,而不是在执行阶段。这些是非常重要的概念,您可以在Gradle User GuideGradle Forums 上阅读它们。

    doFirstdoLast 块在执行阶段被执行,作为执行任务的一部分。两者都来不及告诉任务要复制什么:doFirst 在主要任务操作(在本例中是复制)之前立即执行,但(不久)在 skippedup-to-date 检查之后(这是基于任务的配置)。 doLast 在主要任务操作之后执行,因此显然为时已晚。

    【讨论】:

    • 我告诉复制任务在配置时它需要复制哪个文件夹(在配置时该文件夹为空)。当任务开始在执行时复制文件夹时,另一个任务已经执行并将我需要的文件复制到源目录中。似乎工作正常。
    【解决方案2】:

    我认为以下Gradle User Guide quote 最能回答我的问题:

    其次,当任务被用作复制源(即作为 from() 的参数)时,copy() 方法不能尊重任务依赖关系,因为它是一种方法而不是任务。因此,如果您将 copy() 方法用作任务操作的一部分,则必须显式声明所有输入和输出才能获得正确的行为。

    【讨论】:

    • 该段讨论了project.copy 方法及其相对于Copy 任务的缺点。与您的问题无关。
    • 嗯..它实际上是相关的。因为我真正的问题是我试图在“复制”任务的 doLast 块中复制(我提供的示例不包含该内容并且过于简化)并且由于缺少输入源定义而没有触发该任务.我将复制从 doLast 块中移出,现在很高兴 :) 感谢您的帮助!
    • 不确定“我将复制移出 doLast 块”到底是什么意思。
    • 我实际上使用了gradle RPM plugin(它提供了 Copy 类型的任务)而不是 task "distRpm${templ}" (type: Rpm, dependsOn: xxx) { from ... into ...有任务“distRpm${templ}”(类型:Rpm,dependsOn:xxx)
    • 您的旧代码在doLast 操作中配置任务,正如我所解释的那样,为时已晚。 (这与project.copy方法无关。)现在你在配置阶段配置任务,这是正确的。
    【解决方案3】:

    在 gradle 中阅读了“UP-TO-DATE”复制任务的大部分答案后,似乎缺少的部分是 'include' 关键字:

    task copy3rdPartyLibs(type: Copy) {
        from 'src/main/jni/libs/'
        into 'src/main/libs/armeabi/'
        include '**/*.so'
    }
    

    【讨论】:

      【解决方案4】:

      frominto 作为doLast 部分的一部分不起作用。工作任务定义的一个示例是:

      task copyMyFile(type: Copy) {
      
          def dockerFile = 'src/main/docker/Dockerfile'
          def copyTo = 'build/docker'
      
          from dockerFile
          into copyTo
      
          doLast {
              println "Copied Docker file [$dockerFile] to [$copyTo]"
          }
      }
      

      不是我期望的行为。 使用 gradle 3.2.1

      【讨论】:

      • 您的意思是def dockerFile = 'src/main/docker/Dockerfile' 吗?
      猜你喜欢
      • 2011-11-09
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多