Introduction
Gradle loads separately and in strict order the following scripts:
init.gradle(.kts)
settings.gradle(.kts)
build.gradle(.kts)
Separately means that different class loaders or different processes can be used. Therefore, in order to have any method or class, it must be added to the classpaths of these scripts. And if Kotlin DSL is used, code completion will be achieved.
The solution is to create a library containing the Kotlin extension and include it in the classpathes of these scripts.
Building a library
So for this we have a library containing only one class without any package:
// SomeFileName.kt
import org.gradle.api.artifacts.dsl.RepositoryHandler
fun RepositoryHandler.myRepo() {
apply {
mavenCentral() // replace with your own repository
}
}
This library should be published to your own repository. To demonstrate that this works, I used the Maven Local
repository. The build.gradle.kts
for this library looks like this:
plugins {
kotlin("jvm") version "1.9.0"
`java-library`
`maven-publish`
}
group = "my.company"
version = "1.0"
repositories {
mavenCentral()
}
dependencies {
implementation(gradleApi())
}
publishing {
publications {
create<MavenPublication>("gradleExtensions") {
from(components["java"])
}
}
repositories {
mavenLocal() // replace with your own repository like Nexus or Artifactory
}
}
Patching init.gradle.kts
The library can be included using the initscript
block:
// init.d/init.gradle.kts
initscript {
repositories {
gradlePluginPortal() // needed for some purposes
mavenLocal() // replace with your own repository
}
dependencies {
classpath("my.company:gradle-extensions:1.0")
}
}
And the myRepo()
method can now be called:
// init.d/init.gradle.kts
allprojects {
repositories {
myRepo()
}
}
Pathcing build.gradle.kts
This file can be patched using the buildscript
block. And this block can be defined both in the script itself and in init.gradle.kts
.
// build.gradle.kts
buildscript {
repositories {
mavenLocal() // replace with your own repository
}
dependencies {
classpath("my.company:gradle-extensions:1.0")
}
}
And in the init script it looks like this:
// init.d/init.gradle.kts
allprojects {
buildscript {
repositories {
mavenLocal() // replace with your own repository
}
dependencies {
classpath("my.company:gradle-extensions:1.0")
}
}
}
And the myRepo()
method can now be called:
// build.gradle.kts
repositories {
myRepo()
}
Patching settings.gradle.kts
The settings script also has its own buildscript
that can be configured in the same manner.
For example in the init script it looks like this:
// init.d/init.gradle.kts
beforeSettings {
buildscript.apply {
repositories {
gradlePluginPortal()
mavenLocal()
}
dependencies.apply {
add(ScriptHandler.CLASSPATH_CONFIGURATION, "my.company:gradle-extensions:1.0")
}
}
}
But unfortunately it doesn't work.
// settings.gradle.kts
pluginManagement {
repositories {
myRepo() // error: "Unresolved reference: myRepo"
}
}
I don't know if this is a bug or if I did something wrong. I didn't find any useful information.
But there is a workaround.
Instead of setting myRepo()
in the settings script, it can also be set globally in the init script, like this:
// init.d/init.gradle.kts
initscript {
repositories {
gradlePluginPortal() // needed for some purposes
mavenLocal() // replace with your own repository
}
dependencies {
classpath("my.company:gradle-extensions:1.0")
}
}
beforeSettings {
pluginManagement {
repositories {
myRepo()
}
}
}
I hope this works for you.
I also published working code on my github