How to specify plugin task output which depends on extension property?


(Mike Caldwell) #1

I am writing a custom gradle plugin task and it uses a property which is passed in using the plugin extension to generate a directory name. I want the task to set a property on the project object with that generated name as the output of the task. That project property would then be used as input to tasks that are in the plugin as well and also the build script the plugin is applied to. I am having problems because the extension properties are not available at configuration time. So I do not see how I can set input/output values.

class BuildExtension {
    def outDir = ""
}

class BuildPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("tooling", BuildExtension)
        project.task('setRootDir', type: SetRootDirTask)
    }
}

class SetRootDirTask extends DefaultTask {

    SetRootDirTask() { }

    @InputFile
    def getVersionFile() {
        def f = new File("${project.tooling.outDir}/version.properties")
        return f
    }

    @TaskAction
    def action() {
        def value = null
        // Read the properties
        Properties props = new Properties()
        props.load(new FileInputStream("${project.tooling.outDir}/version.properties"))
        props.each { prop ->
            if (prop.key == "revision") {
                value = prop.value
            }
        }
        // Set the project property to hold the generated name
        project.ext.rootDirName = value
    }
}

The build script it is applied in

tooling {
       outDir = "${buildDir}"
}

   task foo {
        dependsOn setRootDir
        inputs.property("rootDirName", "${project.ext.rootDirName}")
        doLast {
        }
  }

(Chris Doré) #2

You can pass a closure or Callable to inputs.property, which will defer obtaining the value of the property till just before running the task

inputs.property( 'rootDirName', {project.ext.rootDirName} )

Another solution is to make your groovy string lazy by adding a closure {->} instead of a statement/variable.

inputs.property( 'rootDirName', "${->project.ext.rootDirName}" )

(Mike Caldwell) #3

Thanks that is just what I was looking for! Another related question. I would like the output of the task to be a property on the project. That is the value of project.ext.rootDirName which is set by the task.

Since I am a newbie to gradle, I have only seen task outputs defined as a directory or a file. Is it possible for me to specify that the task SetRootDirTask has an output which is the project.ext.rootDirName which it updates in the EXECUTION phase?