I'm facing a problem with KMP+KSP. I have a projec...
# multiplatform
p
I'm facing a problem with KMP+KSP. I have a project-local KSP processor (not published anywhere). I initially added the annotation as an
implementation
kind of dependency, which was obviously a mistake. Then changed it to
compileOnly
, but now I'm getting:
Copy code
> There was a failure while executing work items
   > A failure occurred while executing kotlinx.benchmark.gradle.NativeSourceGeneratorWorker
      > e: KLIB resolver: Could not find "it.krzeminski:copy-dsl-ksp-processor" in [/home/runner/work/snakeyaml-engine-kmp/snakeyaml-engine-kmp]
with this hint:
Copy code
A compileOnly dependency is used in targets: Kotlin/JS, Kotlin/Native, Kotlin/Wasm.
Dependencies:
    - snakeyaml-engine-kmp:copy-dsl-ksp-processor:unspecified (source sets: iosArm64Main, iosSimulatorArm64Main, iosX64Main, jsMain, linuxArm64Main, linuxX64Main, macosArm64Main, macosX64Main, mingwX64Main, tvosArm64Main, tvosSimulatorArm64Main, tvosX64Main, wasmJsMain, watchosArm32Main, watchosArm64Main, watchosSimulatorArm64Main, watchosX64Main)
Adding an
api
kind of dependency indeed helps, but only for another module in the repo that consumes my module using the KSP processor. For external clients, I'd still need to publish the lib. My question is: how do I deal with using my local KSP processor only during build time, so that it doesn't need to be used in compile/runtime by the external clients? Relevant PR: https://github.com/krzema12/snakeyaml-engine-kmp/pull/599
So far the only idea that comes to my mind is moving the annotation to the consumer library, which would remove a dependency on the KSP processor module from the lib consumer's PoV, but also make the KSP processor module aware of the module that uses the processor. Perhaps an acceptable trade-off for a local processor
e
3 submodules: • :annotation • :processor • :lib :processor can
dependencies { implementation(project(":annotation")) }
to reference it in a type-safe way, although KSP does let you look up annotations by name too :lib can
Copy code
dependencies {
    implementation(project(":annotation")) // or compileOnly
    ksp(project(":processor"))
}
p
Thank, but the 3-submodule approach doesn't address the problem, it just shifts it to depending on another module from within the lib. Unless I'm missing something!
e
why not depend on another module within the same lib? it doesn't make sense to depend on the processor, that pulls in all the KSP into your classpath, but the annotation is sensible
p
it's just I'd have to publish the annotation module to Maven Central, and I'm wondering if it can be avoided
I'm preparing a PR that shows my current idea for a workaround
e
it can be avoid for jvm but not so much the other targets…
p
☝️ exactly!
e
otherwise, just have the annotation in the lib and not in the processor. you can still look it up by name,
Copy code
resolver.getSymbolsWithAnnotation("my.annotation")
p
yes, that's my idea (see Remove dependency on unpublished KSP processor module), I just don't like that the annotation is public (needed to access it in the processor's tests), but maybe that's not a big deal. Now it's almost like publishing the separate annotation library 😄
e
also I dunno about JS/WASM but in practice compileOnly does work on native, the warning is a bit aggressive for annotations (which don't get referenced at runtime, especially if they don't have binary retention)
p
I try to support as many targets as possible in my lib, so JS/WASM support is a must
e
I dunno if it works or not
but as far as I know, it should just be a warning?
p
see my original post, and the first error (
There was a failure while executing work items
(...))
e
well that seems to be
kotlinx.benchmark
doing some additional magic and not the build itself… perhaps it has other issues
p
that may be the benchmark thing, indeed. However, it still seems weird to me that any information about KSP and the annotation (both needed in compile time) somehow survives to the runtime phase
anyway, I think I'll go with the approach of having the annotation in the lib, and referencing it via the FQN from the processor, thanks
in a spare moment, I'll try to look for a relevant YouTrack ticket or an issue in KSP, or report one - it does look like a sharp edge
e
an annotation with source retention shouldn't really be visible in the API, but binary retention and runtime retention are arguable… and it's kind of moot if compileOnly doesn't work, which forces runtime classpath to be compile classpath
👍 1
p
FWIW, I managed to decouple the processor from the lib by creating a parameter for the processor which is the FQN of the annotation. It turns out to be needed for Wasm tests on Windows where it cannot find some internal dependency 🤷 but it also feels better nevertheless