https://kotlinlang.org logo
Title
m

Mustafa Ozhan

03/20/2023, 1:31 PM
is it possible to reach
libs
from
gradle/libs.versions.toml
in pre-compiled scripts located in
buildScr/src/main/kotlin
?
c

CLOVIS

03/20/2023, 1:34 PM
Yes, you have to configure your included build to access it. Here's an example with an included build in
gradle/conventions
, it's the same in
buildSrc
: https://gitlab.com/opensavvy/decouple/-/blob/110-gradle/gradle/conventions/settings.gradle.kts#L11
m

Mustafa Ozhan

03/20/2023, 1:36 PM
I have that part actually, it makes it visible in
buildScr/build.gradle.kts
that’s fine but I want to reach it also inside
buildScr/src/main/kotlin/some.name.gradle.kts
c

CLOVIS

03/20/2023, 1:37 PM
Ah, sorry. I don't know, then.
there’s a workaround in that issue
m

Mustafa Ozhan

03/20/2023, 1:38 PM
Ohh great thanks a lot Adam!
v

Vampire

03/20/2023, 2:08 PM
It's a hack-around, not a work-around. :-D
And there is a proper but stringly API to access them
m

Mustafa Ozhan

03/20/2023, 2:39 PM
Yea but works like a charm thank you 🙂
j

Javier

03/20/2023, 2:54 PM
@Vampire it is almost an official hackaround, everyone is using it hahah
v

Vampire

03/20/2023, 3:13 PM
Yep, glad I could help so many with it. :-)
m

Mustafa Ozhan

03/20/2023, 9:18 PM
it looks like this
hackaround
is still not enough to use in
plugin
block right ? I confirm that I am now able to use libs in gradle file of included build but I can not use the libs inside
plugins {…}
block, perhaps it is not integrated yet when the
plugins
block is being read. Maybe there is another
hackaround
for that too ? 😄
a

Adam S

03/20/2023, 9:58 PM
the plugins block is pretty limited, intentionally https://docs.gradle.org/current/userguide/plugins.html#sec:constrained_syntax What are you trying to do though? I suspect there might be a better way...
h

Humphrey

03/20/2023, 10:06 PM
I think you should use alias() in the plug-in block
v

Vampire

03/20/2023, 11:19 PM
Your are right that it does not work and there is no other hackaround.
He cannot use alias, as he cannot use the version catalog.
m

Mustafa Ozhan

03/21/2023, 9:11 AM
Yea, I also wanted to reach
[plugins]
from TOML file in my
build.gradle
but it seems not possible, I mean it is possible everywhere except
plugins {
   // here is not possible
}

dependencies {
   // here is possible
}
I think the reason is when the
plugins
block is applied the version catalogs are not integrated yet. I wanted to keep the name of pre-compiled plugins inside TOML file and avoid statically writing
a

Adam S

03/21/2023, 9:15 AM
yes that's true, you will have to duplicate the plugin IDs. But that's not such a big problem tbh. Either the plugin name is right, and it works, or it's wrong and Gradle will throw an error. And because precompiled-script plugins cannot specify a version in the
plugins {}
block (see docs), you have to specify the plugin version in the dependencies block in
buildSrc/build.gradle.kts
. And you can use version catalog to do that.
and you can re-use the plugin aliases in
buildSrc/build.gradle.kts
to specify the version of the external plugins
public fun DependencyHandlerScope.plugin(id: String, version: String): String =
    "$id:$id.gradle.plugin:$version"

public fun DependencyHandlerScope.plugin(plugin: Provider<PluginDependency>): Provider<String> =
    plugin.map { "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version}" }
https://www.linen.dev/s/gradle-community/t/10015775/one-feature-that-i-liked-about-buildsrc-is-that-i-could-defi#3c55229f-e2d0-4cd6-bff8-8137a717bd53
m

Mustafa Ozhan

03/21/2023, 10:45 AM
Ohh according to PR in the conversatation that you send frim gradle-community, it should be possible in gradle 8.1-RC i will try with that
v

Vampire

03/21/2023, 10:53 AM
No
m

Mustafa Ozhan

03/21/2023, 10:53 AM
v

Vampire

03/21/2023, 10:53 AM
Nothing changed in 8.1, except that you do not get an error displayed when using plugins from the version catalog in normal build scripts
You still can't use them in pre-compiled script plugins
As my hackaround cannot work there as it has preconditions that are not fulfilled for them
m

Mustafa Ozhan

03/21/2023, 10:57 AM
I think they are referring for the default
buildScr
, and your hack-around should work for that as well
v

Vampire

03/21/2023, 11:09 AM
Then you think wrong. My hackaround is for precompiled script plugins, no matter whether in an included build or
buildSrc
. That change is only about normal build script's plugins blocks.
Those where you already can use them fine without my hack around, but get an ide error displayed even though it works
m

Mustafa Ozhan

03/21/2023, 11:11 AM
Ohh right I get what you mean
a

Adam S

03/21/2023, 11:13 AM
so, in this context, there are two types of Gradle config files. Precompiled script plugins, e.g.
buildSrc/src/main/kotlin/my-project-conventions.gradle.kts
. You can't use Plugin Aliases here, and even if you could, the plugins' coordinates would have to be defined in
dependencies [}
in
buildSrc/build.gradle.kts
anyway. And regular
build.gradle.kts
files e.g. •
./build.gradle.kts
./buildSrc/build.gradle.kts
./my-cool-subproject/build.gradle.kts
. You can use plugin aliases in these since Gradle 7.3 or something. The bugfix in 8.1 is specifically about fixing an IDE warning.
m

Mustafa Ozhan

