Why Gradle?

Back in my youth, programs used to come as listings in magazines that you copied into the ZX81’s BASIC editor and then ran. How times have changed. Building software has become more complex as the underlying runtimes and platforms have evolved. As a result of that, we have seen an evolution in build tools. I started my working life using Make (for both C++ and Java), before progressing onto Apache Ant and Apache Maven 2. For a brief interlude I even worked with CMake, which I found to be one of the more challenging tools to learn and understand.

Gradle is a recent entrant to the field, and my current build tool of choice. What lifts it above the more established tools, Ant and Maven? This is a question that anyone involved in building Java software in particular should be asking themselves.

Let’s go back to basics and ask ourselves what we want from a software build. As an example, consider the process of compiling a Java application. You could use the javac command directly, but then you would have to ensure that all the appropriate source files were specified on the command. And don’t forget all the JARs you’d have to include in the classpath. Imagine specifying that command line each time you wanted to recompile the source files. It’s ridiculously time consuming and error prone, hence why any sane developer or team uses a build tool to automate the process. And this is the key foundation of building software: automating the steps required to go from the inputs (typically source files) to the outputs (packaged applications, deployed web applications, etc.).

Automation provides a couple of major benefits:

  • Reliability – you’re eliminating many potential sources of human error
  • Time saving – fewer manual steps means less time wasted

Another consideration is reproducibility. In other words, given a fixed set of inputs, we want the outputs to always be the same. If a build is not reproducible, you won’t be able to guarantee that you’re building the same binaries that you gave to a client a year or two back. Build tools can certainly help with this by removing the human error component, but they are not sufficient on their own as you can easily make a build that is dependent on its environment.

In essence, we want a build tool that allows us to automate as much of the development and deployment process as possible. Most of us already include compilation, running unit tests, and packaging, but what about:

  • Creating a complete developer environment for a project from scratch
  • Generating a project’s documentation (possibly in multiple languages)
  • Running the application in a special developer mode
  • Running functional/integration tests that require special setup
  • Automatically updating source control management (SCM) information, such as tags
  • Stopping, deploying, and restarting server apps in different environments

A lot of these aspects are very project-specific and require customisation of the build. It’s also becoming quite common to mix multiple languages and platforms into a single project, such as JavaScript for a rich browser front end and Java for the back end. How should you handle these project-specific build requirements? You might use different tools or run special scripts manually, but that kind of appraoch takes you away from the ideal of a fully automated process, weakening the benefits I talked about earlier.

Full automation is an important goal for building software, but it’s not the sole one. How much effort does it takes to set up a software build in the first place and how easy it is for an outside or new hire to understand it? You don’t want developers and build masters wasting time trying to understand how to use a highly customised build system if you don’t have to. That’s where the concept of conventions comes in: standardise those things that are common to the majority of software projects of a particular type. Think directory structure, compilation, packaging, etc. Maven hit the nail on the head when it introduced conventions to Java build.

In real life, most projects will be a mix of standard build bits and custom steps. They’ll often be mostly standard with just a few customisations. So ideally you want a tool that gives you a bunch of conventions that you can follow, but with the flexibility to both customise the standard steps and introduce your own ones. This is where I feel Gradle shines. Consider this basic build for a Java project:

apply plugin: "java"

version = "1.0.0"
group = "org.example"

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

