Is it possible to query the values of Gradle extension settings during the “apply” phase? This is best illustrated with this example build.gradle where I want to access the “greeting.name” value in the apply() method:
apply plugin: GreetingPlugin
greeting {
message = "Hi from closure"
name = "Fred"
}
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
// Add the 'greeting' extension object
project.extensions.create("greeting", GreetingPluginExtension)
// Attempt to use the provided name during the "apply" phase
if (project.hasProperty('greeting.name')) {
println "We have a name provided : ${project[greeting.name]}"
} else {
println 'No name found'
}
// Add a task that uses the configuration
project.task('hello') << {
println "${project.greeting.message} and your name is ${project.greeting.name}"
}
}
}
class GreetingPluginExtension {
String message = 'Hello from GreetingPlugin'
String name = 'Unknown'
}
The output is as follows
$ gdl -q hello
No name found
Hi from closure and your name is Fred
Notice the No name found message - I can’t seem to be able to extra the name property (set to “Fred”) during the extension apply() phase. How can I query project extension settings and make decisions based on their values while the plugin is being applied?
Note: I found this related question but I want to know if there is a better way orther than project.afterEvaluate.
You should read about the new rules based plugin model. This is how issues like this are addressed in the new style plugins for Gradle. There are examples of plugins using the rules based model in the distribution samples.
Look at the example under samples/modelRules/basicRuleSourcePlugin
Thanks for the tip - I will read through that for our own plugins. Do you have any suggestions on how to do this with the older extension based plugin model?
Background
The issue I’m describing is for a contribution I’m making to a 3rd party plugin that I can’t convert to the rules based plugin model in the short term.
The afterEvaluate hack is the only viable trick I can think of. If the example you posted is close to what you are trying to do I see no reason for the afterEvaluate to not work.
It is too bad you cannot do the conversion. I have done such conversions on my own and 3rd party open source plugins successfully and I can attest that it is a much better model for making plugins.
I just looked at the plugin you mentioned, this plugin needs to operate mostly in the apply stage because it interfaces with the dependency resolution. Things that rely on the resolved dependencies may fail if you do things lazily in afterEvaluate. I am not sure what you are trying to change in the dependency-lock plugin but it would be a hard one to make work with the rules based model.
One way that is possible to use here is to require the extension to be created by the build script author prior to calling “apply plugin” in the build script. Then you change the call to project.extension.create to be project.extension.maybeCreate which will use the extension created in build.gradle instead of adding a new instance.
You can see a similar approach in the dependency-lock plugin source with the DependencyLockCommitExtension handling. This plugin allows the extension to exist prior to the call to apply.
The item I’m trying to change in the gradle-dependency-lock-plugin is described in issue 80. If you have any hints then that would be greatly appreciated.
I will also look at the creating the extension prior to calling “apply plugin” using DependencyLockCommitExtension as an example.