Create custom plugin for my task


(john dafis) #1

Hi

I am looking for help in creating a custom plugin that can be reuse across projects.

I have the following task that I want to move outside the main build file.

apply plugin: 'java'

def myJavaExclusions = file('java.exclusions').readLines()
def myResourcesExclusions = file('resources.exclusions').readLines()

sourceSets {
    main {
        java { j ->
             myJavaExclusions.each { j.exclude it }
        }
        resources { r ->
            myResourcesExclusions.each { r.exclude it }
        }
    }
}

I have looked to custom plugin approach, but I am not sure how to structure the script and use it in the main gradle build file.

My plugin groovy code is as follow:

import org.gradle.api.*;

class SPL implements Plugin {
    def void apply(Project project) {
        //c4rTask task has been defined below.
        project.task('filterbuild') << {
            def myJavaExclusions = file('java.exclusions').readLines()
  
  	sourceSets {
   		main {
        	java { j ->
          	   myJavaExclusions.each { j.exclude it }
       		 }
       
    			}
		}
        }
    }
}

Can you please help with the above

Thanks
John


(Pierre) #2

Hi,

I think this is the continuation of your previous request. I suggest you to consider the approach given by @Lance here: Filter source file when copy from directory.

Should you want to continue with the exclusion approach then you first need to understand that it has nothing to do with a task. Gradle build lifecycle is divided in 3 phases: initialization, (project) configuration and (task) execution. The gradle code snippet you quote is evaluated when Gradle reads the build.gradle file, hence at the configuration phase. No task is involved here.

To wrap this configuration behavior in a custom plugin, you also need to understand that most of the lines in the gradle script are sugar coating around java methods on the Project class (apidoc).

For example:

sourceSets {
    // something ...
}

is equivalent to:

project.getConvention().getPlugin(JavaPluginConvention).sourceSets.configure({
    // configuration closure
})

That is the hardest part in my mind with Gradle: being able to link sugar coating code snippets with API elements. With these elements, we can start to write a small plugin:

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer

class SPL implements Plugin<Project> {

    @Override
    void apply(Project project) {
        // read exclusion files
        List javaExclusions = project.file('java.exclusions').readLines()
        List resourcesExclusions = project.file('resources.exclusions').readLines()
        if (!javaExclusions && !resourcesExclusions) {
            // nothing to exclude, stop here to save time
            return
        }
        // apply the java project if not already applied to ensure we have access to the JavaPluginConvention
        project.apply plugin: 'java'
        // obtain the instance of the SourceSetContainer, and the main SourceSet
        SourceSetContainer ssc = project.getConvention().getPlugin(JavaPluginConvention).sourceSets
        SourceSet main = ssc.findByName('main')
        // call the exclude method for the java and resources SourceDirectorySet objects
        javaExclusions.each(main.java.&exclude)
        resourcesExclusions.each(main.resources.&exclude)
    }
}