18 Mar 2015 · Software Engineering

    Introduction to Gradle

    8 min read
    Contents

    Gradle is a free Java build tool for project automation, similar to Ant and Maven. It’s used by software developers working in Java for running common repetitive tasks in project lifecycle, like compiling code, resolving dependencies, packaging, unit testing, code execution and deployment. Google positioned Gradle as the build system of choice for Android and integrated it in Android Studio.

    Gradle combines approaches of Ant and Maven providing a middle ground between configuration and convention. Gradle is compatible with both, as you can use the existing Ant tasks and Maven repositories. Projects are auto-configured with sensible defaults, but the configuration can be easily changed.

    Unlike Ant and Maven which use XML for scripting, Gradle uses Groovy, a Domain Specific Language that’s a subset of Java with plenty of syntactic sugar. That makes the scripts much more concise and expressive. Learning Groovy is not required as you can use plain Java, but it helps.

    All the project build configuration goes into build.gradle file, an executable Groovy script which runs when you issue gradle someTask command.

    Installing Gradle

    Gradle requires Java JDK/JRE 6 or higher. To download Gradle go to the Gradle download page and download the binaries and unpack them where you want the application to reside.

    After that open your .bash_profile or .bashrc file and add the bin folder from the unpacked Gradle folder to you PATH system variable.

    So if you unpacked it in your home directory under gradle folder you add the following:

    export PATH="$PATH":~/gradle/bin
    

    Now Gradle should be available from the command line. To check run:

    gradle -v
    

    Helpful commands

    Gradle provides many common tasks out-of-the-box by convention. To see output of all the available tasks go to your project folder and run:

    gradle tasks --all
    

    For more information on the options and flags:

    gradle --help
    

    To see details of structure and state of the current build run:

    gradle properties
    

    Gradle ships with GUI which you can get to by:

    gradle --gui
    

    Building with Gradle

    When building Gradle first looks for a build configuration script build.gradle in the directory and evaluates the script. After that it executes the task and any related dependency.

    Gradle uses several configuration files:

    • build.gradle specifies a project and its tasks.
    • gradle.properties configures the properties of the build.
    • gradle.settings describes which projects participate in multi-project build

    When creating a new project you can let Gradle create build.gradle and other helpful files by running:

    gradle init
    

    Typical Java project usually requires source compilation, unit testing and Jar file packaging. Those default tasks are available just by declaring a plugin that ships with Gradle in build script. Open build.gradle and make sure that following line is present:

    apply plugin: 'java'

    Run gradle tasks again and you should get much more tasks.

    Some of the more common tasks are:

    • gradle build for full build including compilation, testing and packaging
    • gradle test compiles the source file, the test file and executes the test
    • gradle compileJava compiles the source code
    • gradle clean deletes build directory
    • gradle assemble build without testing
    • gradle check compilation and test only
    • gradle run runs project as JVM application

    Note: To be able to run the application be sure to add apply plugin: 'application' and specify the main class for execution mainClassName = 'yourPackage.MainClass' in build.gradle.

    A minimal working build.gradle for a simple HelloWorld applciation would be very simple:

    apply plugin: 'java'
    apply plugin: 'application'
    
    mainClassName = 'main.java.HelloWorld'

    Gradle by convention expects the following directory structure in your project:

    • src/main/java for production source code
    • src/test/java for test source code
    • src/main/resources will be included in the JAR file as resources
    • src/test/resources will be included in the classpath used to run the tests
    • build where Gradle outputs the build (compiled classes, jars, dependencies)

    If you just need to evaluate and run build file without any tasks executing add --dry-run or -m flag. Another helpful flag is --debug or -d for generating a lot more output and troubleshooting build problems.

    Custom Tasks

    Tasks are named collections of build instructions that Gradle executes as it performs a build. If you have a specific build in mind you can create your own task, and use Groovy or regular Java for logic.

    To write a custom helloWorld task just define it inside build.gradle:

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

    There are alternative ways to do the same thing. A short form alternative is:

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

    Now you can run gradle helloWorld and see the output. Optionally add -q flag for log supression.

    You can add default task for the gradle command like this:

    defaultTasks 'helloWorld'

    To control task dependencies and order of their execution use this syntax:

    task introduction(dependsOn: helloWorld) << {
        println "I'm Gradle"
    }
    $ gradle introduction -q
    Hello world!
    I'm Gradle
    

    You can run tasks using their abbreviated camel-case form. For example you can run helloWorld like this:

    gradle hW
    

    You can run multiple tasks in one command, but each task gets executed only once. For example:

    $ gradle introduction helloWorld 
    Hello world!
    I'm Gradle
    

    Consult the user guide for :

    Project Dependencies

    If your Java project uses a non-standard library for extra functionality, then it’s considered a dependency. Gradle can use main Maven repository for resolving and managing those dependencies.

    Dependencies are downloaded when you run the build and are put in your local cache making them available to the project. Gradle figures out which dependencies need to be rebuilt so that they match the project requirement, making the code work on every machine regardless of its local cache.

    To add the repository and external dependencies just declare following in the build.gradle:

    repositories {
      mavenCentral()
    }
    
    dependencies {
      compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
      testCompile "junit:junit:4.12"
    }

    The first dependency, hibernate-core, uses a long form declaration and junit the short form. They both get retrieved from Maven repository.

    compile and testCompile represent dependency configuration. By declaring hibernate-core as a compile dependency we are telling Gradle it’s required to compile the production source of the project. On the other hand, testCompile is for dependencies required to compile the test source of the project.

    You can also define runtime dependencies. These would be dependencies required for your classes at runtime in production environment. testRuntime if you want to include testing.

    Read the user guide for more information on project dependencies.

    Gradle Wrapper

    Gradle Wrapper is script that allows you to run a Gradle build even if you don’t have Gradle installed. It downloads Gradle as a shell and batch scripts, and provides Gradle functionality as if you had it installed, without actually installing it. That way you don’t have to worry if other developers have Gradle installed on their local machines and what version.

    To enable it open build.gradle and add wrapper task like this:

    task wrapper(type: Wrapper) {
        gradleVersion = '1.11'
    }

    Now run gradle wrapper task to download and cache the Gradle binaries, and initialize the wrapper scripts. This adds following files in root of the project:

    project_root
    └── gradlew
    └── gradlew.bat
    └── gradle
        └── wrapper
            └── gradle-wrapper.jar
            └── gradle-wrapper.properties
    

    Now you can use wrapper scripts, gradlew for *nix and gradlew.bat for Windows, for build and not rely any longer on Gradle installation. Those scripts are meant to be included in your version control so that anyone can use them for the build.

    To execute build task using wrapper just run:

    ./gradlew build
    

    You can read more information about wrapper here.

    Using Daemon to increase performance

    Whenever you run a basic task it can take more than a few seconds to complete, and as your application grows it can become even slower. It is because everytime you run a Gradle command, JVM has to be started and all the code needs to be loaded in memory. There is a way to improve the performance and that is by using the Deamon.

    The Gradle Daemon is a Java process that runs your builds in the background on Gradle’s behalf, so you don’t need to start JVM and load all the Gradle classes every time you run a task. This cuts the startup and execution time and improves performance. This proves very useful if you invoke Gradle many times to execute a small number of relatively quick tasks.

    To use the Daemon you need to declare each time you want to run a task in it like this:

    gradle --daemon someTask
    

    When you use --daemon option, process will be active for several hours, after which it needs to be started again.

    If you want to run deamon by default for every task you have two ways to do it:

    1. Create gradle.properties file inside ~/.gradle/ folder and write org.gradle.daemon=true to it:

    echo 'org.gradle.daemon=true' > ~/.gradle/gradle.properties
    

    2. Set system variable GRADLE_OPTS to -Dorg.gradle.daemon=true in your .bash_profile or .bashrc:

    export GRADLE_OPTS="-Dorg.gradle.daemon=true"
    

    Now every task is run inside daemon. Note that it is still experimental feature and shouldn’t be relied to much in production mode.

    You can use --no-daemon explicitly to run a task without daemon.

    For more information read about The Gradle Daemon here.

    Useful Resources

    For more information on Gradle, read the official Gradle user guide. Some interesting topics include::

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Aleksandar Olić
    Writen by:
    Loves connecting wild ideas into a harmonious unit. Writer fusing classical thought with tech soul. You will find him either chilling or researching some new exciting concept.