xenomachina
(Laurence Gonsalves)
April 27, 2024, 6:39am
1
Say I have a functions that creates an ArtifactRepository:
fun RepositoryHandler.myCustomRepository(): MavenArtifactRepository {
// etc...
}
I want to use this function:
for both dependency loading and plugin loading
in my root project, all subprojects, and in buildSrc
The best I’ve found is to use settings.gradle.kts and buildSrc/settings.gradle.kts and define and use the function in four places:
settings.gradle.kts in pluginManagement
settings.gradle.kts in dependencyResolutionManagement
buildSrc/settings.gradle.kts in pluginManagement
buildSrc/settings.gradle.kts in dependencyResolutionManagement
This still requires that I have 4 copies of this code. Is there some way to define this function in ONE place, and use it in all four of these places?
Vampire
(Björn Kautler)
April 28, 2024, 12:53am
2
As pluginManagement
is executed before settings plugins are the on the class path, even a settings plugin would not help to reduce it to 1.
So the only thing that comes to mind is an init script that could do it, and thus most probably a custom Gradle distribution.
xenomachina
(Laurence Gonsalves)
April 30, 2024, 9:57pm
3
I asked this question on Stack Overflow as well, and Simon Jacobs came up with a solution that seems to work .
Here it is with a few more details filled-in:
create a settings plugin in a separate build:
// repositories/build.gradle.kts
plugins {
`java-gradle-plugin`
`kotlin-dsl`
}
dependencies {
repositories {
gradlePluginPortal()
}
}
gradlePlugin {
plugins {
create("RepositoriesPlugin") {
id = "my.repositories"
implementationClass = "RepositoriesPlugin"
}
}
}
// repositories/src/main/kotlin/RepositoriesPlugin.kt
class RepositoriesPlugin : Plugin<Settings> {
override fun apply(target: Settings) {
target.pluginManagement.repositories.pluginRepositories()
}
}
fun RepositoryHandler.pluginRepositories() {
// TODO: set up repositories here
}
fun RepositoryHandler.dependencyRepositories() {
// TODO: set up repositories here
}
in settings.gradle.kts
, in the main build do something like:
pluginManagement {
includeBuild("repositories")
}
plugins {
id("my.repositories")
}
dependencyResolutionManagement {
repositories {
dependencyRepositories()
}
}
in settings.gradle.kts
, in buildSrc/
, do almost the same thing:
pluginManagement {
includeBuild("repositories")
}
plugins {
id("my.repositories")
}
dependencyResolutionManagement {
repositories {
pluginRepositories()
dependencyRepositories()
}
}
Any code we want to share between the 4 repository locations can be in RepositoriesPlugin.kt
(once!), so we don’t have to have multiple copies of our repository setup code.
Some caveats:
The pluginManagement.repositories
for both builds (main and buildSrc) end up being the same. This is fine for our purposes. I assume a second settings plugin could be defined if these needed to be different.
The repository plugin’s build itself needs repositories set up.
I believe this is only necessary in order to get the Kotlin compiler, so perhaps this could be avoided by writing the plugin in Groovy, but I haven’t tested this.
This is a lot more circuitous than I would have expected for something I’d expect to be a pretty common need, so probably isn’t worth it unless you have sufficiently complex repository setup.