Open Source Tools: Build – Gradle

Gradle is a JVM based build tool whose aim is to let developers create binaries from sources. It has grown in popularity in recent years due to is flexibility, one of the reasons why the Android ecosystem switched from Apache Ant to Gradle, turning every single Android developer out there into a Gradle user. Gradle has its origin way back in late 2007 as a response to Maven’s inability to deliver a flexible lifecycle. At the time Gradle’s aim was to deliver a richer model on which any kind of project could be built; this allowed Gradle to support non-JVM based projects such as C++, Objective-C, and just recently Swift. Nowadays the aim of the tool is to make builds faster while still keeping a flexible model.

Getting started with Gradle is as simple as getting started with Maven as witnessed by the official install documentation found at the Gradle website. Just like it happened with Maven, you have the choice to manually download and configure the tool or choose a package manager to achieve the same feat. Once installed you may run gradle --version to verify that the tool was installed correctly. This is what I get on my computer at the time of posting this entry

$ gradle --version

------------------------------------------------------------
Gradle 4.0
------------------------------------------------------------

Build time:   2017-06-14 15:11:08 UTC
Revision:     316546a5fcb4e2dfe1d6aa0b73a4e09e8cecb5a5

Groovy:       2.4.11
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_131 (Oracle Corporation 25.131-b11)
OS:           Mac OS X 10.12.5 x86_64

Notice this tool also gives detailed information about its current release and execution environment. Do not forget to mention this information when submitting a bug report or discussing a problem related to Gradle. There are several options to create a build file, you can find documentation at the Gradle website as well. Say for example you’d want to build a Java project that happens to follow the Maven conventions too; also it has no dependencies other than JUnit in order to run tests. The Maven build files looks like this

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.acme</groupId>
    <artifactId>sample</artifactId>
    <version>0.0.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

while the Gradle build file looks like this

plugins {
    id 'java'
    id 'maven-publish'
}

group   = 'com.acme'
version = '0.0.0-SNAPSHOT'

repositories {
    mavenLocal()
}

dependencies {
    testCompile 'junit:junit:4.12'
}

The signal-to-noise ratio in terms of syntax is better in the Gradle file than for the Maven one, however we know we can train our brains to watch out for the important information and discard what’s not needed. One could say is the same thing that Lispers do; developers complain that Lisp (or Clojure if you’re interested in a JVM version of Lisp) has too many parentheticals. To the trained eye of a Lisper that’s not true, and if you really want to be picky just count how many parenthesis can be found in a “normal” Java class, you’ll be surprised that the number is often higher than what you’d expect; sum up additional syntax characters and you’ll see that on average Java has more syntax noise than Clojure! Coming back to Gradle, the file size is quite manageable and as long as the only thing we do is add dependencies with the right configuration (similar to Maven’s scopes but with added features) then the apparent benefit of using Gradle instead of Maven is of little use, but is it? A maven build similar to this one with a moderate sized codebase will most of the times be faster than it’s Gradle counterpart, because Maven performs less checks than Gradle. Gradle on the other hand will check inputs and outputs of every task (such as processResources, compile, etc) to see if there’s actual work to be done. Additionally to this, both tools have to pay the price of creating a JVM on which the build itself runs. In order to minimize this time and speed up build results Gradle has come up with a series of alternatives such as keeping a JVM running int he background (known as the Gradle daemon) and a brand new build cache (local & remote). These features certainly help in speeding up builds but given their very nature they may bring unexpected errors form time to time (such as the daemon running out of memory/space or running for too long).

Personally I like Gradle better than the alternatives, as form my point of view it delivers enough flexibility for power users while still giving a good set of conventions and sensible defaults to newcomers. This flexibility comes with a price: you must understands the basics of Apache Groovy and its dynamic features as sometimes you may experience a problem due to different scopes being in place (see [Issue 001] Gradle project properties for more information on this subject). For this reason there are developers that don’t like Gradle at all, the usage of Groovy as a DSL poses a problem as it allows you to write any type of valid Groovy statement in a build file, including loops and gasp creating new Threads. In other words, it opens the door for developers to go crazy with the build file and paste code here and there, throw snippets of code together and see what sticks. Clearly a recipe for disaster. The problem is not the fact that the tool is flexible but lack of organization, design, and some restrain. As Uncle Ben famously uttered: with great power comes great responsibility. As an author of a Gradle build script it befalls into you to make the build as slick and readable as possible. Yes, anyone can write a snippet of Groovy in a build file, the question is, should that snippet be in the build file at all? This feature can be used for quick prototyping and one-off setups. The moment you see complexity begins to rise or duplication is introduced is when our trusty refactoring skills should kick in, moving those snippets of code to secondary build scripts, external task definitions, or plugin projects. It’s up to you to decide how much entropy your build may be able to withstand.

All this being said, the learning curve for Gradle may be a bit steeper than Maven’s. Despite all the years I had of experience writing Groovy code I found myself quite lost when I started using Gradle back in mid 2009, due to the fact that Gradle had little documentation at the time and that its model was still in flux. Nowadays the documentation and the amount of information and examples available all over the Net should be enough to get you started. One more thing, the development speed of Gradle and its releases is quite fast, as witnessed by the following comparison posted on April 10th 2017, a moment in time when both Maven and Gradle released version 3.5.0

Leave a Reply

Your email address will not be published. Required fields are marked *

ˆ Back To Top