Gradle best plugin methods for tasks that depend on extension objects

I would like to receive feedback on best practices for determining plug-in tasks that depend on the external state (i.e. defined in build.gradle that refers to the plug-in). I use extension and lock objects to defer access to these settings until they are needed and available. I am also interested in sharing states between tasks, for example. Configuring the outputs of one task as inputs of another.

The code uses "project.afterEvaluate" to define tasks when the necessary settings have been configured through the extension object. This seems more complicated than necessary. If I translate the code from "afterEvaluate", it will get compileFlag == null, which is not an external parameter. If the code is modified again to use <or doLast, then it will receive an external flag ... but then it will not be able to work with the type: Exec and other similarly useful types.

I feel that to some extent I’m fighting w140>, which means that I don’t understand how best to work with him. Below is a simplified pseudo-code of what I am using. This works, but I'm looking to make sure that this can be simplified or really better methods. In addition, an exception should not be thrown if tasks are not performed.

apply plugin: MyPlugin

class MyPluginExtension {
    String compileFlag = null
}

class MyPlugin implements Plugin<Project> {

    void apply(Project project) {

        project.extensions.create("myPluginConfig", MyPluginExtension)

        project.afterEvaluate {

            // Closure delays getting and checking flag until strictly needed
            def compileFlag = {
                if (project.myPluginConfig.compileFlag == null) {
                    throw new InvalidUserDataException(
                            "Must set compileFlag:  myPluginConfig { compileFlag = '-flag' }")
                }
                return project.myPluginConfig.compileFlag
            }

            // Inputs for translateTask
            def javaInputs = {
                project.files(project.fileTree(
                        dir: project.projectDir, includes: ['**/*.java']))
            }

            // This is the output of the first task and input to the second
            def translatedOutputs = {
                project.files(javaInputs().collect { file ->
                    return file.path.replace('src/', 'build/dir/')
                })
            }

            // Translates all java files into 'translatedOutputs'
            project.tasks.create(name: 'translateTask', type:Exec) {
                inputs.files javaInputs()
                outputs.files translatedOutputs()

                executable '/bin/echo'
                inputs.files.each { file ->
                    args file.path
                }
            }

            // Compiles 'translatedOutputs' to binary
            project.tasks.create(name: 'compileTask', type:Exec, dependsOn: 'translateTask') {
                inputs.files translatedOutputs()
                outputs.file project.file(project.buildDir.path + '/compiledBinary')

                executable '/bin/echo'
                args compileFlag()
                translatedOutputs().each { file ->
                    args file.path
                }
            }
        }
    }
}
+4
1

-. , , , . -, "" , ?

SourceSets . , . JVM .

Exec @TaskAction, ( project.exec {}). @Input, @InputFiles .. @OutputFiles, @OutputDirectory .. / ( , , ).

, , , compileFlag , ( ).

, Groovy.with method.

( , -), , . ( , src/something.java), /, - -, "" ( - ). , "" . , compileFlag ( , ).

TransactTask (, , ). , , . , .

apply plugin: 'base'
apply plugin: MyPlugin

class MyTranslateTask extends DefaultTask {
    @InputFiles FileCollection srcFiles
    @OutputDirectory File translatedDir

    @TaskAction
    public void translate() {
        // println "toolhome is ${project.myPluginConfig.toolHome}"
        // translate java files by renaming them
        project.copy {
            includeEmptyDirs = false
            from(srcFiles)
            into(translatedDir)
            rename '(.+).java', '$1.m'
        }
    }
}

class MyCompileTask extends DefaultTask {
    @Input String compileFlag
    @InputFiles FileCollection translatedFiles
    @OutputDirectory File outputDir

    @TaskAction
    public void compile() {
        // write inputs to the executable file
        project.file("$outputDir/executable") << "${project.myPluginConfig.toolHome} $compileFlag ${translatedFiles.collect { it.path }}"  
    }
}

class MyPluginExtension {
    File toolHome = new File("/some/sane/default")
}

class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.with { 
            extensions.create("myPluginConfig", MyPluginExtension)

            tasks.create(name: 'translateTask', type: MyTranslateTask) {
                description = "Translates all java files into translatedDir"
                srcFiles = fileTree(dir: projectDir, includes: [ '**/*.java' ])
                translatedDir = file("${buildDir}/dir")
            }

            tasks.create(name: 'compileTask', type: MyCompileTask) {
                description = "Compiles translated files into outputDir"                
                translatedFiles = fileTree(tasks.translateTask.outputs.files.singleFile) { 
                   includes [ '**/*.m' ]
                   builtBy tasks.translateTask 
                }
                outputDir = file("${buildDir}/compiledBinary")
            }
        }
    }
}

myPluginConfig {
    toolHome = file("/some/custom/path")
}

compileTask { 
  compileFlag = '-flag'
}
+4

All Articles