All About Gradle

Craig Burke

About Me

  • Groovy/Grails Developer at Carnegie Mellon

  • Author of the Karma / Bower Installer Gradle Plugins

  • www.craigburke.com

  • @craigburke1

  • @groovypgh

What is Gradle?

Powerful build tool with:

  • Groovy DSL

  • Dependency management

  • Support for many languages/platforms

  • Plugins

  • A terrible website

Groovy Fundamentals

Groovy Features

  • Simple Syntax (Less Noise)

  • Operator Overloading

  • Scripting Support

  • Meta-Programming

Syntactic Sugar

Maps and lists
Map map = [language: 'Groovy']
List list = ['foo', 'bar']
Command chaining and optional parenthesis
// equivalent to: say(hello).to('Craig')
say hello to 'Craig'

Operator Overloading

a + b

a.plus(b)

a - b

a.minus(b)

a * b

a.multiply(b)

a ** b

a.power(b)

a / b

a.div(b)

a % b

a.mod(b)

a | b

a.or(b)

a & b

a.and(b)

a ^ b

a.xor(b)

a or a

a.next()

a-- or --a

a.previous()

a << b

a.leftShift(b)

a >> b

a.rightShift(b)

a <⇒ b

a.compareTo(b)

The MetaClass

  • Every class in Groovy has a corresponding metaClass

  • Class instances can also have custom metaClasses

Closures

A first-class function that can be:

  • Passed as an argument

  • Assigned to a variable

  • Returned from a function

Closure Scope

this

instance of the class the closure was defined

owner

usually the same as this unless it was declared inside another closure

delegate

same as owner but can be reassigned

Getters and Setters

class Person {
  String name
  String nickName
}
Person person = new Person()
Equivilent to person.setName('Craig')
person.name = 'Craig'
Equivilent to println person.getName()
println person.name
Equivilent to person.setNickName(person.getName())
person.nickName = person.name

Dynamic Properties

Extending the Number class
Number.metaClass.getDollars = { delegate as BigDecimal }

Number.metaClass.getProperty = { String name ->
  def rates = [euros: 1.1f, pesos: 0.063f]
  delegate * (rates[name] as BigDecimal)
}
Adding different currencies together
def total = 20.dollars + 40.euros + 200.pesos
assert total == 76.60

Dynamic Methods

class Person {
  def methodMissing(String name, args) {
    if (name.startsWith('say')) {
      String message = (name - 'say').trim()
      println message
    }
  }
}
Trying out our dynamic method
Person you = new Person()
you.sayHello()
you."say Craig is Awesome"()

Getting Started with Gradle

Terminology

Task

an atomic piece of work

Project

collection of tasks

Build

one or more projects

Installing Gradle

  1. Use SDKMan!

  2. Download from gradle.org: http://gradle.org/gradle-download/

  3. Use Gradle wrapper

Create a New Project

  • Create a build.gradle file

  • Run gradle init

gradle init
gradle init --type groovy-library

Gradle Tasks

Defining a Task

task helloWorld {
    doLast {
        println 'Hello world!'
    }
}

Task phases

Configuration

run for all tasks everytime gradle is run

Execution

run only when a task is executed

Phase Example

task foo {
    println 'Configuration phase'

    doLast {
        println 'Execution phase'
    }
}

Alternate Syntax

Not recommended

task foo << {
    println "Execution phase"
}

task bar {
    println "Configuration phase"
} << {
    println "Execution phase"
}

Task Ordering

  • dependsOn

  • finalizedBy

  • shouldRunAfter

  • mustRunAfter

Building Java (Groovy) Projects

Apply Plugins

apply plugin: 'groovy'
apply plugin: 'java'

Adding Dependencies

apply plugin: 'java'

Main tasks

assemble

compiles and packages project (into a jar)

check

runs tests and verification tasks

build

runs both assemble and check

Adding dependencies

apply plugin: 'groovy'

repositories {
    mavenLocal()
    mavenCentral()
    jcenter()
}

dependencies {
    compile 'org.codehaus.groovy:groovy:2.4.5'
    testCompile group:'org.spockframework', name:'spock-core', version:'1.0-groovy-2.4'
}

Dependency configurations

compile

The dependencies required to compile the source of the project.

runtime

The dependencies required by the at runtime (includes compile time dependencies).

testCompile

The additional dependencies required to compile the tests the project (includes compile dependecies).

testRuntime

The dependencies required by the tests at runtime (includes testCompile and runtime dependecies).

Custom Plugins

Creating plugin

  • apply from file

  • Add a plugin code in buildSrc

  • Add a build dependency of published plugin

Build Classpath

Build classpath is distinct from application classpath

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.2'
    }
}

apply plugin: 'groovy'
apply plugin: 'com.github.johnrengelman.shadow'

repositories {
    jcenter()
}

dependencies {
    compile 'org.codehaus.groovy:groovy:2.4.5'
}

Useful Plugins

  • Gradle Shadow (johnrengelman/shadow)

  • Gradle SSH (int128/gradle-ssh-plugin)

  • Gradle Node (srs/gradle-node-plugin)

  • Bower Installer (craigburke/bower-installer-gradle)

Bower Installer

bower {
    installBase = 'src/assets/bower'

    'angular'('1.4.x')

    'angular-animate'('1.4.x') {
        source 'angular-animate.js' >> '/angular/modules/'
    }

    'bootstrap'('3.3.x') {
        source 'dist/css/*.min.css' >> 'styles/'
        source 'dist/fonts/**' >> 'fonts/'
        excludes 'jquery'
    }
}

Resources

Books

Presentations

Links

Thank You

parrot