Gradle Goodness: Adding Custom Extension To Tasks
We can add extensions to our project in Gradle to extend the build script with extra capabilities. Actually we can add extensions to any object in Gradle that implements the ExtensionAware
interface. The Task
interface for example extends the ExtensionAware
interface so we can add custom extensions to Gradle tasks as well. Inside a task configuration we can then use that extension.
In the following build script we use a custom extension for JavaCompile
tasks to configure the compiler -Xlint
arguments. The extension is added via the plugin com.mrhaki.gradle.JavaCompilerLintPlugin
. First we take a look ate the extension class. This is a POGO for configuring the compiler arguments with -Xlint
options:
// File: buildSrc/src/main/groovy/com/mrhaki/gradle/JavaCompilerLintExtension.groovy
package com.mrhaki.gradle
/**
* Extension class for use with JavaCompile tasks
* to set -Xlint options.
*/
class JavaCompilerLintExtension {
Boolean cast
Boolean classfile
Boolean deprecation
Boolean depAnn
Boolean divzero
Boolean empty
Boolean fallthrough
Boolean finallyblocks
Boolean options
Boolean overrides
Boolean path
Boolean processing
Boolean rawtypes
Boolean serial
Boolean staticref
Boolean tryblocks
Boolean unchecked
Boolean varargs
void enableAll() {
cast = true
classfile = true
deprecation = true
depAnn = true
divzero = true
empty = true
fallthrough = true
finallyblocks = true
options = true
overrides = true
path = true
processing = true
rawtypes = true
serial = true
staticref = true
tryblocks = true
unchecked = true
varargs = true
}
/**
* Create list of compiler -Xlint arguments.
*
* @return List of -Xlint compiler arguments.
*/
List asCompilerArgs() {
final List optionArgs = []
optionArgs << optionArg('cast', cast)
optionArgs << optionArg('classfile', classfile)
optionArgs << optionArg('deprecation', deprecation)
optionArgs << optionArg('dep-ann', depAnn)
optionArgs << optionArg('divzero', divzero)
optionArgs << optionArg('empty', empty)
optionArgs << optionArg('fallthrough', fallthrough)
optionArgs << optionArg('finally', finallyblocks)
optionArgs << optionArg('options', options)
optionArgs << optionArg('overrides', overrides)
optionArgs << optionArg('path', path)
optionArgs << optionArg('processing', processing)
optionArgs << optionArg('rawtypes', rawtypes)
optionArgs << optionArg('serial', serial)
optionArgs << optionArg('static', staticref)
optionArgs << optionArg('try', tryblocks)
optionArgs << optionArg('unchecked', unchecked)
optionArgs << optionArg('varargs', varargs)
// filter null values.
final List compilerArgs = optionArgs.findAll()
return compilerArgs
}
/**
* Create -Xlint compile option if option is set.
*
* @param name Name of the -Xlint compile option.
* @param enable Set option argument as -Xlint:option if true, otherwise as -Xlint:-option if false.
* @return Null if enable is null, otherwise a valid -Xlint compiler option.
*/
private String optionArg(final String name, final Boolean enable) {
if (enable != null) {
final String option = enable ? name : "-$name"
return "-Xlint:$option"
}
return null
}
}
Next we have a plugin class that registers the extension with the name lint
on all JavaCompile
tasks in our project:
// File: buildSrc/src/main/groovy/com/mrhaki/gradle/JavaCompilerLintPlugin.groovy
package com.mrhaki.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.compile.JavaCompile
/**
* Plugin for applying a custom extension to
* JavaCompile tasks for configuring the
* -Xlint options.
*/
class JavaCompilerLintPlugin implements Plugin<Project> {
void apply(final Project project) {
// For all JavaCompile tasks we add
// a custom extension with the name lint
// for configuring -Xlint options.
project.tasks.withType(JavaCompile) { task ->
// Let Gradle create a new extension.
// Users can configure a compile task
// from the Java plugin like:
// compileJava {
// lint {
// cast = true
// }
// }
JavaCompilerLintExtension taskExtension =
task.extensions.create('lint', JavaCompilerLintExtension)
// Use options set via the lint extension
// and assign them to the options.compilerArgs
// property.
// We do this in doFirst because the options are not
// set yet at the Gradle configuration phase.
task.doFirst {
options.compilerArgs = taskExtension.asCompilerArgs()
}
}
}
}
We have everything ready, so let's use the plugin in our Java project:
// File: build.gradle
apply plugin: 'java'
apply plugin: com.mrhaki.gradle.JavaCompilerLintPlugin
repositories {
jcenter()
}
dependencies {
testCompile 'junit:junit:4.11'
}
compileJava {
// Here we use the custom
// task extension. The closure
// delegates to JavaCompilerLintExtension.
lint {
enableAll()
empty = false
depAnn = false
}
}
compileTestJava {
// All JavaCompile task have the
// lint extension.
lint {
cast = true
}
}
Written with Gradle 2.11.