2

projectA我在创建文件的项目(我们称之为)构建脚本中有一个简单的自定义任务。任务如下所示:

task createFile() {
  def outputFile = rootProject.file("${buildDir}/tmp/outputFile.txt")
  outputs.file(outputFile)
  outputs.upToDateWhen { false }
  doLast {
    outputFile.parentFile.mkdirs()
    outputFile.text = "Hello World"
  }
}

该项目是多项目构建的一部分,我需要此任务生成的文件作为projectB. 为了实现这一点,我在其中创建了一个配置projectB和一个相应的依赖项:

configurations {
  mySourceConfig
}

dependencies {
  mySourceConfig project(path: ':projectA', configuration: 'myDistConfig')
}

task copySourceDependencies(type: Copy) {
   from configurations.mySourceConfig 
   into contextDir
}

projectA我得到一个myDistConfig配置并希望使用createFile任务的输出文件作为这个配置的工件:

configurations {
  myDistConfig
}

artifacts {
  myDistConfig createFile
}

如果我这样做,gradle 会告诉我一个任务不能转换为ConfigurablePublishArtifact

> Cannot convert the provided notation to an object of type ConfigurablePublishArtifact: task ':projectA:createFile'.   The
  following types/formats are supported:
     - Instances of ConfigurablePublishArtifact.
     - Instances of PublishArtifact.
     - Instances of AbstractArchiveTask, for example jar.
     - Instances of Provider<RegularFile>.
     - Instances of Provider<Directory>.
     - Instances of Provider<File>.
     - Instances of RegularFile.
     - Instances of Directory.
     - Instances of File.
     - Maps with 'file' key

所以我尝试createFile.outputs.files.singleFile作为神器。这会阻止 gradle 抱怨,但无法设置 and 之间的依赖关系:projectB:copySourceDependencies:projectA:createFile如果projectB:copySourceDependencies在干净的工作空间上执行,它会简单地跳过 status NO-SOURCE

是否有可能以某种方式使用自定义任务作为类似于 Zip 任务的工件,以使 gradle 了解依赖关系?!


2020-02-28 更新

基于@BjørnVester 的非常好的回答,我在一个单独的 gradle 文件中实现了以下任务util.gradle

class CreateFile extends DefaultTask {

  @OutputFile
  RegularFileProperty outputFile = project.objects.fileProperty()

  @TaskAction
  void createFile() {
    def tOutFile = outputFile.get().asFile
    tOutFile.parentFile.mkdirs()
    tOutFile.text = "Hello World"
  }
}

rootProject.ext.CreateFile = CreateFile

在 projectA 中,build.gradle它看起来像这样:

apply from 'util.gradle'

task createFile(type: CreateFile) {
  outputFile = rootProject.file("${buildDir}/tmp/outputFile.txt")
}

artifacts {
  myDistConfig createFile.outputFile
}

现在 gradle 知道正确的依赖关系,它就像一个魅力!

4

1 回答 1

2

当使用任务作为工件符号时,它必须是AbstractArchiveTask类型。因此,对于其他类型的任务,您将不得不做其他事情。

使用方法createFile.outputs.files.singleFile很好,因为它是受支持的类型(从错误输出中可以看到)。但是 Gradle 不创建对生产任务的依赖的原因是 aFile不携带该信息。为此,它必须是一个Provider. 但修复它的一种快速方法是明确配置生成工件的任务:

artifacts.add("myDistConfig", createFile.outputs.files.singleFile) {
    builtBy("createFile")
}

或者,您也可以将 outputFile 更改为Provider<File>RegularFileProperty使用 ObjectFactory,因为它们携带任务生产者信息。我从未将它们用作 DSL 的一部分,它可能更适合使用类。(虽然这看起来需要更多工作,但一旦代码增长到一定水平,它就会使代码更具可读性。)这是 Groovy 中的一个示例:

class MyFileCreator extends DefaultTask {
  @OutputFile
  RegularFileProperty outputFile = project.objects.fileProperty().convention(project.layout.buildDirectory.file("tmp/outputFile.txt"))

  @TaskAction
  void createFile() {
    File outFile = outputFile.get().asFile
    outFile.parentFile.mkdirs()
    outFile.text = "Hello World"
  }
}

MyFileCreator createFileTask = tasks.create("createFile", MyFileCreator)

configurations {
  myDistConfig
}

artifacts {
  myDistConfig createFileTask.outputFile
}
于 2020-02-28T12:31:09.413 回答