Elye Elye - 1 month ago 11
Android Question

Gradle: Can't pass argument to class in plugin

I tried as per example in, and simplified it to just "message".

class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
def extension = project.extensions.create('greeting', GreetingPluginExtension, project)
project.tasks.create('hello', Greeting) {
message = extension.message
}
}
}

class GreetingPluginExtension {
def String message = "aa"

GreetingPluginExtension(Project project) {
message = project.property(String)
}

}

class Greeting extends DefaultTask {
@Input
def String message = project.property(String)

@TaskAction
def testCoverageVerification() {
logger.quiet("Message is")
logger.quiet(message)
}
}

apply plugin: GreetingPlugin

greeting {
message = 'Hi from Gradle'
}


When I run
./gradlew -q hello
, I got

Message is
value: null


I expect it to be

Message is
value: Hi from Gradle


Why did my String from the greeting fail to pass in?

Answer Source

Actually, it's quite easy to explain. The plugin (hence the task creation and variable value assignment) is applied and evaluated before the extension block is evaluated. So the task is created even before the extension's value is set. From the link you provided:

The extension declaration in the build script as well as the mapping between extension properties and custom task properties occurs during Gradle's configuration phase of the build lifecycle. To avoid evaluation order issues, the actual value of a mapped property has to be resolved during the execution phase.

To make it work you can change the plugin declaration to this:

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        def extension = project.extensions.create('greeting', GreetingPluginExtension, project)
        project.tasks.create('hello', Greeting) {
            doFirst {
              message = extension.message
            }
        }
    }
}

However it doesn't make much sense - so don't use it ;)