Brief history of building tools starts with Make, which is maybe an overly complex solution. And it’s not so platform independent. After that evolution continues with Ant, which is XML based and it has its pros and cons. Ant is still used for scriptings and there are still good use cases for it.

Today we have more and more complex projects and we need to incorporate different technologies, languages and support all kinds build strategies. To support rapid changes of the landscape of modern software development, we are probably using Maven, as the next evolution step. We can easily incorporate different modules and libraries in our final product. Maven brings the philosophy of convention over configuration. And it brings lot advantages to JVM ecosystem, but XML is still here. One of Maven “killer feature” is that it will check your project dependencies and pull new versions from upstream. Maven also supports plugins, so you can extend the functionalities of your build process.

After all, we are coming to the Gradle, as the next evolutionary step in JVM build tools. As with each evolutionary step, Gradle has incorporate learned lessons from Ant and Maven, and move those concepts and best ideas to the next level.

First and main difference between Maven and Gradle, that there is no XML syntax anymore. Gradle allows declaratively modeling your problem domain using a powerful and expressive DSL implemented in Groovy as a first citizen language. And because is JVM native, it allows you to write custom logic in Java or Groovy.
Gradle tends to be flexible as much as possible, by that you can change some of convention-over-configuration principles. For example, if you have a different project structure from convention, it’s possible to configure build script to be aligned with different folder structure, which is specially acceptable for older projects. Lots of project are using different technologies and languages on client and server side. And we always looking for the best way to incorporate those technologies in our final product. By that Gradle fits right into that place, by providing expressive DSLs and to abandon XML, and convention over configuration approach with the ability for to bend that rule if needed. And it also provides powerful dependency management.

Picture 1. Union of Gradle technologies

gradle.build vs POM.xml

    gradle.build is equivalent of Maven POM.xml. But it offers much more, especially if you are treating your build script as a piece of software, then you want to test, extend and maintain that script, and Gradle allows you to do that. If we want to compare the same build script in Maven and Gradle, then we can notice significant cuts down on the size and improved readability.

Code block 1. maven pom.example with 15 LoC

Code block 2. Gradle build.gradle example with 11 LoC

 

Adding Gradle to our project

If we are starting a new project and we want to manage our project dependencies and build process with Gradle. We can start by downloading Gradle from official page. And after unpacking Gradle, and putting Gradle bin folder in our System path, we can enter our project folder from console, and write:

$gradle init

Running above command, Gradle will create next folder structure:

Picture 2. File and folder structure of empty initialized project

If you are using some DVCS, then you should put folders ‘.gradle’ and ‘gradle’ to ignore. Because those folders are temporary Gradle folders.

Files ‘gradlew’ and ‘gradlew.bat’ stands for Gradle Wrapper, and running them is a preferred way of starting a Gradle build. Gradlew is convenient way to use same Gradle version to build all instances of the project or if Gradle is not installed, gradlew will download project dependent Gradle version.

Settings file is used for storing default values for build process, and it’s executed during initialization phase. In multi-project build settings.gradle is mandatory in the project root, by defining which projects are taking part in that build. Most important file ‘build.gradle’, which contains your build configuration, rules and tasks. (Code block 2.)

 

Most common element for writing build script

apply plugin
Is used to include a plugin for the current build file. And by that including new tasks shipped with that plugin. If we want to get a list of all available tasks in our build script, we can run ‘gradle tasks’ command to list all available tasks and their description.

Some example of plugins is ‘java’, to include java nature to project. There a many other plugins like: eclipse, idea, scala, com.android.library, ear, war, maven, findbugs, signing. Its also possible to load custom plugins, by providing a buildscript element.

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.2.RELEASE")
    }
}
apply plugin: 'spring-boot'

Code block 3. Example how to use custom plugin

repositories
This element is used to define your project repositories where Gradle can search for artifacts.

repositories {
    mavenCentral() // to use Maven central
    jcenter() //Bintray's JCenter
    mavenCentral artifactUrls: ["http://www.mycompany.com/artifacts1"
}

Code block 4. Example of common used repository references

dependencies
In this element we define our project dependencies, which are grouped in configurations. For example Java plugin defines four configurations:

  • compile
    required to compile the production source of the project.
  • runtime
    required by the production classes at runtime. By default, also includes the compile time dependencies.
  • testCompile
    required to compile the test source of the project. By default, also includes the compiled production classes and the compile time dependencies.
  • testRuntime
    required to run the tests. By default, also includes the compile, runtime and test compile dependencies.
dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
    testCompile: 'junit:junit:4.+'    // Shortcut definition
}

Code block 5. Example of long and short definition of dependencies

task
A Task represents a single atomic piece of work for a build, such as compiling classes or generating javadoc. The task can be set of commands, and it can be written in Groovy. A task also can depend on other tasks, by that running our task, Gradle will first run depending task, and then our task.

task copy(type: Copy) {
   description 'Copies the resource directory to the target directory.'
   from 'resources'
   into 'target'
   include('**/*.txt', '**/*.xml', '**/*.properties')
}

Code block 6. Task example

 

Gradle is full mature and enterprise ready solution, used more and more by big companies to support automated full lifecycle of their products. Obviously it’s represent the next step to build automation with some of the key features:

  • enterprise-ready build system
  • declarative and expressive DSL
  • no XML
  • support Groovy and Java
  • compatible with Maven and Ant
  • convention over configuration and allowing flexibility
  • Effortless Extendibility
  • scalable builds
  • incremental builds
  • run in daemon mode (to speed up builds)
  • robust and powerful dependency management
  • strong community involvement

 

For more information you can visit Gradle homepage with excellent documentation and tutorials. Great place for start learning Gradle.