Submitted by Tomek Kaczanowski on Thu, 11/04/2010 - 14:12

A short comparison of length of the build files of Maven 3, Polyglot Maven (Groovy version), Ant and Gradle. Please notice that this is NOT a full comparison of these build frameworks!

[UPDATED 2010-11-18 - I implemented changes requested by some commentators, i.e. made maven pom.xml shorter by using properties instead of full maven-compiler-plugin configuration].

The source code is available at github. Enjoy !

Let us see what is required by each of popular build tools - Ant, Maven and Gradle - to build a very simple project. The project consists of few Java 1.6 classes that require only one dependency for compilation ( commons-lang 2.5 ) and one for tests ( junit 4.8.2 ). Each build ends up with generation of a valid coc-comparison-1.0-SNAPSHOT.jar file.

If you notice possibility to make some of build files shorter (but still readable and without any nasty hacks), please let me know.

I tried to make build files as concise as it is possible but at the same time readable and written in a spirit of this particular tool. For example, build.xml of Ant could be few lines shorter, but I follow the unwritten convention of clean-init-compile tasks.

This blog post is written rather to show how build files evolved over time than to compare build tools. Please bear this in mind when commenting.

Ant



Old, good Ant. No Convention over Configuration (CoC) at all. You need to specify everything by hand. This results in very bloated build.xml files. On the other hand, reading of build.xml is enough to understand what the build does, where the sources are etc. Nothing hidden, nothing happening "by magic".

The lack of built-in CoC resulted in several community-standards, like keeping all libraries in lib subdirectory, having clean and init tasks etc. This helped to make Ant builds more "standard" and easier to digest. However these are not rules but rather community recommendations and they are not supported, checked or forced by Ant in any way.

Build file (build.xml):

<?xml version="1.0"?>

<project name="simple" default="dist" basedir=".">

<property name="src" location="src/main/java"/>

<property name="srcTest" location="src/test/java"/>

<property name="build" location="build"/>

<property name="dist" location="${build}/lib"/>

<property name="version" value="1.0-SNAPSHOT" />

<path id="classpath.compile">

<pathelement location="libs/commons-lang-2.5.jar"/>

</path>

<path id="classpath.test">

<pathelement location="libs/junit-4.8.2.jar"/>

<pathelement location="libs/commons-lang-2.5.jar"/>

<pathelement location="${srcTest}"/>

<pathelement location="${build}/classes"/>

<pathelement location="${build}/test-classes"/>

</path>

<target name="init">

<mkdir dir="${build}/classes"/>

<mkdir dir="${build}/test-classes"/>

</target>

<target name="compile" depends="init">

<javac srcdir="${src}" destdir="${build}/classes">

<classpath refid="classpath.compile"/>

</javac>

</target>

<target name="testCompile" depends="compile">

<javac srcdir="${srcTest}" destdir="${build}/test-classes">

<classpath refid="classpath.test"/>

</javac>

</target>

<target name="test" depends="testCompile">

<junit fork="yes" haltonfailure="yes">

<batchtest fork="yes">

<fileset dir="${srcTest}">

<include name="**/*Test.java"/>

</fileset>

</batchtest>

<classpath refid="classpath.test"/>

<formatter type="plain"/>

</junit>

</target>

<target name="dist" depends="test">

<mkdir dir="${dist}"/>

<jar jarfile="${dist}/coc-comparison-${version}.jar" basedir="${build}/classes"/>

</target>

<target name="clean">

<delete dir="${build}"/>

</target>

</project>

Maven 2

This is how CoC in Java build tools started! Maven uses default (conventional) values for many aspects of your build. It assumes that sources are in src/main/java , test resources in src/test/resources , web files in src/main/webapp and so on. This makes build files (named pom.xml ) to be much smaller than Ant counterparts. The other benefit is that any new developer knows what to expect when she/he joins any team that uses Maven.

No wonder that Maven was so successful and some of its defaults (like putting all Java sources into src/main/java ) were accepted by Java community (and other build tools as well).

Still many complains about the XML format of build files, which makes them much longer than they could be. Also the need to specify that Java 1.5 is required seems rather outdated to me.

Build file (pom.xml):

Maven 3



Pom.xml file of Maven 3 is similar to pom.xml of Maven 2, but Java 1.5 is used by default so 4 properties lines can be ommitted.

Build file (pom.xml):

Polyglot Maven

I thought that writing POMs using script languages will be a major change in new Maven 3, but I was wrong. Now I know, that this feature is still not in Maven core but you have to install a fork called Maven Polyglot.

As you can see it is a very nice feature that reduces POMs size significantly. Now you can see that a substantial part of Maven pom.xml files was never really needed. Definitely this is a step in the right direction and I hope this feature will be merged into Maven core.

Still when comparing to Gradle (see below) one can observe that the legacy of old XML format is still present in this new approach. Also being Maven compatible means that Java 1.4 is used by default (and has to be changed by configuration of maven-compiler-plugin ).

Build file (pom.groovy)

project {

modelVersion '4.0.0'

artifactId 'coc-comparison'

groupId 'grId'

version '1.0-SNAPSHOT'



dependencies {

dependency('commons-lang:commons-lang:2.5')

dependency('junit:junit:4.8.2')

}



properties {

'maven.compiler.target' '1.6'

'maven.compiler.source' '1.6'

}

}

Gradle



Gradle does it right. Build files - named by default build.gradle - contain only information that are really necessary. No cryptic tags, no bloated XML structures, "no fluff just stuff". :)

Build file (build.gradle):

apply plugin: 'java'



version="1.0-SNAPSHOT"

group="grId"

archivesBaseName="coc-comparison"



repositories {

mavenCentral()

}



dependencies {

compile 'commons-lang:commons-lang:2.5'

testCompile 'junit:junit:4.8.1'

}

Conclusion

First a little summary of file lengths (as returned by wc tool):

tool language lines characters ant 1.8 XML 50 1733 maven 2.0 XML 28 904 maven 3.0 XML 24 765 polyglot maven (groovy) 0.8-SNAPSHOT groovy 16 303 gradle 0.9-rc-2 groovy 15 224

Nothing surprising here but still some interesting observations regarding build tools can be made.

XML is a evil. No one likes it anymore and new tools avoid it. . Poor Maven needs to be still compatible with its legacy XML format which does not allow him to grow and compete with newer frameworks. Polyglot Maven seems like a move in the right direction. DSLa are taking over. Gradle beats the competition in this aspect but Polyglot Maven achieves very similar result. XML-based tools have no chances. Convention over Configuration gives a huge gain in terms of build script conciseness. All tools except grandpa Ant take use of CoC. Being backward compatible is painful. Polyglot Maven suffers from its 100% compatibility with Maven which does not allow its build files to use the full potential of script languages. Haven't included buildr script in my comparison, but I guess it would be similar to Gradle. Another example of good DSL.

One interesting question is if you can get any better than Gradle in terms of conciseness? I remember seeing somewhere (probably on Gradle mailing list) some ideas regarding automatic recognition of dependencies which would made build files even shorter. Sounds nice, but this idea is rather hard to be implemented, isn't it?

Please be sensible when drawing conclusions from this simple comparison. The fact that Maven's pom.xml is several times bigger than Gradle's build.gradle doesn't mean that Gradle is few times better! (Well, in fact it is, but for many other reasons). For example when running the Maven version one can easily generate a project site which is not possible when running presented Gradle build.

Presentation

There is also a short presentation available if you are interested:

Links