Zac Sweers
11/10/2025, 6:41 PMdependencies {
add("kspCommonMainMetadata", project(":test-processor"))
add("kspJvm", project(":test-processor"))
}
However, I'm finding this to have a couple problems
1. The kspCommonMainMetadata task never appears to run unless explicitly depended on. This has been pointed out in the issue tracker it seems: https://github.com/google/ksp/issues/567#issuecomment-2609469736
2. It appears that processors in specific targets run on all sources (the complete set of target and common sources), which results in redeclaration/duplication issues for any sources in commonMain.
My questions on this I guess are
• Should kspCommonMainMetadata be configured to always run? Or at least if it has processors on its classpath? Seems a longstanding footgun that it's inert by default without some manual gradle fiddling
• Should there be a way to limit processing in specific targets to only run on sources defined in that source set, rather than the full set? I don't see a means currently for processors to handle this scenario (no means of detecting source set of origin, etc)
In general, it appears strongly to me like KSP on common sources is essentially only viable if you don't use the same processors in multiple source sets and know how to do the above gradle task wiring trick to force it to run. Happy to file issues for each of the above bullets tooRey (Kingg22)
11/10/2025, 7:54 PMexpect actual or handle it in common main using Gradle tricks, but I still don't quite understand it.
@eygraber I see your name in the latest commits, could you instruct me on how a processor should support both configurations?Rey (Kingg22)
11/10/2025, 7:56 PMeygraber
11/10/2025, 8:00 PMeygraber
11/10/2025, 8:16 PMwhen working with KMP, the docs suggest to apply the KSP processors you need to both common and the specific targets: https://kotlinlang.org/docs/ksp-multiplatform.htmlThat doesn't seem correct. I tried doing that originally, and got redeclaration/duplication issues. I thought I would be able to get it to work by detecting what target the processor was running for, but IIRC that wasn't possible. I think the rule of thumb is that if your annotated code is in the common source set, and doesn't reference anything that is expect/actual, then you should add the KSP processors to
kspCommonMainMetadata
The kspCommonMainMetadata task never appears to run unless explicitly depended onIf I'm using
kspCommonMainMetadata I always do this (I use a convention plugin):
kotlin {
// I don't remember if this is needed anymore
commonMain {
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}
}
tasks.withType<KspAATask>().configureEach {
if (name != "kspCommonMainKotlinMetadata") {
dependsOn("kspCommonMainKotlinMetadata")
}
}
It appears that processors in specific targets run on all sources (the complete set of target and common sources), which results in redeclaration/duplication issues for any sources in commonMainCorrect, which is why I'm pretty sure it's is XOR for a processor to be used in common / targets.
Rey (Kingg22)
11/10/2025, 8:20 PMdependencies {
// don't apply on common main because we going to generate on each platform
// kspCommonMainMetadata(projects.compiler)
add("kspAndroidDebug", projects.compiler)
add("kspAndroidRelease", projects.compiler)
add("kspJvm", projects.compiler)
add("kspJs", projects.compiler)
// all targets ...
}Rey (Kingg22)
11/10/2025, 8:21 PMeygraber
11/10/2025, 8:24 PMRey (Kingg22)
11/10/2025, 8:26 PMgeneratedKotlin.srcDir("...") 😉Ting-Yuan Huang
11/11/2025, 9:56 PMTing-Yuan Huang
11/11/2025, 10:22 PMkspCommonMainMetadata didn't run because compileKotlinCommonMainMetadata didn't run. This is rooted from Kotlin's compilation model, which KSP follows. In KMP, common files are compiled with different target files multiple times. They are compiled N+ times if it is shared among N targets. The "+" comes from metadata compilation such as compileKotlinCommonMainMetadata. compileKotlinCommonMainMetadata can be skipped when there is only JVM target.
By design, generated files from common files are not visible to downstream target compilations. Processors (and kotlinc) are expected to re-generate files (and binaries in the case of kotlinc) in each compilation. Unless the generated files are wired together from different tasks manually in the build script, there shouldn't be redeclaration. (or bugs in KSP, of course)
Back to Zac's questions:
1. Generated files from kspCommonMainMetadata would be useless unless compileKotlinCommonMainMetadata also runs. They should not be consumed by other tasks, at least with current build model.
2. I thought add("kspJvm", project(":test-processor")) is exactly designed for that. Users can specify which task (slightly different to source sets though) they want processors to run. It would be an regression / bug if that doesn't work.mbonnin
11/11/2025, 10:38 PMmbonnin
11/11/2025, 10:41 PMProcessors (and kotlinc) are expected to re-generate files (and binaries in the case of kotlinc) in each configuration.@Ting-Yuan Huang did you mean "in each compilation" here?
Ting-Yuan Huang
11/11/2025, 10:42 PMZac Sweers
11/11/2025, 10:42 PMcompileKotlinCommonMainMetadata to run? As best I can tell, that task never seems to runZac Sweers
11/11/2025, 10:43 PMIt would be an regression / bug if that doesn't work.That is the observed behavior in this project: https://github.com/JvmName/sprakbund
Ting-Yuan Huang
11/11/2025, 10:43 PMZac Sweers
11/11/2025, 10:43 PMZac Sweers
11/11/2025, 10:44 PMIt should run as long as you have multiple targets, and one of them is not JVM.That's quite the asterisk 🙂
mbonnin
11/11/2025, 10:44 PMcommonMainMetadata then? What is the target used for? IDE support maybe?Zac Sweers
11/11/2025, 10:45 PMElijah Dangerfield
11/15/2025, 2:45 PMkspCommonMainMetadata AND the target specific kspIosArm64 (for example)? How exactly do we solve the redeclaration issues? I'm very new to KMP and im having a hard time setting up everything