Maven – Pain = Gradle?
Being in the continuous integration game, it’s part of my job to keep an eye on build tools and technologies. Occasionally I hear of something interesting enough to try out, so when I next start a small project I’ll give it a go.
This time it is the turn of Gradle. From the Gradle website:
Gradle is a build system which provides:
- A very flexible general purpose build tool like Ant.
- Switchable, build-by-convention frameworks a la Maven (for Java and Groovy projects). But we never lock you
- Powerful support for multi-project builds.
- Powerful dependency management (based on Apache Ivy).
- Full support for your existing Maven or Ivy repository infrastructure.
- Support for transitive dependency management without the need for remote repositories and pom.xml
or ivy.xml files (optional).
- Ant tasks as first class citizens.
- Groovy build scripts.
Build tools that leverage scripting languages such as Groovy, Ruby and Python are all the rage. This is undoubtedly a useful feature, but so common these days that it is not a differentiating factor. After all, just adding a more concise way to write procedural build scripts is not a big win. The focus needs to be on making builds as declarative as possible.
The current king of declarative builds in the Java world is undoubtedly Maven. However, as I have said in a previous post, the current implementation of Maven leaves a lot to be desired. Still, the Maven idea of build-by-convention is still a good one if it can be achieved in a flexible way. This, then, is what attracts me to Gradle — its specific goal of providing build-by-convention without the lock-in.
To begin, I set myself the lofty goal of writing a “Hello, World” build script. This gets me to the point where I have a working gradle installation. As I already had a JDK installed (the only external dependency), installation was as simple as:
$ unzip gradle-0.4-all.zip
$ export GRADLE_HOME=”$(pwd)/gradle-0.4″
$ export PATH=”$PATH:$GRADLE_HOME/bin”
$ gradle -v
Gradle buildtime: Tuesday, September 16, 2008 9:20:38 AM CEST
JVM Vendor: Sun Microsystems Inc.
OS Name: Linux
Gradle build files are named “build.gradle”, so next I created a trivial example as follows:
println ‘Hello, world!’
The above is normal Groovy source code, executed in an environment provided by gradle. It defines a single task which is gradle’s equivalent of a target (almost like the combination of an Ant task and target). Executing this task gives:
Note that the -q flag suppresses some gradle output.
A Simple Java Project
To test gradle’s claims of build-by-convention, I next put it to work on a simple Java project. Gradle’s build-by-convention support is implemented as “plugins” for different languages, with Java and Groovy plugins provided out of the box. The project to be built is a JavaDoc doclet, so the build just needs to compile Java source files into a single jar. To make life a little interesting, the project does not fit gradle’s default conventions in two ways:
- It should not be named after the containing directory.
- The source is located under “src/java”, not “src/main/java”.
These are truly simple customisations — so you would expect them to be easily configured. And indeed they are, as shown in the build.gradle file:
version = ‘0.1’
sourceCompatibility = 1.5
targetCompatibility = 1.5
srcDirNames = [‘java’]
The first line customises the project and jar file names, and the last line is used to override the default location for Java source files. With this build file in place, I can build the jar as follows:
$ ls build
classes com.zutubi.xmlrpc.doclet-0.1.jar reports test-classes test-results
That was pleasantly simple! The Java plugin also gives me a bunch of other tasks for free:
Task :archive_jar [:test]
Task :clean 
Task :compile [:resources]
Task :dists [:libs]
Task :eclipse [:eclipseCp, :eclipseProject]
Task :eclipseClean 
Task :eclipseCp 
Task :eclipseProject 
Task :eclipseWtpModule 
Task :init 
Task :javadoc 
Task :libs [:archive_jar, :test]
Task :resources [:init]
Task :test [:testCompile]
Task :testCompile [:testResources]
Task :testResources [:compile]
Task :upload [:uploadDists, :uploadLibs]
Task :uploadDists [:dists]
Task :uploadInternalLibs [:libs]
Task :uploadLibs [:libs]
So far, gradle looks very promising. The example above is too simple to judge how it would fare on a larger, more challenging build, but it shows the basics are right: at least a simple case is simple. I hope to give it a try on a larger code base soon.
At the moment the gradle project is still in its infancy, so I’ll be keeping a keen eye on its development. Indeed, if it can achieve its stated goals it will become a build tool to reckon with, and a tough competitor for Maven.
This entry was posted on Friday, November 28th, 2008 at 2:25 am and is filed under Build, Java, Technology. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.