You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin DSL(KTS)中正确配置带指定输入输出的自定义Gradle任务

解决方案

方法一:扩展Copy任务实现轻量内容转换

Copy任务本身支持内容过滤,适合简单文本替换场景,且自动集成增量构建能力,无需手动声明输入输出追踪逻辑。

代码示例

tasks.register<Copy>("processTextFiles") {
    from("src/main/text")
    into("build/processed-text")
    include("**/*.txt")

    // 方式1:用ReplaceTokens批量替换占位符(适合@oldString@格式的标记)
    filter<ReplaceTokens>("tokens" to mapOf("oldString" to "newString"))

    // 方式2:自定义FilterReader实现精准字符串替换
    /*
    filter { reader ->
        object : FilterReader(reader) {
            override fun read(cbuf: CharArray, off: Int, len: Int): Int {
                val tempBuf = CharArray(len)
                val readCount = super.read(tempBuf, off, len)
                if (readCount == -1) return -1
                val processedContent = String(tempBuf, off, readCount).replace("oldString", "newString")
                processedContent.toCharArray().copyInto(cbuf, off)
                return processedContent.length
            }
        }
    }
    */
}

关键说明

  • 复用Copy任务的输入输出追踪机制,Gradle会自动检测输入文件的内容/路径变化,仅在需要时执行任务。
  • 两种过滤方式按需选择:ReplaceTokens适合批量替换占位符,自定义FilterReader更灵活,支持任意字符串处理逻辑。

方法二:自定义任务类型(适配复杂处理逻辑)

如果需要多步骤文本处理、正则匹配等复杂操作,可创建自定义任务类,通过注解明确声明输入输出,同时支持增量构建。

步骤1:编写自定义任务类

可将类放在项目的buildSrc/src/main/kotlin目录(全局复用)或模块的src/main/kotlin目录(模块内复用):

import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.work.Incremental
import org.gradle.work.InputChanges
import java.io.File

abstract class ProcessTextTask : DefaultTask() {
    // 输入目录,@Incremental标记支持增量处理
    @get:Incremental
    @get:InputDirectory
    abstract val inputDir: DirectoryProperty

    // 输出目录
    @get:OutputDirectory
    abstract val outputDir: DirectoryProperty

    // 可配置的替换参数
    @get:Input
    abstract val oldString: Property<String>

    @get:Input
    abstract val newString: Property<String>

    @TaskAction
    fun process(inputChanges: InputChanges) {
        // 仅处理变化的文件
        inputChanges.getFileChanges(inputDir).forEach { change ->
            val inputFile = change.file
            val outputFile = outputDir.file(inputFile.name).get().asFile

            if (change.fileType == FileType.DIRECTORY) return@forEach

            when (change.changeType) {
                ChangeType.ADDED, ChangeType.MODIFIED -> {
                    val content = inputFile.readText()
                    val processedContent = content.replace(oldString.get(), newString.get())
                    outputFile.writeText(processedContent)
                }
                ChangeType.REMOVED -> outputFile.delete()
            }
        }
    }
}

步骤2:在build.gradle.kts中注册任务

tasks.register<ProcessTextTask>("processTextFiles") {
    inputDir.set(file("src/main/text"))
    outputDir.set(file("build/processed-text"))
    oldString.set("oldString")
    newString.set("newString")
}

关键说明

  • @Incremental:告诉Gradle可以增量处理输入,仅处理新增/修改/删除的文件。
  • @InputDirectory/@OutputDirectory:让Gradle正确追踪输入输出的状态变化,避免无意义的重复执行。
  • 若不需要增量处理(比如必须全量生成),可移除@Incremental和inputChanges相关逻辑,保留输入输出注解即可。

解决你之前的增量构建失效问题

你之前的自定义任务每次都执行,核心原因有两个:

  1. 仅声明了输入输出目录,但任务动作中没有利用Gradle的增量输入API,Gradle无法判断哪些文件需要处理,只能全量执行。
  2. 手动遍历文件时未保留输入文件的相对路径(比如子目录文件会被覆盖到输出根目录),导致Gradle无法建立输入输出的关联关系。

验证增量构建

执行任务后,再次运行./gradlew processTextFiles,若输入文件无变化,Gradle会输出UP-TO-DATE,表示任务无需执行。

内容的提问来源于stack exchange,提问作者wnetsimon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:08:27