I spent some time looking around at various suggestions (including on the Gradle documentation page) about how to write a custom plugin. For my specific purpose, it was not intended to be a shared plugin - but rather one to abstract out some of the logic we are doing in our build. I did
another post on writing a Groovy plugin, here's the Java one.
To show that we are really doing a minimalist design here, let's start with a completely empty directory.
~> mkdir mytest
~> cd mytest
1. Gradle Wrapper
I personally use the Gradle Wrapper. Since the last post, I upgraded to
Gradle 2.0, but the Gradle Wrapper it installs by default is not
currently compatible with the Android plugin. As such, we'll still manually define one.
Create a build.gradle file:
task wrapper(type: Wrapper) {
gradleVersion = '1.12'
}
Run it.
~/mytest> gradle wrapper
Now that we have the wrapper installed in a fresh directory, let's look to that plugin. We'll be adding 3 Java classes and 1 properties file.
Here's what we are aiming for:
.
├── build.gradle
├── buildSrc
│ └── src
│ └── main
│ ├── java
│ │ └── org
│ │ └── eoti
│ │ └── gradle
│ │ ├── BrewinPluginExtension.java
│ │ ├── BrewinPlugin.java
│ │ └── BrewTask.java
│ └── resources
│ └── META-INF
│ └── gradle-plugins
│ └── brewin.properties
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
2. POJO Extension
Let's start this time by defining our POJO. We'll create
buildSrc/src/main/java/org/eoti/gradle/BrewinPluginExtension.java.
We'll add our package:
package org.eoti.gradle;
And import the Gradle API:
import org.gradle.api.*;
And create our POJO with getters/setters.
Our complete POJO:
package org.eoti.gradle;
import org.gradle.api.*;
public class BrewinPluginExtension
{
private String message = "Wake up!";
public String getMessage(){return message;}
public void setMessage(String message){this.message = message;}
}
3. Task
Next, we'll define our task. Create
buildSrc/src/main/java/org/eoti/gradle/BrewTask.java.
We'll add our package and imports:
package org.eoti.gradle;
import org.gradle.api.*;
import org.gradle.api.tasks.*;
Our class will extend
DefaultTask.
public class BrewTask extends DefaultTask{...}
Next we'll define our task and annotate it:
@TaskAction
public void brew() {...}
In the implementation, we want to find our configuration. If there isn't one, we'll create a default one. Then, we'll output our message. The complete code:
package org.eoti.gradle;
import org.gradle.api.*;
import org.gradle.api.tasks.*;
public class BrewTask extends DefaultTask
{
@TaskAction
public void brew() {
BrewinPluginExtension extension = getProject().getExtensions().findByType(BrewinPluginExtension.class);
if(extension == null)
extension = new BrewinPluginExtension();
System.out.format("%s\n", extension.getMessage());
}
}
Note the
getMessage() that we defined in our POJO.
4. Plugin
Next, we'll define our plugin. Create
buildSrc/src/main/java/org/eoti/gradle/BrewinPlugin.java.
Add your package and the Gradle import. In my case, that is:
package org.eoti.gradle;
import org.gradle.api.*;
Our class
implements Plugin<Project> which means we have:
@Override
public void apply(Project project){ ... }
We will specify two things in this function.
First, an extension to allow parameters to be passed in:
project.getExtensions().create("brewin", BrewinPluginExtension.class);
The name
"brewin" is the name of the configuration block.
Second, a task to be added once this plugin is applied:
project.getTasks().create("brew", BrewTask.class);
That
'brew' is the
@TaskAction name from above.
The complete plugin:
package org.eoti.gradle;
import org.gradle.api.*;
public class BrewinPlugin implements Plugin
{
@Override
public void apply(Project project)
{
project.getExtensions().create("brewin", BrewinPluginExtension.class);
project.getTasks().create("brew", BrewTask.class);
}
}
5. Properties
Now, we need to add the properties file using the same configuration name we chose above. In this case,
buildSrc/src/main/resources/META-INF/gradle-plugins/brewin.properties.
It contains one line that points to our plugin implementation:
implementation-class=org.eoti.gradle.BrewinPlugin
Ok, we're almost done.
6. Apply it
In your top-level
build.gradle, specify that we want to apply our new plugin by adding this to the top:
apply plugin: org.eoti.gradle.BrewinPlugin
And then from the command line, call the task we defined earlier:
~/mytest> ./gradlew brew
That's great! But, why did we create a configuration parameter if we aren't going to use it?
Add this to your top-level
build.gradle:
brewin{
message = "Make another pot!"
}
And then re-run it:
~/mytest> ./gradlew brew
There you go. You can add additional parameters, additional Java logic, etc.