Gradle中定义任务非文件输出并在其他任务中使用的最优方案
Gradle任务间非文件值传递的最优实现方案
需求场景
我们的任务依赖关系为:Task B 和 Task C 均依赖于 Task A,需要在 Task A 中生成值"dogs",并让 Task B、Task C 能够获取并使用该值。Gradle 提供了@OutputFile注解用于标记文件类型的任务输出,但没有直接对应非文件输出的@Output注解。
最优实现方式
推荐方案:使用@OutputProperty注解(Gradle 6.0+)
Gradle 6.0及以上版本官方提供了@OutputProperty注解,专门用于标记非文件类型的任务输出属性。该方案既可以让Gradle追踪属性值的变化以实现增量构建,又能方便其他任务直接引用该值,是最规范的实现方式。
示例代码:
// 定义TaskA,生成并输出"dogs"值 abstract class TaskA extends DefaultTask { // 用@OutputProperty标记非文件输出属性 @OutputProperty final Property<String> dogs = project.objects.property(String) @TaskAction void execute() { // 设置输出值 dogs.set("dogs") } } // 定义TaskB,接收并使用TaskA的输出值 abstract class TaskB extends DefaultTask { // 用@Input标记输入属性,关联TaskA的输出 @Input final Property<String> dogs = project.objects.property(String) @TaskAction void execute() { // 使用获取到的值 println "Task B 获取到的值:${dogs.get()}" } } // 配置任务 task taskA(type: TaskA) task taskB(type: TaskB) { // 关联TaskA的dogs输出属性 dogs.set(taskA.dogs) // 声明依赖,确保TaskA先执行 dependsOn taskA } task taskC(type: TaskB) { dogs.set(taskA.dogs) dependsOn taskA }
兼容低版本方案:使用Provider API
如果使用Gradle 6.0以下版本,可以通过Provider API实现值传递,同时手动标记输出属性以支持增量构建。
示例代码:
class TaskA extends DefaultTask { private final Property<String> dogs = project.objects.property(String) // 暴露供其他任务引用的Provider Provider<String> getDogsProvider() { dogs } @TaskAction void execute() { dogs.set("dogs") } // 标记为任务输出,支持增量构建 @Output String getDogs() { dogs.getOrNull() } } class TaskB extends DefaultTask { @Input String dogs @TaskAction void execute() { println "Task B 获取到的值:${dogs}" } } // 配置任务 task taskA(type: TaskA) task taskB(type: TaskB) { // 通过Provider获取TaskA的输出值 dogs = taskA.dogsProvider dependsOn taskA } task taskC(type: TaskB) { dogs = taskA.dogsProvider dependsOn taskA }
方案说明
- 两种方案都能实现任务间的非文件值传递,同时保证Gradle的增量构建功能正常工作:当
dogs值发生变化时,依赖它的Task B、C会自动重新执行。 - 优先选择
@OutputProperty方案,这是Gradle官方针对非文件输出场景提供的标准解决方案,代码更简洁、符合Gradle的设计规范。
内容的提问来源于stack exchange,提问作者Fudge Fudge
相关产品推荐
相关产品推荐

