Tuesday, February 23, 2010

Gradle: building with bliss

I’ve used Ant for years, and though the XML can get annoying, it’s a great tool. It’s so flexible, and once you understand it, you can do anything with it. Gant addresses the XML issue by introducing a Groovy syntax for writing Ant scripts. But one of the biggest issues with Ant, in my opinion, is the amount you have to write just to get a basic build that compiles some classes, runs some test, and builds a JAR or WAR.

One solution to this is Maven. Another nice tool, though it uses XML also. With Maven you can have a build up and running in minutes. But Maven takes a rather radical approach. With Maven, you don’t have a build file, you have a Project Object Model (POM). You use the POM to declaratively describe your project. Then all the Maven plugins use that information and fallow a build lifecycle to do the actual build. So, you don’t have a build file anymore, the build is just something that happens based on what you have in your POM. The Maven people are pretty big on the whole declarative POM describing your project. This line of thought is illustrated by a quote from the Maven AntRun Plugin page:

It is not the intention of this plugin to provide a means of polluting the POM, so it's encouraged to move all your Ant tasks to a build.xml file and just call it from the POM using Ant's <ant/> task

In other words, “don’t defile our beautifully declarative POM with your dirty procedural Ant scripts.”

The declarative concept is really neat in theory, but builds are a procedural process. So at times it feels to me like Maven is forcing something unnatural. And any time you want to add just a bit of logic to your build, you have to go through the effort of writing your own Maven plugin or do it in Ant and use the AntRun plugin. Seems like it should be easier than that, to me.

So, what I really want is a tool as powerful as Ant, as easy to add logic to as Gant, and as quick to setup as Maven. That’s exactly what Gradle is. It has tight integration with Ant, so anything you can do in Ant you can do in Gradle. It uses Groovy for the build scripts like Gant, so adding a bit of logic is easy and natural. And it has a build by convention concept (via plugins) like Maven that allows you to have a build running with a minimal amount of effort.

The most basic build

Here is the most basic Gradle build file you can have for a Java project. In your project root directory create a file called build.gradle and put this line in it

usePlugin 'java'

If you follow the Gradle convention (meaning you put your source code in src/main/java), this one line build file will allow you to compile and JAR your project. By default the name of your project that Gradle uses (and the name on the JAR) is the name of the folder that contains the build.gradle file. To learn how to actually run the build, check out the Gradle user guide.

Running some test

To actually run some tests, we’ll have to add some more too our build. Again, we’ll follow the Gradle convention of putting test in the src/test/java folder and change the build file to look like this:

usePlugin 'java'

repositories {
   mavenCentral()
}

dependencies {
   testCompile 'junit:junit:4.4'
}

With this build file we can now compile our code, compile our tests, run the jUnit tests, and create a JAR. Not bad for just a few lines of Groovy.

Changing the source locations

If you don’t want to follow the Gradle conventions, you can change the locations of your source files and test files. To do this you use the Source Sets concept from the Gradle Java plugin. Adding this code to the build file will change you source location to the src folder under the project root, and the tests to the test folder under the project root:

sourceSets {
   main {
      java {
         srcDir 'src'
      }
      resources {
         srcDir 'src'
      }
   }
   test {
      java {
         srcDir 'test'
      }
      resources {
         srcDir 'test'
      }
   }
}

There’s a lot more to learn about Gradle, and I may post more about it in the future. If you want to learn more, check out the user guide. But honestly the best thing I can say about Gradle is that I barely spend much time working with it. It’s so flexible and easy to work with that most of the time when I need to add something to a build file I can get in there add the logic I need quickly and get it all working in a few minutes, then get back to working on my software. Which is really what you want from a build tool because customers don’t care about builds! So you want a build tool that allows you to accomplish what you need as quickly and easily as possible, so you can get back to doing the work that your customers actually care about. To me, that’s where Gradle really shines.

4 comments:

  1. Errr.....actually, src/main/java is the Maven 2 standard layout. Many of these tools do offer genuine advantages, but there are definitely some maturity issues, small issues like difficulties dealing with corporate firewalls, et al.

    ReplyDelete
  2. I know src/main/java is the Maven 2 standard, that's obviously where Gradle got it from. But what I said was correct. It is the convention for Gradle.

    ReplyDelete
  3. How important is to knwow Groovy to use it?

    ReplyDelete
  4. You'll have to have a decent understanding of Groovy, but usually there isn't much code in the build, and it's not too complicated. So, you don't have to be a Groovy expert. I don't really know Groovy very well.

    ReplyDelete