DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations

Developing a Custom Gradle Plugin

Elina Valieva user avatar by
Elina Valieva
·
Jun. 18, 20 · Tutorial
Like (2)
Save
Tweet
Share
8.69K Views

Join the DZone community and get the full member experience.

Join For Free

Gradle allows you to implement your own plugins in any languages like Java, Groovy, or Kotlin, so you can reuse your build logic, and share it with others, which can be used across many different projects and builds. 

In our example, we are going to use Kotlin as the implementation language for a standalone plugin project and Kotlin in the build script plugin examples. In the following example, we will create a plugin with two tasks: task with command-line option and task with extension.

Plugin Setup

Setup build.gradle.kts

Let's create a plugin as a  standalone project so that we can publish it and share it with others, which we are going to package and publish a plugin is to use the Java Gradle Plugin Development Plugin.  It's a is simply a Java project that produces a JAR containing the plugin classes, it's will automatically apply the Java Plugin, add the gradleApi() dependency to the implementation configuration, generate the required plugin descriptors in the resulting JAR file, and configure the Plugin Marker Artifact to be used when publishing. 

Here is a simple build script for the project build.gradle.kts:

Groovy
xxxxxxxxxx
1
36
 
1
plugins {
2
    `kotlin-dsl`
3
    `java-gradle-plugin`
4
}
5
6
group = "com.example"
7
version = "1.0.0"
8
9
repositories {
10
    mavenCentral()
11
}
12
13
dependencies {
14
    implementation(kotlin("stdlib-jdk8"))
15
    compileOnly(gradleApi())
16
    testImplementation("junit:junit:4.13")
17
}
18
19
tasks {
20
    compileKotlin {
21
        kotlinOptions.jvmTarget = "1.8"
22
    }
23
    compileTestKotlin {
24
        kotlinOptions.jvmTarget = "1.8"
25
    }
26
}
27
28
gradlePlugin {
29
    (plugins) {
30
        register("my_plugin") {
31
            id = "com.example.my_plugin"
32
            implementationClass = "com.example.MyPlugin"
33
        }
34
    }
35
}
36


Plugin

To create a Gradle plugin, you need to write a class that implements the Plugin interface. When the plugin is applied to a project, Gradle creates an instance of the plugin class and calls the instance’s Plugin.apply() method.  Handling user input from the script we will do through an extension and command option.  

Kotlin
xxxxxxxxxx
1
13
 
1
package com.example
2
3
import org.gradle.api.Plugin
4
import org.gradle.api.Project
5
6
class MyPlugin : Plugin<Project> {
7
8
    override fun apply(project: Project) {
9
        project.extensions.create("greeting", MyExtension::class.java)
10
        val task = project.tasks.create("hello", MyTask::class.java)
11
        task.group = "welcome"
12
    }
13
}


Create src/resource/META-INF/plugin.properties  file and set reference to your plugin class:

Properties files
xxxxxxxxxx
1
 
1
implementation-class=com.example.MyPlugin


Extension

For using extension the Gradle Project has an associated ExtensionContainer object that contains all the settings and properties for the plugins that have been applied to the project. You can provide a configuration for your plugin by adding an extension object to this container.  An extension object is simply an object with Java Bean properties that represent the configuration.

Kotlin
xxxxxxxxxx
1
 
1
package com.example
2
3
open class MyExtension {
4
5
    var message: String? = null
6
}


Task

Task classes from the Gradle API can be used in specific circumstances, extending DefaultTask is the most common scenario. Annotate the default task action as @TaskAction.  

Kotlin
xxxxxxxxxx
1
26
 
1
package com.example
2
3
import org.gradle.api.DefaultTask
4
import org.gradle.api.tasks.Input
5
import org.gradle.api.tasks.TaskAction
6
import org.gradle.api.tasks.options.Option
7
8
open class MyTask : DefaultTask() {
9
10
    @Input
11
    @Optional
12
    @Option(description = "Message from command line", option = "message")
13
    var message: String? = null
14
15
    @TaskAction
16
    fun run() {
17
        val extension = project.extensions.findByName("greeting") as MyExtension
18
        extension.message?.let {
19
            println("Hello from extension ${extension.message}")
20
        }
21
        message?.let {
22
            println("Hello from command line $message")
23
        }
24
    }
25
}
26


Test

You can use the ProjectBuilder class to create Project instances to use when you test your plugin implementation.  

Kotlin
xxxxxxxxxx
1
19
 
1
package com.example
2
3
import org.gradle.api.Project
4
import org.gradle.testfixtures.ProjectBuilder
5
import org.junit.Assert.*
6
import org.junit.Test
7
8
class MyPluginTest {
9
10
    @Test
11
    fun test() {
12
        val pluginProject: Project = ProjectBuilder.builder().build()
13
        pluginProject.pluginManager.apply("com.example.my_plugin")
14
        val task = pluginProject.tasks.findByName("hello")
15
        assertNotNull(task)
16
        assertTrue(task is MyTask)
17
        assertEquals("welcome", task!!.group)
18
    }
19
}


Plugin publishing

Register in Gradle Plugin Portal. See more: publishing tutorial 

Add the Plugin Publishing Plugin to the project

Add plugin from plugin-publishing (use the latest version):

Groovy
xxxxxxxxxx
1
 
1
plugins {
2
    ...
3
    id("com.gradle.plugin-publish") version "0.12.0"
4
}


Configure the Plugin Publishing Plugin

Create a pluginBundle block in build.gradle.kts and specify global information regarding your plugin. This helps other people browsing the portal find more information about your plugin and learn how to contribute to its development.

Groovy
xxxxxxxxxx
1
 
1
pluginBundle {
2
    website = "https://your_project_web_site"
3
    vcsUrl = "https://your_project_source"
4
    tags = listOf("hello", "greeting")
5
}
6


Publish your plugin

Run validate plugin command:

./gradlew validatePlugins

Run publishing, if you're not authorized use login command:

./gradlew publishPlugins 


Usage

Apply your plugin to project:

Java
xxxxxxxxxx
1
 
1
plugins {
2
     ...
3
    id "com.example.my_plugin" version "1.0.0"
4
}


Output of gradle hello --message = "My Gradle Plugin"

Plain Text
xxxxxxxxxx
1
 
1
> Task :hello
2
3
Hello from command line My Gradle plugin


Add extension in your build.gradle:

Groovy
xxxxxxxxxx
1
 
1
greeting {
2
    message = "My Gradle plugin"
3
}


Output of  gradle hello:

Plain Text
xxxxxxxxxx
1
 
1
> Task :hello
2
3
Hello from extension My Gradle plugin
Gradle

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • 7 Most Sought-After Front-End Frameworks for Web Developers
  • Using GPT-3 in Our Applications
  • Build an Automated Testing Pipeline With GitLab CI/CD and Selenium Grid
  • Practical Example of Using CSS Layer

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: