I’m trying to create a Kotlin library project that publishes build logic so that consuming applications can use that logic. I’m following the guide and sample included here.
My structure is essentially to have multiple modules in my library that produce separate artifacts. Each project here is using the latest Gradle version 8.14. I am also using Kotlin version 2.1.21. Here is my library project structure:
sample-lib/
build-conventions/
src/main/kotlin/org/example/
application.gradle.kts (1)
common.gradle.kts (2)
library.gradle.kts (3)
build.gradle.kts (4)
settings.gradle.kts (5)
cli/
build.gradle.kts (6)
core/
build.gradle.kts (7)
settings.gradle.kts (8)
My build-conventions
module has the following build scripts:
- In
build-conventions/settings.gradle.kts
(5):
dependencyResolutionManagement {
versionCatalogs {
create("libs") { from(files("../gradle/libs.versions.toml")) }
}
}
rootProject.name = "build-conventions"
- In
build-conventions/build.gradle.kts
(4):
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
}
dependencies {
implementation(libs.kotlin.gradle.plugin)
implementation(libs.shadow.gradle.plugin)
implementation(libs.spotbugs.gradle.plugin)
implementation(libs.gradle.versions.plugin)
}
My convention plugins contain:
- In
common
(2):
plugins {
kotlin("jvm")
id("com.github.ben-manes.versions")
id("com.github.spotbugs")
}
group = project.property("group") as String
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
tasks.test {
useJUnitPlatform()
}
- In
application
(1):
plugins {
id("org.example.conventions.common")
application
distribution
id("com.gradleup.shadow")
}
- In
library
(3):
plugins {
id("org.example.conventions.common")
`java-library`
`maven-publish`
signing
}
version = project.property("version") as String
java {
withSourcesJar()
withJavadocJar()
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
}
}
}
As for my other build scripts:
- In
cli/build.gradle.kts
(6):
plugins {
id("org.example.conventions.library")
}
- In
core/build.gradle.kts
(7):
plugins {
id("org.example.conventions.library")
alias(libs.plugins.serialization)
}
- In
settings.gradle.kts
(8):
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "sample-lib"
includeBuild("build-conventions")
include("core", "cli")
Using this project structure, if I then create a sample application which includes this library via includeBuild()
and implement both core
and cli
as dependencies, I get the following warning from the Gradle build output:
The Kotlin Gradle plugin was loaded multiple times in different subprojects, which is not supported and may break the build.
This might happen in subprojects that apply the Kotlin plugins with the Gradle 'plugins { ... }' DSL if they specify explicit versions, even if the versions are equal.
Please add the Kotlin plugin to the common parent project or the root project, then remove the versions in the subprojects.
If the parent project does not need the plugin, add 'apply false' to the plugin line.
See: https://docs.gradle.org/current/userguide/plugins.html#sec:subprojects_plugins_dsl
The Kotlin plugin was loaded in the following projects: ':cli', ':core'
How can I get rid of this error? I don’t see how I can avoid applying the Kotlin Gradle plugin in core
and cli
while using my convention plugins. Simply adding apply false
in common.gradle.kts
does not make the warning go away. I’m wondering if it’s possible share Kotlin build logic at all, or if there is no way to do this and I need to apply the plugin and write related logic in each of my consumer projects (and library modules) individually?
I have attached my sample projects, both the sample library and sample application.
sample-sharing-convention-plugins-with-build-logic-nathlrowe.zip (379.4 KB)