We have several Kotlin projects built in Gradle. All projects have a common part – plugins and their configurations.
build.gradle.kts
plugins {
kotlin("jvm") version "1.9.22"
kotlin("plugin.allopen") version "1.9.22"
id("io.quarkus")
}
Generally, most of our projects have a build.gradle.kts file like this:
plugins {
kotlin("jvm") version "1.9.22"
kotlin("plugin.allopen") version "1.9.22"
id("io.quarkus")
}
repositories {
mavenCentral()
mavenLocal()
}
val quarkusPlatformGroupId: String by project
val quarkusPlatformArtifactId: String by project
val quarkusPlatformVersion: String by project
dependencies {
implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))
implementation("io.quarkus:quarkus-kotlin")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("io.quarkus:quarkus-arc")
}
group = "org.acme"
version = "1.0.0-SNAPSHOT"
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
tasks.withType<Test> {
systemProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager")
}
allOpen {
annotation("jakarta.ws.rs.Path")
annotation("jakarta.enterprise.context.ApplicationScoped")
annotation("jakarta.persistence.Entity")
annotation("io.quarkus.test.junit.QuarkusTest")
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = JavaVersion.VERSION_21.toString()
kotlinOptions.javaParameters = true
}
Everything except the dependencies {} section is boilerplate for us. Is it possible to hide these things?
I was thinking about making a plugin that would contain most of these configurations, let’s say these things:
plugins {
kotlin("jvm") version "1.9.22"
kotlin("plugin.allopen") version "1.9.22"
id("io.quarkus")
}
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
tasks.withType<Test> {
systemProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager")
}
allOpen {
annotation("jakarta.ws.rs.Path")
annotation("jakarta.enterprise.context.ApplicationScoped")
annotation("jakarta.persistence.Entity")
annotation("io.quarkus.test.junit.QuarkusTest")
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = JavaVersion.VERSION_21.toString()
kotlinOptions.javaParameters = true
}
and in our projects we will only add our plugin and the dependencies section:
plugins {
id("org.example.common-plugin-with-boilerplate")
}
dependencies {
...
}
Any tips on how to do this?
As far as I understand, I can’t just enter the common part of the configuration into build.gradle.kts in the plugin, I have to include it in the plugin code, in this section:
class CustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
val newTask = project.tasks.create("newTask") {
it.doLast {
//...
}
}
}
}
I guess I need to modify “project: Project” itself, but I have no idea how to do it.
As a starting point, I wrote two plugins that create files when the application starts. Plugin First creates fileA, plugin Second creates fileB:
class CustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
val newTask = project.tasks.create("firstTask") {//secondTask in plugin Second
it.doLast {
val resourcesDir = File(project.projectDir, "src/main/resources")
if (!resourcesDir.exists()) {
resourcesDir.mkdirs()
}
val configFile = File(resourcesDir, "fileA.txt") // fileB.txt in the plugin Second
configFile.writeText("some text")
}
}
project.tasks.named("classes") {
it.dependsOn(newTask)
it.mustRunAfter(newTask)
}
}
}
Then I wanted to add the Second plugin to the First plugin, so that by adding the First plugin to the target application, both tasks from both plugins would be launched when the application started.
But I didn’t manage to do it. If I add plugin Second to the plugins {} section in plugin First:
build.gradle.kts in plugin First
plugins {
kotlin("jvm") version "1.9.22"
`java-gradle-plugin`
`maven-publish`
id("com.org.example.second-plugin") version "0.0.1"
}
and then I add the First plugin to the plugins {} section of the target application, only one file is created when the application starts - fileA.txt. So the application only executes the task from plugin First.
I tried to add plugin Second to plugin First by declaring in fun apply(project: Project):
and declared in plugins {} :
build.gradle.kts in plugin First
plugins {
kotlin("jvm") version "1.9.22"
`java-gradle-plugin`
`maven-publish`
id("com.org.example.second-plugin") version "0.0.1"
}
Now when I add the First plugin to the application, I get an error when building:
An exception occurred applying plugin request [id: 'com.org.example.first-plugin']
> Failed to apply plugin 'com.org.example.second-plugin'.
> Plugin with id 'com.org.example.second-plugin' not found.
I also tried, instead of putting plugin Second in the plugins {} section, adding it in buildSrc:
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath("com.org.example:second-plugin:0.0.1")
}
}
but the same error remains.
Generally, I don’t know if I’m going in the right direction. It seems to me that the approach to configuring the execution of tasks from both plugins in the application may be different from the approach where I want to place plugins like
kotlin(“jvm”) version “1.9.22”
kotlin(“plugin.allopen”) version “1.9.22”
id(“io.quarkus”)
in one plugin. I will be grateful for any help.