Dylan Bolger
03/13/2024, 4:33 PMproject.version using a plugin I've written. Ideally, I'd like the plugin to support loading the project.version from the project.rootProject.version if one was not provided in the `project`'s build.gradle. Is there a method I can use to configure this at the correct time without using project.afterEvaluate? I'm unsure if the project needs to be evaluated before the version can be determined, or if there's a different way I should be looking to evaluate the version. I tried using project.configure(project.version, { //... } but this seems to be too early, considering the property I'd like to evaluate is still the default convention value.Dylan Bolger
03/13/2024, 4:36 PMproject.afterEvaluate to evaluate if the project.version is 'unspecified', and if it is, use the project.rootProject.version as the project.version.Dylan Bolger
03/13/2024, 4:40 PMDylan Bolger
03/13/2024, 5:03 PMProperty<Boolean> to control whether or not the convention (using the root project's version) should be used.
https://gradle-community.slack.com/archives/CA745PZHN/p1706038393743189Vampire
03/13/2024, 5:11 PMVampire
03/13/2024, 5:12 PMVampire
03/13/2024, 5:13 PMgradle.properties as then it is already set when my plugin runs and I just set my enhanced version then already.Dylan Bolger
03/13/2024, 5:27 PMgradle.properties approach, if I define a property in that file, and that file lives at the root of my project, will that property be included in all subprojects or in the root project?Vampire
03/13/2024, 5:35 PMproject.version works fine, it is backed by version from gradle.properties as long as not overwrittenAdam
03/13/2024, 6:14 PMproject.version, it will override the convention (which is version = rootProject.version).
Does that sound like it will help?Dylan Bolger
03/13/2024, 6:46 PMproject.version to append a qualifier, and any consumer of the plugin that sets a custom project.version will also need to handle appending a qualifier. Ideally we'd have the plugin do that, but that doesn't sound like it will be feasible.Vampire
03/13/2024, 6:54 PMversion not being lazy, you can probably not do much but using afterEvaluate 😞Vampire
03/13/2024, 6:54 PMAdam
03/13/2024, 7:08 PMand any consumer of the plugin that sets a custom project.version will also need to handle appending a qualifierdo you mean, for example, that you want a project to set
version = "1.2.3" and then what you're doing in an afterEvaluate is appending a qualifier? E.g. afterEvaluate { version = "${version}-qualifier" }Dylan Bolger
03/13/2024, 7:09 PMAdam
03/13/2024, 7:10 PMAdam
03/13/2024, 7:11 PM.toString() that returns the version.Adam
03/13/2024, 7:12 PM.toString() with the constructed versionAdam
03/13/2024, 7:14 PM.toString() is called, the properties can't be modified, otherwise you'll end up with a version that could be different depending on when it's queried!Vampire
03/13/2024, 7:21 PMgradle.properties to set the versionDylan Bolger
03/13/2024, 7:41 PMafterEvaluate (for getting the qualifier on the custom project.version), so that's what I'll stick to. I've found the specific GitHub issue for getting project coordinates (including version and group ) using providers here: https://github.com/gradle/gradle/issues/13672Dylan Bolger
03/13/2024, 7:53 PMVampire
03/13/2024, 8:24 PMafterEvaluate as part of the approaches is, that the consumer sticks to the set rules, that is does not set project.version manually, but either configure the property on the extension (could even be a field on poject.version instead, but then you need to cast to set it) or set it in gradle.properties, depending on approach.Dylan Bolger
03/13/2024, 8:30 PMVampire
03/13/2024, 9:34 PMafterEvaluateVampire
03/13/2024, 9:35 PMafterEvaluate himself to set the version and thus again undo what the plugin didVampire
03/13/2024, 9:35 PMafterEvaluateDylan Bolger
03/14/2024, 2:04 PMrepositories were used in a project, what would be the best time to evaluate that?Dylan Bolger
03/14/2024, 2:05 PMVampire
03/14/2024, 2:08 PMIf I wanted to control whatwere used in arepositories, what would be the best time to evaluate that?project
repositories is a RepositoryHandler which is a DomainObjectCollection so you probably can use .configureEach or .all to check.Vampire
03/14/2024, 2:10 PMI've noticed that evaluating extensions properties inside of task configuration seems to be a good time to configure defaults for tasks.Depends on what you mean by "evaluating". As I wrote in the forums, using
get() on a property is not a good idea, as this still can easily be done too soon.
Better wire properties to properties or evaluate them only at execution time.
Whenever you request their value at configuration time, you void the advantages and again introduce ordering problem / timing problems / race conditions.Dylan Bolger
03/14/2024, 2:14 PMget() has been to set defaults for a wider-scope than individual properties. For example, one property we have is enableDefaultEncoding, which sets up encoding for any JavaCompile task and the 'javadoc' task specifically. In hindsight though, maybe the better approach for this one specifically would be to set up the property as a Property<String> , that way it can be configured without using multiple configurations (disabling the boolean property, and then setting up their own encoding).Dylan Bolger
03/14/2024, 2:15 PMJavaPluginExtension defaults, we want to have withSourcesJar() and withJavadocJar() by default.Vampire
03/14/2024, 2:17 PMDylan Bolger
03/14/2024, 2:17 PMwithoutSourcesJar()?Vampire
03/14/2024, 2:26 PMDylan Bolger
03/14/2024, 2:34 PMEasiest for that is to not use a property, but a function in the extension that does this configuration changeWas this referring to the default encoding or the JavaPluginExtension?
Vampire
03/14/2024, 2:40 PMwithSourcesJar() and withJavadocJar(), as there is not a setting you need to change or a property you can wire, but some method you need to call.Vampire
03/14/2024, 2:40 PMVampire
03/14/2024, 2:42 PMProperty-enabled (hopefully changes with the big provider migration in Gradle 9), there is not really a good point in time where you evaluate a Property to set it.
So maybe better either have a function in the extension or a separate convention plugin for the different options.Vampire
03/14/2024, 2:45 PMmy.convention.default.encoding.utf8 that sets everything to UTF-8 immediately.
And a my.convention.custom.default.encoding that provides an extension with a function that you can call with an encoding that sets it.
Or you just set it to the default and provide the function that the consumer can call to change it to something else.
Probably no need for two plugins here.Dylan Bolger
03/14/2024, 3:19 PMget(), you're suggesting we instead make a function that lives inside the Extension class, that does the action for us, i.e:
Boolean myFlagToDoSomething = true // The convention is that this is true
void disableMyFlagToDoSomething() {
myFlagToDoSomething = false
}
And then at the time it's needed, check the value of extension.myFlagToDoSomething?Dylan Bolger
03/14/2024, 3:24 PM// Extension implementation
abstract Property<Boolean> htmlRequired
// Plugin implementation
// For example, the JacocoReportsContainer has a Property `html.required`
project.tasks.named('jacocoTestReport', JacocoReport).configure {
reports.html.required = extension.htmlRequired
}Vampire
03/14/2024, 3:30 PMvoid produceAuxilaryJars() {
....withSourcesJar()
....withJavadocJar()
}Dylan Bolger
03/14/2024, 3:32 PMproject correct?Vampire
03/14/2024, 3:32 PMVampire
03/14/2024, 3:33 PMabstract class MyExtension : ExtensionAware {
@get:Inject
abstract val project: Project
...
}Dylan Bolger
03/14/2024, 3:34 PMproject.objects into the constructor of the Extension class, so that should be a quick swap.Vampire
03/14/2024, 3:40 PMObjectFactory as usually you can just leave the stuff abstract and let Gradle provide the implemenations like
interface MyExtension : ExtensionAware {
val myProperty: Property<String>
}
or
abstract class MyExtension : ExtensionAware {
abstract val myProperty: Property<String>
}Dylan Bolger
03/14/2024, 3:55 PMimplements ExtensionAware and using @Inject on the project but that doesn't seem to work.Dylan Bolger
03/14/2024, 3:58 PMProject project
MyExtension(Project project) {
this.project = project
ObjectFactory objectFactory = project.objects
}
And then I can use the extensions.create method without providing any ...constructionArgumentsVampire
03/14/2024, 4:04 PMabstract class MyExtension implements ExtensionAware {
@Inject
abstract Project project
@Inject
abstract ObjectFactory objectFactory
}
or something like that should work just fineVampire
03/14/2024, 4:04 PMVampire
03/14/2024, 4:04 PMVampire
03/14/2024, 4:05 PMabstract class MyExtension implements ExtensionAware {
@Inject
abstract Project getProject();
@Inject
abstract ObjectFactory getObjectFactory();
}Vampire
03/14/2024, 4:05 PM