question to KGP developers I think :slightly_smili...
# gradle
o
question to KGP developers I think 🙂 Looks like from 1.9.20 it will not be allowed to add
dependsOn
of
commonMain/commonTest
to some other source set (as from what I’ve found in current master branch on GitHub) What would be a suggestion on how to provide autogenerated code which should be accessible from
commonMain
? The question is for
ffi-kotlin
where I would want to generate some code with bindings (for different platforms) and then attach it to specific source sets/compilations F.e. for project with 2 targets (like jvm and macosArm64) I would want: 1. generate
common
code with
expect
functions/classes and make it accessible from
commonMain
2. generate
jvm
specific code which will actualise those
expects
and maybe add some new declarations - should be accessible from
jvmMain
3. generate
macosArm64
specific code - same as for
jvm
In comparison to how
cinterop
do it, I would want not to declare dependency on some generated klib, but link directly sources, at least to be able to mark some of those declarations
internal
in generated code, so they will be accessible inside sourceSets in module, but not outside. I found, that it’s possible to create separate compilation in platform targets, and associate
main
compilation with created one - it works, and I can access external
internal
declarations inside
jvmMain
(IDEA don’t like such code, but compilation works) - but it’s not possible to add additional
metadata
compilation, so in the end it doesn’t work for my use-case Of course it’s possible to just directly add those sources to
commonMain
sourseSet, like
sourceSets.commonMain.get().kotlin.srcDir("PATH")
- But Im not sure it’s a good idea, as those sources are mutable by anyone, and could be easily replaced by some other plugin or even by user, when she prefer to use other convention to sources folders Note: those declarations of course should be accessible after publication to library consumers
what I originally tried to do is to do something like this:
Copy code
kotlin {
    // applied by default via KGP from 1.9.20 (with different API)
    targetHierarchy.default()
    // will be applied in foreign plugin, could be not default, but here it's ok
    targetHierarchy.default {
        sourceSetTrees(KotlinTargetHierarchy.SourceSetTree("libcrypto"))
    }
    jvm {
        compilations {
            val main by getting
            val libcrypto by creating
            main.associateWith(libcrypto)
        }
    }
    macosArm64 {
        compilations {
            val main by getting
            val libcrypto by creating
            main.associateWith(libcrypto)
        }
    }
    macosX64 {
        compilations {
            val main by getting
            val libcrypto by creating
            main.associateWith(libcrypto)
        }
    }
    linuxX64 {
        compilations {
            val main by getting
            val libcrypto by creating
            main.associateWith(libcrypto)
        }
    }
    metadata {
        compilations.all {
            println("${target.name} -> ${name} -> ${defaultSourceSet.name} -> ${defaultSourceSet.dependsOn.map { it.name }}")
        }
    }
}
And for platform compilations, everything works But no new intermediate
metadata
compilations were created and there is no association in intermediate sources
Should I convert this to YouTrack issue, or is it something, that is not expected to support at all?
m
@tapchicoma could you please have a look?
a
cc @Sebastian Sellmair [JB]
s
I am sorry, I did not really deep dive into the details yet. Can you try to wire your generated source code into corresponding source sets directly? So if you generate ‘root’ expects then add them to commonMain as srcDir?
o
Yeah, that’s how I would do it now (mentioned it in the end of original message), but because this code will be in gradle plugin, it’s not future proof, as user or other
plugin
could easily just replace
srcDir
with
setSrcDirs
- and generated bindings will be lost. Use case for replacing default
srcDirs
which I know is to f.e. change directory layout from
src/commonMain/kotlin
to f.e.
common/src
(like in kotlinx.* repositories) or because any other different from default convention for sources. And AFAIK there is no really strait forward way to know when this replacement will be called (in other gradle plugin or in user script or in some convention plugin)
s
I see! So you need some kind of ‘safe’ way of adding sources that can not be easily remove by accident from the user (or another plugin the user uses)
But other than this concern, the approach would work fine for you?
o
Overall, yes The only other concern that I have is incremental compilation - in case we have a lot of generated declarations and we will add them directly to source set - this will cause all those declarations to recompile when not generated code changes. It should not be an issue for JVM and JS, where incremental compilation is implemented, but could increase K/N compilation time significantly where AFAIK there is no yet incremental compilation So IMO, separate compilation (or some other abstraction) for generated code would be better - also as some kind of separation of concerns
s
This is OK, there will be effectively no difference from my point of view in compilation speed here ✅
o
Then, yes, it should be fine for me to just add sources to srcDir - I will start using that approach and will come back if I will found any other issues, that I haven’t spotted yet I could also create an YouTrack issue for “safe srcDir” replacement if needed with this use case Also, I think, KSP should need similar capabilities when it will fully support generation of common code: https://github.com/google/ksp/issues/567