如何将自定义任务用作工件
How to use custom task as artifact
我在项目的(我们称之为 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 抱怨,但无法设置 :projectB:copySourceDependencies
和 :projectA:createFile
之间的依赖关系,如果 projectB:copySourceDependencies
在干净的工作区上执行,它会被简单地跳过状态 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
在项目 A 的 build.gradle
中,它看起来像这样:
apply from 'util.gradle'
task createFile(type: CreateFile) {
outputFile = rootProject.file("${buildDir}/tmp/outputFile.txt")
}
artifacts {
myDistConfig createFile.outputFile
}
现在 gradle 知道正确的依赖关系并且它工作得很好!
当使用任务作为工件符号时,它必须是 AbstractArchiveTask 类型。所以对于其他类型的任务,你将不得不做其他事情。
使用 createFile.outputs.files.singleFile
的方法很好,因为它是受支持的类型(从错误输出中可以看出)。但是 Gradle 不对生产任务产生依赖的原因是 File
不携带该信息。为此,它必须是 Provider
。但修复它的一种快速方法是明确配置生成工件的任务:
artifacts.add("myDistConfig", createFile.outputs.files.singleFile) {
builtBy("createFile")
}
或者,您也可以使用 ObjectFactory 将 outputFile 更改为 Provider<File>
或 RegularFileProperty
,因为它们带有任务生成器信息。我从未将它们用作 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
}
我在项目的(我们称之为 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 抱怨,但无法设置 :projectB:copySourceDependencies
和 :projectA:createFile
之间的依赖关系,如果 projectB:copySourceDependencies
在干净的工作区上执行,它会被简单地跳过状态 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
在项目 A 的 build.gradle
中,它看起来像这样:
apply from 'util.gradle'
task createFile(type: CreateFile) {
outputFile = rootProject.file("${buildDir}/tmp/outputFile.txt")
}
artifacts {
myDistConfig createFile.outputFile
}
现在 gradle 知道正确的依赖关系并且它工作得很好!
当使用任务作为工件符号时,它必须是 AbstractArchiveTask 类型。所以对于其他类型的任务,你将不得不做其他事情。
使用 createFile.outputs.files.singleFile
的方法很好,因为它是受支持的类型(从错误输出中可以看出)。但是 Gradle 不对生产任务产生依赖的原因是 File
不携带该信息。为此,它必须是 Provider
。但修复它的一种快速方法是明确配置生成工件的任务:
artifacts.add("myDistConfig", createFile.outputs.files.singleFile) {
builtBy("createFile")
}
或者,您也可以使用 ObjectFactory 将 outputFile 更改为 Provider<File>
或 RegularFileProperty
,因为它们带有任务生成器信息。我从未将它们用作 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
}