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

多平台项目:如何将generated源集类加入metadata工件?

这个问题我之前帮同行排查过类似的,核心就是Kotlin多平台(KMP)的metadata构件默认只包含commonMain源集的内容,而你自定义的generated源集没被关联到common侧的构建流程里,导致依赖项目的commonMain找不到这些生成类。给你几个可行的解决方案,按需选择:

方案1:把生成代码直接归到commonMain(最省心)

没必要单独维护generated源集,直接让kapt生成的代码成为commonMain的一部分,这样metadata自然会把这些类包含进去。

在你的build.gradle.kts里这么配置:

kotlin {
    sourceSets {
        val commonMain by getting {
            // 把kapt生成common代码的目录添加到commonMain的源码路径
            kotlin.srcDir("build/generated/source/kaptKotlin/commonMain")
        }
        // 原来jvmMain、jsMain依赖generated的配置可以保留,或者如果不需要就删掉
        val jvmMain by getting
        val jsMain by getting
    }
}

// 确保kapt先生成代码,再编译commonMain的元数据
tasks.named("compileCommonMainKotlinMetadata") {
    dependsOn(tasks.named("kaptCommonMainKotlin"))
}

这样kapt生成的类会被当作commonMain的原生代码处理,编译后自动进入metadata工件,依赖项目的commonMain就能直接用了。

方案2:保留generated源集,关联到common侧构建

如果你想保留单独的generated源集,那就得调整源集依赖和任务执行顺序,打破循环依赖的问题:

kotlin {
    sourceSets {
        // 先定义generated源集
        val generated by creating {
            kotlin.srcDir("build/generated/source/kaptKotlin/generated")
            // 让generated依赖commonMain的输出,因为kapt需要用common里的注解类
            dependencies {
                implementation(commonMain.get().output)
            }
        }
        val commonMain by getting {
            // 让commonMain依赖generated,但得确保先生成代码再编译
            dependsOn(generated)
        }
        // 原来jvm、js依赖generated的配置不变
        val jvmMain by getting { dependsOn(generated) }
        val jsMain by getting { dependsOn(generated) }
    }
}

// 强制kapt生成代码后,再编译generated的元数据
tasks.named("compileGeneratedKotlinMetadata") {
    dependsOn(tasks.named("kaptCommonMainKotlin"))
}

// 确保generated编译完成后,再编译commonMain的元数据
tasks.named("compileCommonMainKotlinMetadata") {
    dependsOn(tasks.named("compileGeneratedKotlinMetadata"))
}

这个方案通过明确任务执行顺序解决循环:先跑kapt处理commonMain的注解生成代码,再编译generated,最后编译依赖generated的commonMain,这样metadata里就会包含generated的类了。

方案3:直接给metadata jar塞generated类

如果前两个方案都不适合,还可以直接修改metadata构件的内容,把generated的编译产物加进去:

tasks.named<Jar>("kotlinMetadataJar") {
    // 把generated源集编译后的元数据产物添加到metadata jar里
    from(tasks.named("compileGeneratedKotlinMetadata").map { it.outputs })
}

这种方式更直接,相当于手动把generated的类塞进metadata工件里,适合不想调整源集结构的场景。

几个要注意的点

  • 确保kapt生成的代码是跨平台兼容的,不能有jvm/js专属的API,不然metadata里的类在跨平台依赖时会出问题。
  • 如果用的Gradle版本比较新,任务名称可能有变化,比如kaptCommonMainKotlin可能变成kaptGenerateStubsCommonMainKotlin,可以跑./gradlew tasks查看具体的任务名。
  • 一定要检查任务依赖顺序,不然会出现编译时找不到生成类的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 21:58:00