repositories {

dependencies {
    compile "commons-io:commons-io:2.4"

It’s not very long, but this build file gives you everything you need to compile, test, and package a Java project that follows the conventions established by Maven. Anybody that knows those conventions will be able to easily navigate their way around the project and understand from the build file exactly what is specific to this project (such as the dependencies).

Now consider a scenario in which you have a build step (or task in Gradle parlance) that generates some source files that should be included in the compilation. There are two things you need to do:

  • Make sure the source code generation happens before the compilation
  • Configure the compiler to include the files in the generated source directory

This may seem intimidating at first, but Gradle gives you access to a full-featured API that makes such customisations trivial. This is all you need to add to the original build file:

sourceSets {
    main {
        java {
            // Include the generated source files in the compilation
            srcDir "$buildDir/genSrc"

task generateSource << {
    // Generate the required source files into "$buildDir/genSrc"

// Make sure that the source files are generated before compilation occurs
compileJava.dependsOn generateSource

It’s not the ideal approach, but it gives you an idea of what’s possible.

So where is all the stuff that implements compilation, testing, packaging etc.? You may have already guessed: the Java plugin. It contains all the relevant tasks (JavaCompile, Test) as well as the conventions that tie all those tasks together. In fact, if you don’t include the Java plugin in your build, then you don’t get any of that stuff. This is great if you want to build something else entirely, such as a user guide, or a JavaScript project. The only thing that Gradle forces you to do is model your build in terms of a graph of tasks. But that’s flexible enough to satisfy any build requirements you might have.

The inherent flexibility of Gradle combined with this concept of plugins means that Gradle can be used to build not only Java projects but also Android and C/C++ ones. You can find plugins to create executable fat JARs (Shadow plugin), create command line apps (Applicatin plugin), build documentation projects based on Asciidoctor, and more. And there’s nothing stopping you from creating your own types of conventional build.

Let’s not get carried away though. Gradle is a powerful tool that rewards time spent understanding it. It’s simple to use for simple projects, but you can easily dig yourself into a deep hole if you abuse the power given to you. That’s the trade off: you’re given the flexibility to solve your problems and shoot yourself in the foot. Be responsible.

Hopefully this post has given you some inkling of what differentiates Gradle from its competitors and how it can help you model your own non-trivial build processes. Feel free to use the comments to raise questions!

9 thoughts on “Why Gradle?

  1. Pingback: Diario di Grails (settimana 3 del 2015) | BME

  2. Pingback: Settimanale Groovy #54 | BME

  3. Jack Ottofaro

    I’m investigating an issue one of our s/w dev teams is having. They must develop offline (closed network) and are currently using nexus and maven. To populate their offline repositories they must retrieve the data from a network connected computer, copy data onto a DVD and transfer to the closed network by copying from the DVD. Because of the overhead involved with getting the data to the closed network it’s important to completely understand, and retrieve, all dependencies when, for example, upgrading to a later version of s/w, e.g. Hibernate, Spring, etc.
    Does grable offer additional “power” over maven to resolve dependencies and help with the dev environment described above? None of the articles I have read comparing gradle and maven really discuss dependency management and any difference in the tools so I’m concluding that there is not much if any difference between the gradle and maven when it comes to dependencies

  4. Peter Post author

    Hi Jack,

    First, sorry. Your comment was languishing in moderation as I didn’t see an email about it. I’m glad it only sat there for a few days. Anyway, onto your question.

    Gradle does indeed give you more power over the dependency resolution strategy as many users have complex requirements and dependency metadata is often unreliable. If you want to read more on what you can do in Gradle, I recommend you take a look at ResolutionStrategy in the DSL guide.

    Unfortunately I can’t say whether that is sufficient for your needs, but from what I understand of your situation, you can guarantee that you end up with all required dependencies without rogue requests to an online repository. Just remember that it would require continual effort on someone’s part to maintain the dependency resolution rules.

    An alternative approach is embodied by the Nebula Dependency Lock plugin, which allows you to freeze dependency versions. I don’t have any experience of it myself, but people with a Ruby background favour the approach, which is used by Bundler.

    One final thought: you can specify filesystem-based repositories too in Gradle. In that case, you just need to put the required dependencies on a shared filesystem. Or developers can copy it locally onto their hard drives. Gradle gives you quite a few extra options over Maven when it comes to repositories.

    Hope that helps,


  5. Pingback: Diario Grails (Settimana 25-28 del 2015) | BME

  6. Steve Paesani

    When you say plugin are you referring to a template for a certain project type? Or is their extra functionality that has to be added along by authoring some code or getting pre authored code for instance ( gradle files being declared data and not code here) ?

  7. Peter Post author

    @Steve No, plugins are custom build logic. They can be used in different ways, for example by providing conventions or integrating with other systems. In essence, a plugin can do anything that you can do in a Gradle build file.

    The Build Init plugin – https://docs.gradle.org/current/userguide/build_init_plugin.html – allows you to create new projects from templates. It doesn’t support many templates right now, though.

  8. Goutham

    What are the advantage of gradle over make for build purpose of c and C++ projects??

    I feel since gradle is mainly focused on java project, it might be slower for c/C++??

  9. Peter Post author

    One good reason to use Gradle for C and C++ projects right now is if you have mixed language projects that you ideally want to build together. I have been involved with several systems that have parts in Java and parts in native languages and it’s messy using different build systems for each.

    I can’t say whether Gradle is slower than Make because it depends on the build. I also have no real world experience with the native support, so it’s best to ask someone that has. I do know that the native performance is no slouch and continues to improve. You might get some useful information if you ask on the Gradle discussion forums at https://discuss.gradle.org/ .

Leave a Reply

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