How to parameterize the apply method of a gradle plugin

When developing a Gradle plugin, is it possible to give some information to the apply() method except of setting some project property before applying the plugin? e. g. uses two property names that could easily clash with existing property names. I’d like to make those property names configurable. But adding a convention object is probably worthless, as you would first have to apply the property to have the convention object to manipulate and then the apply method is already through. Is there any clean gradle-like way to solve this?

The only two things that come to my mind right now are to either set a project property before applying the plugin or to add another plugin that adds the convention object and then first this plugin has to be applied, then the convention object configured and then the main plugin applied. But I hope for a better option I don’t see.

If there is no clean way, I’d like to suggest a change in Gradle, that allows to give parameters to the apply method when applying a plugin, something like

apply plugin: ‘properties’, parameters: [‘foo’, ‘bar’]

which will not invoke the “apply(Project)” method in the plugin, but an apply method with more parameters.

Plugin application can’t be parameterized. Instead, the way to do this is for the plugin to extend the build model via an extension. Currently, access to the extension from the plugin has to be deferred to solve the ordering problem you mentioned. In the future, there will likely be a better way to cope with this. For more information on extensions, see the Gradle User Guide and the samples in the full Gradle distribution.

Actually extension was what I meant with “convention object” (What is a convention object then? :-/ ) But in this specific case the problem is, that the access to the extension cannot be deferred. To when should it be deferred? The plugin is supposed to read properties and set them on the project to configure the build, so this can hardly be deferred to later on.

It’s a common problem, and there are various techniques to deal with it. One of them, which I think is also shown in the samples, is to defer to the end of the configuration phase by wrapping code with ‘afterEvaluate { … }’.

I know afterEvaluate or taskGraph.whenReady, but that is too late for this use-case. The project properties should be loaded before the remaining configuration takes place as it might already use those properties.

Gradle’s own plugins achieve this via convention mapping. Be advised that this isn’t a public feature, and will be replaced at some point.

Hm, is this about a convention object then? How would that work?

Convention mapping is not related to convention objects (and the latter have been replaced by extension objects). As convention mapping isn’t a public feature, it isn’t documented, but you check out the Gradle source code (e.g. the code quality plugins) or previous questions here or on Stack Overflow. And keep in mind that convention mapping while go away at some point.

Ah, ok. Thanks. :slight_smile:

The documentation should be updated then, the Userguide mentions convention objects in many places still.

And the Userguide has a chapter 37.6. in the ToC with an empty header text and down in the chapter, no 37.6. is present.

When convention mapping will go away, can you say whether it will be replaced by something appropriate?

Hm, no, convention mapping is also not what would help me here I think.

I think currently there are really only the two alternatives

  • depend on a property being set before the applying of the plugin - add another plugin that adds an extension, apply that plugin before the existing plugin, configure the extension before applying the existing plugin

So to get this clean, I think my suggestion to be able to parameterize the apply method in the original comment stays. :slight_smile:

At the end of the day, parameterization of a plugin is a limited way to solve ordering problems. These need to be solved in a better way. Currently, convention mapping is the best way, but it will be replaced by something better at some point.

So you still think convention mapping would help in this situation? Then I probably didn’t get it right. I need to somehow give the apply method some input from the build script. The work that uses this input cannot be deferred to a later stage in this case, but must be done at the time the plugin is applied.