The Gradle build system
Since the Gradle build system (http://www.gradle.org) gets more and more attention I decided to have a look at how it works. This article should give you a brief overview of some of the features so that you get the taste of Gradle. It is not meant to be a tutorial to get you started and it’s recommended that you know about another build system.
Dependencies can be managed using Ivy and Maven repositories or by yourself if that is required. Most of the behaviour is defined in Gradle plug-ins that ship with its distribution. They can be used out of the box and adapted to your needs.
It expects the default layout from Maven which consists of
The look-ups will be done in the order given within the repositories section. So in the above Maven example it will first look in the local repository of the user, then on the company’s server and finally on Maven Central.
You can also add dependencies to external modules from Maven or Ivy repositories if you have defined them as described above.
The above sample contains the long and the short version of a module identifier. If you have a dependency on a local file then you can specify it with:
More sophisticated features can be found in the documentation and include stuff like:
Now you can start it:
The configuration steps will be executed first. And since myTaskB depends on myTaskA the output will be:
Tasks can also be of a predefined type. The follwoing example uses the JavaExec type to start some Java code:
The command
In Gradle this would be:
The ‘maven’ plug-in allows you to install the artifact in your local Maven repository. Gradle’s DSL makes the build script much easier to read. Of course one could use polyglot Maven but that didn’t take off yet.
The opposite way around there are also plug-ins for eclipse. The first one is Groovy support so you can edit Groovy code in eclipse. The second one is the Gradle plug-in itself which manages the dependencies of your project, allows you to start Gradle tasks and more.
There is support for other IDEs as well. The current state of tooling can be found here: http://www.gradle.org/tooling
The user guide documents all the parts of Gradle and will be continuously extended as Gradle grows. The reference material is generated Java/Groovy doc for Gradle’s API and DSL.
Even though it has a bit of a steep learning curve it is worth a closer look.
What is it?
Gradle is a build system that combines and extends the best features of Ant and Maven. It supports task based build processes like Ant and follows convention over configuration like Maven. On top of that, Gradle build scripts are written in the Groovy language allowing to define more complex behaviour in cases where it is necessary. But you don’t need to be a Groovy expert because Gradle comes with a domain specific language (DSL) to define the builds.Dependencies can be managed using Ivy and Maven repositories or by yourself if that is required. Most of the behaviour is defined in Gradle plug-ins that ship with its distribution. They can be used out of the box and adapted to your needs.
A simple example
A simple example of abuild.gradle
script for a Java project looks like this:
1
| apply plugin: 'java' |
src/main/java
, src/main/resource
, src/test/java
and src/test/resource
. And it expects the source to be compatible with the current JVM it is running on. To change these properties of the ‘java’ plug-in you can use Gradle’s DSL:
1
2
| sourceSets.main.java.srcDirs = [ 'src/java' , 'src/generated' ] sourceCompatibility = 1.6 |
Dependency management
Repositories
Gradle can access Maven and Ivy repositories. Here are some samples how to configure the repositories:
1
2
3
4
5
6
7
8
9
10
11
12
13
| repositories { mavenLocal() maven { } mavenCentral() } repositories { ivy { } } |
Dependencies
To depend on an internal module, i.e. a module from the same project, you just write:
1
2
3
| dependencies { compile project( ':shared' ) } |
1
2
3
4
| dependencies { runtime group: 'org.hibernate' , name: 'hibernate' , version: '3.0.5' testRuntime 'org.mockito:mockito-core:1.8.4' } |
1
2
3
4
| dependencies { compile files( 'libs/a.jar' , 'libs/b.jar' ) testCompile fileTree(dir: 'testlibs' , include: '*.jar' ) } |
- overwriting transitive dependencies
- use Ivy specific dependency features
- etc.
Tasks
Tasks are the central building blocks of the build process. They consist of two lists of actions. One list is to configure the task and the other to execute it. Here is a sample:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| // Just define an empty task task myTaskA // Add a configuration action myTaskA { println "config A" } // Add an execution action myTaskA << { println "action A" } // Another task depending on myTaskA with configuration and action task myTaskB (dependsOn: myTaskA) { println "config B" doLast { println "action B" } } |
1
| $ gradle myTaskB |
1
2
3
4
5
6
7
8
| config A config B :myTaskA action A :myTaskB action B BUILD SUCCESSFUL |
1
2
3
4
5
6
7
8
9
10
| apply plugin: 'java' … // dependencies, repositories etc. task startMain(type: JavaExec, dependsOn: classes) { main = 'mypackage.Main' args = "-x -y -z" .split(). toList () classpath sourceSets.main.classesDir classpath configurations.compile } |
gradle startMain
prepares the classes and then starts the program using the classes and also the external dependencies as classpath.Maven sample comparison
Just to be clear: this is not an A is better than B comparison. The purpose is only to show you the two different versions of a Maven and a Gradle build script that achieve the same thing.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| < modelVersion >4.0.0</ modelVersion > < groupId >ch.bbv.mavendemo</ groupId > < artifactId >simpleMavenDemo</ artifactId > < version >0.0.1-SNAPSHOT</ version > < properties > < java.source.version >1.7</ java.source.version > < junit.version >4.8.2</ junit.version > </ properties > < dependencies > < dependency > < groupId >junit</ groupId > < artifactId >junit</ artifactId > < version >${junit.version}</ version > < scope >test</ scope > </ dependency > </ dependencies > < build > < plugins > < plugin > < artifactId >maven-compiler-plugin</ artifactId > < version >2.3.1</ version > < configuration > < source >${java.source.version}</ source > < target >${java.source.version}</ target > </ configuration > </ plugin > </ plugins > </ build > </ project > |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| apply plugin: 'java' apply plugin: 'maven' group = 'ch.bbv.gradledemo' version = '0.0.1-SNAPSHOT' //the default artifact id is the project name, which is per default the directory name of the project project.ext.junitVersion= '4.8.2' sourceCompatibility = 1.7 targetCompatibility = 1.7 repositories { mavenCentral() } dependencies { testCompile 'junit:junit:' +junitVersion } |
IDE integration
The first thing I tried was the Gradle plug-in called ‘eclipse’ (it’s a bit unlucky that everything is now called plug-in). This plug-in can generate eclipse configuration files with settings, project and classpath. This works quite well but you have to update and refresh the project yourself after changing the build.gradle file.The opposite way around there are also plug-ins for eclipse. The first one is Groovy support so you can edit Groovy code in eclipse. The second one is the Gradle plug-in itself which manages the dependencies of your project, allows you to start Gradle tasks and more.
There is support for other IDEs as well. The current state of tooling can be found here: http://www.gradle.org/tooling
Documentation
Gradle comes with a comprehensive set of documentation including a user guide, reference material and even a book titled “Building and Testing with Gradle”. You can read the book online if you register on Gradleware’s web site. It’s a good read and covers all the stuff you need to get started with Gradle.The user guide documents all the parts of Gradle and will be continuously extended as Gradle grows. The reference material is generated Java/Groovy doc for Gradle’s API and DSL.
Conclusion
I see three scenarios where Gradle can be a good candidate for your build system.- If you are currently using Ant and the build.xmls get too complicated to handle. With the task based build and the support for existing Ant tasks, Gradle support the migration from Ant.
- You have trouble to get Maven to do what you want and maybe already started to write your own Maven plug-ins. Gradle supports the convention over configuration paradigm similar to Maven but can also be scripted with Groovy to do more powerful stuff.
- You start a new project.
Even though it has a bit of a steep learning curve it is worth a closer look.
No comments:
Post a Comment