loading...

Tips to implement Gradle Plugin

kengotoda profile image Kengo TODA ・2 min read

Now I'm implementing a new Gradle Plugin. The official document is really nice, and I wish my experience will help you to code yours.

Use groovy for extension and task

The extension is a major way to configure your plugin. It's a class that uses Property and Provider as its fields, then users can set values like below:

extension {
  intProp = 10
  fileProp = file('config.yml')
  listProp = [ 'bar', 'baz' ] 
}

Groovy helps you to generate necessary accessors, so what you need is simply private final fields:

class MyExtension {
    @NonNull
    final Property<Boolean> boolProp;

    @Inject
    MyExtension(ObjectFactory objects) {
        boolProp = objects.property(Boolean).convention(false)
    }
}

class MyTask extends DefaultTask {
    @Input
    @NonNull
    final Property<Boolean> boolProp;

    @Inject
    MyTask(ObjectFactory objects) {
        extension = project.exntensions.getByType(MyExtension)
        boolProp = objects.property(Boolean).convention(extension.boolProp)
    }
}

Always prefer lazy-approach

For better performance, we need to learn about build lifecycle, or face performance problem like this.

Prefer the lazy-approach. Pick APIs that lets you specify a configurationAction as its parameter like TaskContainer#register(...).

Refer the official document for detail.

Understand the difference between getXxx() and findXxx()

In Groovy modules, methods named getXxx() throw an exception if you found nothing. On the other hand, methods named findXxx() return null (not Optional!).

So when you expect that you always find the value (e.g. get the extension created by your plugin), use getXxx(). Otherwise, prefer findXxx() and check the nullness of returned value.

Worker API

To run heavy computations like static analysis, it is better to use the Gradle Worker API.

In my case, I need to launch a JVM process to kick SpotBugs, and it makes build especially in multi-module projects. Here is the result of my benchmark:

Benchmark Result

It requires Gradle 5.6+ but is actually valuable. You may have a try :)

Posted on by:

kengotoda profile

Kengo TODA

@kengotoda

Expert of Java, JavaScript, JVM bytecode, build and CI. Publishes SpotBugs plugin, Java libraries, Jenkins plugin and open-source ebook about Maven3.

Discussion

markdown guide