Another topic on my favorite subject Gradle Must Die
I need to do a quite trivial thing: a purely code generated module. I.e.:
there is a tool (a class with main method), written in Kotlin and deployed to maven repo as someToolLib
there is also a couple of other kotlin libraries
before any kotlin MPP compilation, a tool must be executed, with a libraryB on its classpath, to code-generate some kotlin common sources, which then have to be processed by kotlin MPP with additional dependencies.
I have spent almost a day, trying to understand what needs to be configured inside gradle to achieve this (The similar things always worked for me like a charm with Maven)
Does anybody know, what needs to be fixed in buildscript example below to make it work?
Wait, do you mean to run a class from project X, which responsibility is to generate the source code of project X? Sounds like a chicken-egg problem to me. For me it makes much more sense to separate the generator code to another module, no matter the build tool.
edit:
Ahh, sorry, xxx.yyy.MainClass is inside one of included libs, correct?
Yes, xxx.yyy.MainClass is inside one of included libs, correct?
âcorrect
If I make build.dependsOn(âcodeGenerationTaskâ) then everything works, except Kotlin compilation happens BEFORE code generation and geneared code is not compiled
This is far from anything I ever did in Gradle, but I suspect the problem is here:
val runtimeClasspath = configurations["jvmRuntimeClasspath"] + kotlin.targets["jvm"].compilations["main"].output.allOutputs //+ kotlin.targets["jvm"].compilations["main"].runtimeDependencyFiles!!
You basically say that for running the source generation you need the classpath of the current module, which includes its own sources. This is a chicken-egg. We should probably put only the dependencies into the classpath. However, I donât know how to do it and I admit Iâm making educated guesses here.
I am pretty sure that what you described is the reason, BUT:
Why configuration part, that just declares dependencies of the module, produces circular dependency between execution tasks, which must be absolutely independent???
This is one those weird things about gradle It is very badly designed. I hope this damned tool will sink in oblivion as it deserves.
This pattern (and even more comnplicated, when tool is part of multi-module project), works perfectly fine with maven, because maven is designed properly.
I donât know For me it makes perfect sense that if I put e.g. module A in a classpath of module B, then A has to be built before B, because otherwise that classpath dependency wouldnât make any sense. But I honestly donât know if this is whatâs happening here and if this is how Gradle manages task dependencies.
I would try jvmCompileClasspath instead of jvmRuntimeClasspath, because I assume when compiling we need dependencies and when running: dependencies + self code. But I would also probably start with a simple Java module and only when succeeded, move to MPP, because that common-jvm separation also adds complexity and makes debugging harder.
It worked somehow, thank you. Though I had to change the type of dependency on the toollib to âcompileOnlyâ, from âruntimeOnlyâ and it stopped pulling transitive dependencies of the tool library, so I had manually include them