Gradle Logo

Automation Evolved

Open Source by Gradleware (Apache 2.0 license)

Why another build tool

Build Enabler

  1. Defaults to Maven conventions
  2. Full integration with Ant
  3. DSL in Groovy
  4. Flexible dependency management
  5. Automation as well as build

Gradle's Anatomy

  • Projects
  • Tasks
  • Dependency Resolution
  • Lifecycle

Gradle Projects

  • "build.gradle" configures the project
  • Project provides the base DSL
  • Build steps are performed by Tasks
  • Plugins provide preconfigured tasks

Anatomy of a Task

Tasks perform an action
class GreetingTask extends DefaultTask {
    @TaskAction
    def greet() {
        println 'Hello World!'
    }
}
Adding the task to you build
task hello(type: GreetingTask)
Task output
$ gradle hello
:hello
Hello World!

BUILD SUCCESSFUL

Anatomy of a Task

Tasks dependencies control execution order
task helloAgain(type: GreetingTask, dependsOn: hello)
Task output
$ gradle helloAgain
:hello
Hello World!
:helloAgain
Hello World!

BUILD SUCCESSFUL

Anatomy of a Task

Add functions to "Do First"
task redundantGreeting(type: GreetingTask) {
    doFirst {
        println 'Hello Hello Hello'
    }
}
Task output
$ gradle redundantGreeting
:redundantGreeting
Hello Hello Hello
Hello World!

BUILD SUCCESSFUL

Anatomy of a Task

Add functions to "Do Last"
task helloAndGoodBye(type: GreetingTask) {
    doLast {
        println 'Goodbye World'
    }
}
Task output
$ gradle helloAndGoodbye
:helloAndGoodBye
Hello World!
Goodbye World

BUILD SUCCESSFUL

Anatomy of a Task

Tasks can be configurable
class ConfigurableGreetingTask extends DefaultTask {
    def person = 'World'
    @TaskAction
    def greet() {
        println "Hello ${person}!"
    }
}

task helloDuke(type: ConfigurableGreetingTask) {
    person = 'Duke'
}
Task output
$ gradle helloDuke
:helloDuke
Hello Duke!

BUILD SUCCESSFUL

Anatomy of a Task

The DSL is flexible
task version1(type: ConfigurableGreetingTask) {
    person = 'Duke'
    doFirst() {
        println 'Hello Everyone!'
    }
    doLast() {
        println "I hope you are having a good day ${person}"
    }
}
Identical
task version2(type: ConfigurableGreetingTask)
version2.person = 'Duke'
version2.doFirst() {
    println 'Hello Everyone!'
}
version2 << {
    println "I hope you are having a good day ${person}"
}

Anatomy of a Task

A task can be "finalized By" another task (incubating)
task cleanUp {
    doFirst() { println 'Cleanup executed' }
}
task fails {
    finalizedBy cleanUp
    doFirst() { throw new RuntimeException() }
}
Task output
$ gradle fails
:fails FAILED
:cleanUp
Cleanup executed

FAILURE: Build failed with an exception.
...

Artifact Dependency Management

Configurations
configurations {
    compile
    runtime {
        description = "Used at runtime but should not be inherited"
        extendsFrom compile
    }
}
configurations.compile {
    description = 'You can access an already declared configuration'
}

Artifact Dependency Management

Dependency Declarations
dependencies {
    compile 'org.slf4j:slf4j-api:1.7.5'
    runtime 'org.slf4j:slf4j-log4j12:1.7.5'
    runtime group: 'org.apache', name: 'tomcat', version: '7.0.34', ext: 'zip'
    compile files('libs/a.jar', 'libs/b.jar')
    compile("com.sun.jersey:jersey-json:1.12") {
        exclude group: 'stax', module: 'stax-api'
    }
}

Artifact Dependency Management

Repository Setup
repositories {
    mavenCentral()
    maven { url "http://repo.mycompany.com/maven2" }
    ivy { url "http://repo.mycompany.com/repo" }
    flatDir { dirs 'lib1', 'lib2' }
    localRepository { dirs 'lib' }
}

Plugins

To use a plugin:
apply plugin: 'example-plugin'
The plugin then:
configurations {
    pluginConf
}
class PluginTask extends DefaultTask {
    @TaskAction
    def action() {
        def deps = project.configurations.pluginConf.allDependencies
        ... do something ...
    }
}
task pluginTask(type: PluginTask)

The Java Plugin

The Java Plugin Task graph

Project Extensions

Source Sets
apply plugin: 'java'

sourceSets {
    newCode
}
New Tasks
$ gradle tasks --all
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
...
newCodeClasses - Assembles binary 'newCode'.
...
    compileNewCodeJava - Compiles source set 'newCode:java'.
    processNewCodeResources - Processes source set 'newCode:resources'.
...
BUILD SUCCESSFUL

Built in plugins *

  • Language plugins - Java, Scala, Groovy, Antlr, cpp
  • Integration plugins - war, jetty, ear, osgi, maven
  • Code Quality - checkstyles, codenarc, findbugs, jdepend, pmd
  • Development Support - sonar, eclipse, idea

Build Lifecycle

  • Initialization - find all the files
  • Configuration - parse the build file's configuration
  • Execution - execute the task graph
Manual Webapp Setup
jettyRun {
    copy {
        from 'src/bdd/resources/web.xml'
        into "${buildDir}/webapp/WEB-INF"
    }
}
Fixed
jettyRun {
    doFirst {
        copy {
            from 'src/bdd/resources/web.xml'
            into "${buildDir}/webapp/WEB-INF"
        }
    }
}

Examples