Hi Gradle Community! I would be grateful for some ...
# community-support
j
Hi Gradle Community! I would be grateful for some help on applying one convention plugin inside another one while using in included "build-logic" build and the type-safe accessors from
LibrariesForLibs
. Will post in thread to not clutter the main channel.
We are just starting up what will become a quite large mono repo for some back-end applications, and I'm preparing some convention plugins. Starting out, I'm creating one
kotlin-conventions
plugin that all sub projects will use, and one
quarkus-conventions
that a few of them will use in addition. One of the things I have put in the
kotlin-conventions
plugin is Detekt. However, when testing with some dummy code, Gradle warned me that the task
detektMain
must depend on the task
compileQuarkusGeneratedSourcesJava
. That task is of course in the
quarkus-conventions
plugin, so my first thought was to apply the
kotlin-conventions
plugin inside of the
quarkus-conventions
plugin to get a hold of the
Detekt
task type. But since I like the type-safe accessors that the "`LibrariesForLibs` work-around" provides, I use that in both conventions plugins, which then gives me the error
"Extension of type 'LibrariesForLibs' does not exist"
when I try to apply the
kotlin-conventions
plugin inside of the
quarkus-conventions
plugin... Is there a way to solve this, so that the
LibrariesForLibs
extension gets "carried over" from one convention plugin to the other to make this work? Or maybe this whole approach is suboptimal and I should structure these conventions in another way? 😉 The most relevant files pasted below, and further down a zipped MCVE.
Copy code
./gradle/build-logic/kotlin-conventions/src/main/kotlin/kotlin-conventions.gradle.kts

import org.gradle.accessors.dm.LibrariesForLibs

plugins {
    kotlin("jvm")
    id("io.gitlab.arturbosch.detekt")
}

val libs = the<LibrariesForLibs>()

dependencies {
    implementation(libs.kotlin.logging)
}

kotlin {
    jvmToolchain(21)
}

detekt {
    buildUponDefaultConfig = true
}
Copy code
./gradle/build-logic/kotlin-conventions/build.gradle.kts

plugins {
    `kotlin-dsl`
}

repositories {
    gradlePluginPortal()
}

dependencies {
    implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
    implementation(libs.kotlin.gradle.plugin)
    implementation(libs.detekt.gradle.plugin)
}
v
I'm not sure whether my hack-around could work in that situation, could quite be that it is not. One thing to consider though is, that adding an explicit dependency between those tasks is almost always the wrong thing to do anyway.
Whenever you do an explicit
dependsOn
where on the left-hand side is not a lifecycle task, you are most probably doing something wrong, and the suggested solutions by the Gradle finding are usually the wrong thing to do but only symptom treatment like calling
Platform.runLater
to "fix" a GUI problem.
You most probably did not properly register the task generating source files as source dir but instead configured the path manually as source dir or something like that.
This then makes each and ever consumer of source files like sources jar, compilation, static code analyzers and so on miss the necessary task dependency.
If the code generation task is properly declaring its output files like any task should, then you would directly configure that task (or a provider thereof) as
srcDir
which makes its outputs be treated as source files, automatically getting necessary task dependencies implicitly.
j
Thank you so much for the feedback! Ok, so this points in reality to another problem. I need to read up on source dirs, haven't grasped that subject yet with Gradle. If you have the time, would taking a look at the MCVE make it possible to point out where a "source dir configuration" is needed? (Need to add plugin repository, doing this on my work computer where company-specific repo is specified in my home catalogue)
v
Btw. I thought about it, I think my hack-around will not work if you apply one precompiled Kotlin DSL script plugin from another. To generate type-safe accessors for quarkus-conventions the plugins block is extracted and applied to a dummy project, then this is investigated to know which accessors to generate to compile the remaining script. But in this dummy project the extension you try to get in the kotlin conventions plugin is not available, thus it fails with that error.
And regarding the other question, I have no idea, you probably have to ask Quarkus how to do it or to fix their plugin. Seems they are doing all sorts of bad-practice
dependsOn
and
mustRunAfter
instead of properly wiring things together, resulting in that issue. 🤷