【问题标题】:Generating a file in one Gradle task to be operated on by another Gradle task在一个 Gradle 任务中生成文件以供另一个 Gradle 任务操作
【发布时间】:2014-09-04 23:22:06
【问题描述】:

我第一次在一个项目上使用 Gradle,在我的上一个项目中来自 Ant。到目前为止,我喜欢我所看到的,尽管我试图弄清楚如何做一些让我陷入困境的事情。我想知道在以下情况下使用什么模式是正确的。

我有一系列文件,我需要对其执行一些操作。每个任务都对它之前的任务新生成的输出文件进行操作。我将尝试设计一个示例来演示我的问题,因为我的项目有点复杂和内部。

第一阶段

首先,假设我有一个任务必须写出 100 个单独的文本文件,每个文件中都有一个随机数。文件名无关紧要,假设它们都位于 parentFolder 下。

例子:

parentFolder
|
|-file1
|-file2
...
|-file100

我认为我最初的想法是在自定义任务的 doLast(使用

task generateNumberFiles << {
  File parentFolder = mkdir(buildDir.toString() + "/parentFolder")
  for (int x=0; x<=100; x++)
  {
     File currentFile = file(parentFolder.toString() + "/file" + String.valueOf(x))
     currentFile.write(String.valueOf(Math.random()))
  }
}

第二阶段

接下来,假设我需要读取 generateNumberFiles 任务中生成的每个文件,并将每个文件压缩到第二个文件夹 zipFolder 中的单独存档中。为简单起见,我将其放在 parentFolder 下,但位置并不重要。

期望的输出:

parentFolder
|
|-file1
|-file2
...
|-file100
|-zipFolder
  |
  |-file1.zip
  |-file2.zip
  ...
  |-file100.zip

这似乎有问题,因为理论上我需要为每个文件创建一个 Zip 任务(为每个文件生成一个单独的存档)。所以我想这是问题的第一部分:如何创建一个单独的任务来处理在先前任务期间生成的一堆文件,并让该任务作为构建过程的一部分运行?

在执行时添加任务绝对是可能的,但让任务运行似乎更有问题。我读过使用 .execute() 是不可取的,从技术上讲,它是一种内部方法。

我还想过将dependsOn 添加到带有.matching { Task task -&gt; task.name.startsWith("blah")} 块的后续任务中。但这似乎行不通,因为[在 Gradle 配置阶段][1] 解决了任务依赖性。那么如何创建任务来操作这些文件,因为它们在配置时不存在?

第三阶段

最后,让我们稍微复杂一点,说我需要对第二阶段生成的 ZIP 存档执行一些其他自定义操作,这些操作不是 Gradle 内置的。我想不出一个现实的例子,所以假设我必须读取每个 ZIP 的第一个字节并将其上传到某个服务器——这涉及到对每个 ZIP 进行独立操作。

第三阶段只是我在第二阶段的问题的延续。我觉得做这种事情的 Gradle-y 方法是创建对每个文件执行一个工作单元的任务,并使用一些依赖项来执行这些任务。但是,如果在构建依赖图时任务不存在,我该如何完成这种事情呢?另一方面,我是否完全离开了,还有其他方法可以做这种事情吗?

[1]:“Gradle 在执行任何任务之前构建完整的依赖关系图。” http://www.gradle.org/docs/current/userguide/build_lifecycle.html

【问题讨论】:

    标签: groovy gradle


    【解决方案1】:

    您不能在执行阶段创建任务。您可能已经知道,由于 Gradle 在配置阶段构建了该任务执行图,因此您以后无法添加任务。

    如果您只是试图将一个任务的输出作为另一个任务的输入,那么这将变成一个简单的dependsOn 关系,就像 Ant 一样。我相信您可能会走错路,因为您认为您需要为您打算创建的每个存档动态创建 Gradle Zip 任务。在这种情况下,由于您将创建的档案数量是基于另一个任务的输出的动态的(即在执行期间确定),您可以简单地创建一个创建所有这些 zip 文件的任务。最简单的方法是通过 Gradle 的 Ant support 使用 Ant 的 zip 任务。

    【讨论】:

    • 感谢您的回答,马克,很高兴听到有关任务创建的确认。至于使用 Ant 的 zip 任务,似乎使用 Ant 任务更多是为了与旧版本兼容,但我可能错了。由于这是一个新项目,如果可以的话,我宁愿保持干净的 Gradle(没有 Ant),我的想法是 Gradle 必须有一些方法来处理这种情况。也许蚂蚁是唯一的方法?
    • 不一定。除了编写自定义任务(取决于您的用例,这可能是合适的)之外,我没有看到用单个任务创建多个存档的另一种方法。实际上,Gradle Zip 任务在后台使用 Ant,因此它们在功能上应该是相同的。使用 Gradle 任务的优势在于 Gradle DSL 的简洁性和更好的增量构建支持。
    • 如果我写了一个自定义任务,我已经完成了一些自定义处理,我可以利用 Gradle 的内置任务动作,例如 Zip、Upload、War 等吗?或者我是否需要在我的自定义任务中基本上重写这些操作?我肯定明白你对增量构建支持的看法,因为我很期待这种能力,但我不确定是否/如何在这些动态场景中使用它。
    • 您可以扩展Zip 任务,但同样,它旨在创建单个存档。您还可以使用 Gradle 内部 ZipCopyAction,但这是一个内部 API,可能不应该使用。您也可以选择使用 Java 库,例如 commons-io。我个人会选择 Ant 选项。它是一个公共 API,与 Gradle 捆绑在一起,并提供您想要的功能。您仍然可以编写自定义任务,实现(即@TaskAction)将简单地委托给 Ant。
    【解决方案2】:

    我们做类似的事情。虽然马克维埃拉的回答是正确的,但可能有一种方法可以稍微调整两端的东西。具体来说:

    1. 您可以像我们一样发现在配置阶段需要创建的所有 zip 文件。这将允许您创建任意数量的 zip 任务,适当地命名它们并正确关联它们。这也将允许您根据需要单独构建它们,并通过最新检查利用增量构建支持。

    2. 如果在发现 (1) 和 if 所需内容之前,您需要做一些事情相对简单,您可以编写代码特别不是作为一项任务,而是作为一个配置步骤。

    请注意,“Gradle-y”方式很灵活,但不要仅仅因为您可能觉得这是“Gradle-y”而这​​样做。做正确的事。如果您希望能够单独调用和关联它们,则需要单独的任务,也许通过跳过最新的任务来优化构建性能。如果这不是您关心的内容,请不要担心将每个文件变成自己的任务。

    【讨论】:

      猜你喜欢
      • 2020-07-09
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 2014-06-30
      • 1970-01-01
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多