Caleb Cushing
10/31/2024, 1:47 PMGabriel Feo
10/31/2024, 2:16 PMThomas Broyer
10/31/2024, 2:25 PMGabriel Feo
10/31/2024, 2:47 PMThomas Broyer
10/31/2024, 3:05 PMVampire
10/31/2024, 3:10 PMMartin
10/31/2024, 3:10 PMPlugin::apply ?
require(gradleVersion >= minVersion)Martin
10/31/2024, 3:11 PMVampire
10/31/2024, 3:11 PMCaleb Cushing
10/31/2024, 3:12 PMVampire
10/31/2024, 3:12 PMVampire
10/31/2024, 3:12 PMMartin
10/31/2024, 3:19 PMThomas Broyer
10/31/2024, 3:19 PMadditionally reduced complexity in your codeYou're trading an imperative if/throw (2 LoC) in the plugin with an additional publication attribute (slightly more than 2 LoC in your build file).
Martin
10/31/2024, 3:22 PMif(gradleVersion > versionWhereTHeAPIWasIntroduced) {} .Caleb Cushing
10/31/2024, 3:22 PMPlugin::apply is "business logic", in theory gradle could stop an upgrade/downgrade from ever happening. Checking versions shouldn't be part of my business logic unless my plugin deals specifically with versions. Also for certain complexity metrics in increases the likelyhood of failure, and I do use checkstyles complexity metric checks.
Essentially that check doesn't really have anything to do with my plugins functionality. In the same way that java's bytecode doesn't, but it might affect a consumerThomas Broyer
10/31/2024, 3:24 PMKGP publishes several variantsYes, Kotlin and Spring Boot (since 3.2.6 up to 3.3.x: https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-gradle-plugin/3.3.5/spring-boot-gradle-plugin-3.3.5.module) publish variants. Does any plugin uses the attribute only to replace the version check in the code though?
Thomas Broyer
10/31/2024, 3:26 PMThomas Broyer
10/31/2024, 3:28 PMCaleb Cushing
10/31/2024, 3:31 PMCaleb Cushing
10/31/2024, 3:32 PMThomas Broyer
10/31/2024, 3:34 PMbuildSrc/ build apparently adds the attribute to its configurations, but not in subprojects, and included builds that people use as an alternative to buildSrc won't add it automatically, so I'd say many people don't actually resolve plugins using that attribute (unless they depend on a plugin that specifically publishes several variants –see all those matches in the code search link shared above, to resolve the Kotlin or Spring Boot plugins–, as they need a mean of selecting the appropriate variant).Martin
10/31/2024, 3:36 PMMartin
10/31/2024, 3:36 PMMartin
10/31/2024, 3:37 PMMartin
10/31/2024, 3:37 PMephemient
10/31/2024, 3:44 PMephemient
10/31/2024, 3:46 PMMartin
10/31/2024, 3:46 PMbuild-logic so I think it'll also use the "default" one for resolutionVampire
10/31/2024, 3:47 PMIf your plugin is compatible with some Gradle 6.x versions, the attribute won't work.
That's not correct. You can for example have one variant that is used for >7 and from 7 on you can have variants where your like, one for 7+, or one for 7-8 and one for 9+, or one for 7 one for 8 one for 9+, ... If your support many different Gradle versions and the plugin is a bit more complex, you can end up with many version checks and code separated in different classes for different versions, or reflection used for some parts and so on. And there using variants can indeed greatly reduce complexity, increase maintainability, increase testability, and reduce error proneness. As a simple replacement for a minimum version check it can be used, but is not that much different. Mainly matter of taste.
but not in subprojects, and included builds that people use as an alternative to buildSrc won't add it automatically, so I'd say many people don't actually resolve plugins using that attribute
Iirc this is not true. It probably is the plugin development plugin that adds the attribute and that you typically will have applied when your develop a plugin.
Vampire
10/31/2024, 3:49 PMMartin
10/31/2024, 3:52 PMprintln("KGP is at " + KotlinMultiplatformPluginWrapper::class.java.protectionDomain.codeSource.location.toString())
KGP is at file:/Users/martinbonnin/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-gradle-plugin/2.0.20/5ca90c0173fffe0f4e9b73aca425fd99213cc43a/kotlin-gradle-plugin-2.0.20-gradle85.jar
So it does seem to work 👍Martin
10/31/2024, 3:53 PMMartin
10/31/2024, 3:55 PMbuild-logic:compileClasspathMartin
10/31/2024, 3:55 PMVampire
10/31/2024, 3:55 PMVampire
10/31/2024, 3:57 PMephemient
10/31/2024, 3:57 PMephemient
10/31/2024, 3:58 PMMartin
10/31/2024, 3:59 PMbuild-logic knows that my compileClasspath is the one of a Gradle plugin?ephemient
10/31/2024, 4:00 PMplugins { id("build-logic") } doesMartin
10/31/2024, 4:01 PMbuild-logic could very well be a completely standalone buildMartin
10/31/2024, 4:02 PMorg.gradle.plugin.api-version attribute?Martin
10/31/2024, 4:02 PMephemient
10/31/2024, 4:04 PMMartin
10/31/2024, 4:05 PMMartin
10/31/2024, 4:09 PM// build.gradle.kts
val configuration = configurations.create("test")
configuration.dependencies.add(dependencies.create("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21"))
println(configuration.files.filter { it.name.contains("kotlin-gradle-plugin-2.0.21") })
It prints this out:
.../kotlin-gradle-plugin-2.0.21-gradle85.jarMartin
10/31/2024, 4:10 PM"test" configuration, looks like org.gradle.plugin.api-version is set (because it knows I'm running Gradle >= 8.5)Martin
10/31/2024, 4:10 PMMartin
10/31/2024, 4:11 PM.../kotlin-gradle-plugin-2.0.21-gradle82.jar
which is somewhat consistent.Martin
10/31/2024, 4:13 PMorg.gradle.plugin.api-version to the current Gradle version because a configuration in general can be used in very different places. But ABI is the same and it's all working so all good, just a bit suprising IMOVampire
10/31/2024, 4:25 PMbuildSrc or applied the java-gradle-plugin.Vampire
10/31/2024, 4:27 PMdependencyInsight taskMartin
10/31/2024, 4:30 PM$ ./gradlew dependencyInsight --configuration test --dependency "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21"
> Task :dependencyInsight
org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21 (by constraint)
Variant gradle82RuntimeElements:
| Attribute Name | Provided | Requested |
|--------------------------------|--------------|-----------|
| org.gradle.category | library | |
| org.gradle.dependency.bundling | external | |
| org.gradle.jvm.environment | standard-jvm | |
| org.gradle.jvm.version | 8 | |
| org.gradle.libraryelements | jar | |
| org.gradle.plugin.api-version | 8.2 | |
| org.gradle.status | release | |
| org.gradle.usage | java-runtime | |Martin
10/31/2024, 4:30 PMMartin
10/31/2024, 4:30 PMMartin
10/31/2024, 4:30 PMMartin
10/31/2024, 4:31 PM| org.gradle.plugin.api-version | 8.5 | |Martin
10/31/2024, 4:31 PMVampire
10/31/2024, 4:34 PMVampire
10/31/2024, 4:35 PMThomas Broyer
10/31/2024, 4:37 PM> If your plugin is compatible with some Gradle 6.x versions, the attribute won't work.
That's not correct.I was talking about using the attribute as a "version check" in a case where you have a single variant; in this case the attribute "won't work" as setting its value to e.g. "6.8" won't prevent Gradle 6.5 to resolve the plugin. If your plugin supports Gradle < 7, then you have no choice but to use an if/throw in your plugin's code.
Martin
10/31/2024, 8:06 PMMartin
10/31/2024, 8:10 PMorg.gradle.plugin.api-version in my libraries 😈Thomas Broyer
10/31/2024, 8:22 PMThere's a disambiguation rule that is installed for each configuration (not 100% sure about that part but it sure does look like it)A disambiguation rule is linked to the attribute (as declared in the attribute schema), so it's used for each and every resolution (i.e. each configuration)
Martin
10/31/2024, 8:23 PMMartin
10/31/2024, 8:25 PMMartin
10/31/2024, 8:26 PMThomas Broyer
10/31/2024, 8:36 PMephemient
10/31/2024, 8:46 PMephemient
10/31/2024, 8:48 PMVampire
10/31/2024, 9:05 PMAlright, I think I got down to this rabbit hole. Magic is happening hereAh, right, of course. 🙈 Compatibility rules only kick in if both sides (consumer and producer) have a value set. But disambiguation rules are also used if the attribute is not requested but multiple variants provide different values.
There's a disambiguation rule that is installed for each configuration (not 100% sure about that part but it sure does look like it) and that will select the highest possible variantNot on each configuration as they are not bound to configurations. They are added to the attribute matching strategy of the attribute schema which is directly on the whole
DependencyHandler.
the only case where the disambiguation rule won't be used is if you request with the exact same value as a variant; the rule will otherwise select the variant with the highest value that's lower than the requested valueNot exactly, if the documented algorithm is really like written there. It says
1. Each candidate’s attribute value is compared to the consumer’s requested attribute value. A candidate is considered compatible if its value matches the consumer’s value exactly, passes the attribute’s compatibility rule or is not provided.So even when requesting the exact attribute you should still get that and all higher ones as candidates and the disambiguation rule will then pick the closest match. Unless I misread the algorithm description or it is incorrect of course. 😄 So I think it would even be used if there is an exact match as long as there is also an inexact match.
I was expecting it to be applied in buildscripts and plugin builds onlyThat the attribute is requested is only in build scripts and plugin builds. But the disambiguation rule is always configured and used, yes. Like JVM attributes are always added to the schema with their compatibility and disambiguation rules if the
jvm-ecosystem plugin is applied,
Gradle-related attributes are always added to the schema with their compatibility and disambiguation rules if Gradle is involved, so always. 😄Martin
10/31/2024, 9:25 PMVampire
11/01/2024, 12:12 AMGabriel Feo
11/01/2024, 12:01 PMMartin
11/01/2024, 6:27 PMCaleb Cushing
11/01/2024, 6:32 PMMartin
11/01/2024, 6:33 PMMartin
11/01/2024, 6:33 PMCaleb Cushing
11/01/2024, 6:34 PMMartin
11/01/2024, 6:35 PMCaleb Cushing
11/01/2024, 6:39 PMCaleb Cushing
11/01/2024, 6:39 PM