03/21/2023, 11:21 AM
Yea the one I want achieve is the first one you mentioned
buildSrc/src/main/kotlin/my-project-conventions.gradle.kts
and it seems not possible to get plugins from version catalog in
plugins
block, i just have to write it statically. We wanted to share this module as git submodule between projects and then each project could have different plugin id with same name in TOML file
a

Adam S

03/21/2023, 11:22 AM
🤯 huh
sorry, I don't mean to be rude, but that sounds quite complicated. If you were able apply a plugin from versions catalog into the plugins block of a pre-compiled script plugin, what would that help you achieve? What's your end goal?
m

Mustafa Ozhan

03/21/2023, 11:38 AM
Yes indeed it is 🙂 I am not fan of it either, it was just an idea of future structuring of the build scripts for multiple projects. It is hard to explain without a solid example but we wanted to hold all the convention scripts in shared git repo where each project could override the id of plugin in its TOML file because they are also submodule of other projects..
But the more we dig the more complicated it gets so it is not a good idea overall, anyways thanks a lot for everyone who contributes to this conversation ❤️
a

Adam S

03/21/2023, 11:42 AM
okay, so basically wanted a subproject to override a plugin ID as a form of 'scoping', so that plugin IDs don't clash?
m

Mustafa Ozhan

03/21/2023, 11:51 AM
Yea clashing is a point and also as an example some project want to use
detekt = { id = "detek-commercial" }
whereas some
detekt = {id = "detek-library" }
in their TOML file but their submodules will only use
plugins { id(libs.plugins.detekt.get().pluginId) }
in gradle, so TOML file of root project will help which scripts to be used over all submodules
a

Adam S

03/21/2023, 11:52 AM
Gotcha. I don't think such a dynamic way of loading plugins will be workable though, as you're finding out :)
m

Mustafa Ozhan

03/21/2023, 12:03 PM
actually it could be, if we were able to use libs in
plugins
block, it will allow us to create only 1 PR with 1 file into main repo, instead of creating 4-5 PRs to different repositories modifying 40-50 different build.gradle files and replacing
"detek-commercial"
to
"detek-library"
a

Adam S

03/21/2023, 12:07 PM
so
detek-commercial
and
detek-library
are two of your own convention plugins. I presume both apply Detekt, and each have some slightly different configuration based on the final product you want to build?
so for example a debug build will be less strict, and a production build will be more strict?
m

Mustafa Ozhan

03/21/2023, 12:09 PM
yes, and there are more of those scripts not only detekt and it is not for debug and release rather in-company vs client builds
a

Adam S

03/21/2023, 12:11 PM
to me that sounds like you just need one convention plugin, and in it it applies Detekt and sets configuration values dynamically using the Gradle Provider API, based on a build-time variable
m

Mustafa Ozhan

03/21/2023, 12:12 PM
It can be another workaround do you have any example for that ?
a

Adam S

03/21/2023, 12:14 PM
yup! So I did something recently in Dokka. The problem was that we wanted to run the tests using a different Java version. In CI/CD there's a GitHub matrix, so we can pass in a different Java version via an environment variable. And the Gradle config will read this variable, and dynamically change the version of Java
for convenience I made an extension that will contain all of the variables that control a Dokka build https://github.com/Kotlin/dokka/blob/e66f9d8711b5c1ba5e75fdcde8cfe998042c294a/build-logic/src/main/kotlin/org/jetbrains/DokkaBuildProperties.kt#L17-L49
I used a Gradle Property to fetch the Java Test Version, which is convenient because it can be set either via an environment variable that's prefixed with
ORG_GRADLE_PROJECT_
, or in a
gradle.properties
file, or via the command line
m

Mustafa Ozhan

03/21/2023, 12:18 PM
I think this can solve some of our needs i will check with the team thank you for sharing it 🙂
a

Adam S

03/21/2023, 12:18 PM
the DokkaBuildProperties extension is created in a base plugin that's applied to all subprojects and convention plugins, so it's always available https://github.com/Kotlin/dokka/blob/e66f9d8711b5c1ba5e75fdcde8cfe998042c294a/build-logic/src/main/kotlin/org/jetbrains/conventions/base.gradle.kts#L15
and then in the base Java convention, it uses the
testJavaLauncherVersion
variable to set the default Java launcher version for all test tasks https://github.com/Kotlin/dokka/blob/e66f9d8711b5c1ba5e75fdcde8cfe998042c294a/build-logic/src/main/kotlin/org/jetbrains/conventions/base-java.gradle.kts#L25-L31
and then because it's just a convention, subprojects can override the value if required. Which we needed to do in an integration test project, because one of the test project requires a minimum of Java 11 https://github.com/Kotlin/dokka/blob/e66f9d8711b5c1ba5e75fdcde8cfe998042c294a/integration-tests/gradle/build.gradle.kts#L22-L27
generally, it's a bit of a shift in thinking. It's the biggest difference between Maven and Gradle - composition vs inheritance. You can make Gradle behave like Maven, where there's a 'parent' and it controls everything, but that's not how Gradle works best.
m

Mustafa Ozhan

03/21/2023, 12:24 PM
Yea superficially looking it will solve some of our needs, we will give a close look definitely with a team thankfully it is public repo 🙂 Thanks a lot for sharing!
a

Adam S

03/21/2023, 12:26 PM
my pleasure! If you want to get more info, there's also a Gradle Slack that would be better suited to more general Gradle usage questions https://gradle.org/slack-invite
j

Javier

03/21/2023, 12:36 PM
you can solve that issue by not using precompiled plugins and using normal plugins tho
m

Mustafa Ozhan

03/21/2023, 12:43 PM
Yea with Adam’s approach that is also a possibility