Gradle zip任务失败,因为zip不存在

时间:2019-09-19 15:33:50

标签: gradle

我有一个gradle构建脚本,其中包含一个类似于以下内容的任务:

task unzip_foo_bar (type: Copy) {
    from zipTree ("foo.zip").matching { include '**/bar.h' }.singleFile
    into "build"
}

在执行任务之前,将从外部存储库中将.zip文件提取到本地工作空间中。

但是由于某些原因,当您将.matching与.singleFile一起使用时,Gradle希望在编译脚本时该zip文件已经存在于本地工作区中。

在这种情况下,由于.zip文件在编译时不存在,因此脚本编译失败。

因此以下内容可以正常工作

task unzip_foo_bar (type: Copy) {
    from zipTree ("foo.zip")
    into "build"
}

在这种情况下,Gradle能够编译脚本并且可以正常工作。

有人可以解释行为上的差异吗?

第一个实现的原因是我希望能够从.zip存档中提取单个文件,而不是将存档中的所有文件都转储到本地工作区中。

我将如何进行这项工作?

1 个答案:

答案 0 :(得分:1)

Gradle中的方法zipTree返回FileTree,该方法支持惰性求值,因此仅在需要时才确定树的内容。诸如Copy任务之类的各种任务类型通过允许用户传递树作为输入来支持此行为。该树可以在配置阶段中构造,但只有在执行阶段中,并且在执行任务时才进行查询。

现在,第一个示例的问题是调用singleFile会触发树评估,因为它需要返回File的实例。要找到该文件,Gradle需要打开.zip文件,但由于找不到该文件而失败。 matching调用不是问题,因为它会创建另一个延迟评估的FileTree。因此,只需将呼叫放到singleFile上,您的代码就可以工作了:

from zipTree ("foo.zip").matching { include '**/bar.h' }

但是,如果要保留只有一个文件与模式匹配的断言,则可以将表达式包装在Closure中,该表达式将整体上被懒惰地求值:

from { zipTree ("foo.zip").matching { include '**/bar.h' }.singleFile }