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

Gradle中基于已有Kotlin代码生成代码并打包入Jar的构建问题

问题

在Gradle Kotlin库项目中,我需要先编译原有Kotlin代码,通过自省原有代码(由代码中的main()函数触发)生成额外Kotlin代码,再编译生成的代码,最后将原有代码和生成代码的编译产物打包到输出Jar中。我编写的构建脚本如下:

sourceSets {
    generated {
        kotlin {
            srcDir "src/generated/kotlin"
        }
        compileClasspath += main.output + configurations.runtimeClasspath
        runtimeClasspath += main.output
    }
}

task generateCode(type: JavaExec) {
    classpath = sourceSets.main.runtimeClasspath
    mainClass = "com.something.CodeGenMainKt"
    doFirst {
        file("src/generated/kotlin").mkdirs()
    }

    dependsOn compileKotlin
}

task compileGeneratedKotlin(type: KotlinCompile) {
    source = sourceSets.generated.kotlin
    dependsOn generateCode
}


jar {
    dependsOn compileGeneratedKotlin
    from sourceSets.main.output
    from sourceSets.generated.output
}

运行时出现错误:

A problem occurred evaluating root project 'biz-kotlin'.
> Could not create task ':compileGeneratedKotlin'.
   > Could not create task of type 'KotlinCompile'.
      > Unable to determine constructor argument #1: missing parameter of type KotlinJvmCompilerOptions, or no service of type KotlinJvmCompilerOptions.

请问为何无法添加该额外编译步骤?其余脚本是否存在问题?


解决方法

错误原因

你手动创建compileGeneratedKotlin任务时出错,核心原因是新版Gradle Kotlin插件(Kotlin 1.8+)中,KotlinCompile任务的构造必须依赖KotlinJvmCompilerOptions服务,手动实例化该任务时无法自动获取这个必要的构造参数,导致报错。

修复步骤

Gradle会为自定义的sourceSet自动生成对应的编译任务,完全不需要手动创建compileGeneratedKotlin。你只需要调整任务依赖关系即可:

  1. 删除手动定义的compileGeneratedKotlin任务
  2. 让自动生成的compileGeneratedKotlin任务依赖generateCode任务
  3. 确保jar任务依赖自动生成的编译任务

修改后的完整脚本:

sourceSets {
    generated {
        kotlin {
            srcDir "src/generated/kotlin"
        }
        compileClasspath += main.output + configurations.runtimeClasspath
        runtimeClasspath += main.output
    }
}

task generateCode(type: JavaExec) {
    classpath = sourceSets.main.runtimeClasspath
    mainClass = "com.something.CodeGenMainKt"
    doFirst {
        file("src/generated/kotlin").mkdirs()
    }
    dependsOn compileKotlin
}

// 关联自动生成的编译任务与代码生成任务
tasks.named('compileGeneratedKotlin') {
    dependsOn generateCode
}

jar {
    dependsOn tasks.named('compileGeneratedKotlin')
    from sourceSets.main.output
    from sourceSets.generated.output
}

其余脚本的优化建议

  1. 避免污染源码目录:生成的代码属于构建产物,建议将生成目录放在build目录下(比如build/generated/sources/codegen/kotlin),而不是src目录,防止构建产物混入源码仓库。修改方式:
    sourceSets {
        generated {
            kotlin {
                srcDir "${buildDir}/generated/sources/codegen/kotlin"
            }
            // 其余配置不变
        }
    }
    
    task generateCode(type: JavaExec) {
        // 其余配置不变
        doFirst {
            file("${buildDir}/generated/sources/codegen/kotlin").mkdirs()
        }
    }
    
  2. 优化代码生成任务的classpath:sourceSets.main.runtimeClasspath可能包含不必要的依赖,改用sourceSets.main.compileClasspath + sourceSets.main.output更精准,确保只包含编译和自省原有代码所需的类:
    task generateCode(type: JavaExec) {
        classpath = sourceSets.main.compileClasspath + sourceSets.main.output
        // 其余配置不变
    }
    
  3. 清理旧生成代码:可以在代码生成前清理目标目录,避免旧代码干扰新生成的内容:
    task generateCode(type: JavaExec) {
        // 其余配置不变
        doFirst {
            def genDir = file("${buildDir}/generated/sources/codegen/kotlin")
            genDir.deleteDir()
            genDir.mkdirs()
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 13:33:40