State of the Android Gradle Build System
May 2, 2013 | 4 min ReadBuilding an Android project can be challenging at times. The Android SDK ships with a set of helpful ant scripts, but has its shortcomings. It mainly lacks a well-populated dependency infrastructure similar to what maven offers (ivy doesn’t count). Hence, the natural evolution of build process spawned the maven android plugin. The plugin allows you to infuse maven artifacts and perform the necessary build steps to package your app. Although maven has a great artifact repository, it has a pretty rigid set of configuration settings. The pom files tend to get verbose and interfering with the designated build process lacks flexibility.
The “New Build System”
Entering the “New Build System” based on Gradle. The new build system is supposed to become the official mechanism for building Android applications. The gradle-based build combines some of the strengths of ant and maven (flexible architecture with a lot of custom tweaking opportunities), whilst at the same time providing reasonable default configurations to keep the build scripts small. Maven dependencies can be consumed from maven central, while it is also easy to consume “local file” dependencies.
Okay, but how does the “New Build System” prevail in practice?
Using the Gradle Android Build
DISCLAIMER: We are only a few days away from Google IO 2013 so the points raised here might have already changed when you read this.
Basic build scripts can be really really small when you rely on the default folder structure for your project. Your basic gradle build script can look like this:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.3'
}
}
apply plugin: 'android'
In fact the buildscript{} element is only required to bootstrap the script itself. The actual content is the lonely apply plugin: 'android'
. Running this script produces a fully runnable unsigned apk.
The basics are simple but what about dependencies? As I mentioned, you can easily add dependencies from maven central or a local file. In fact, the buildscript downloads its own android tasks from maven central.
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.guava:guava:11.0.2'
compile files ('libs/gcm.jar')
}
The compile
directive is similar to mavens compile
scope in that the dependency will be bundled into your packaged .apk.
Gradle also supports Android library projects. The “New Build System” compiles library projects into .aar packages, which can be consumed by the main project. The main advantage of the .aar format is its ability to handle dynamic Android resource ids. You will be able to ship an *.aar archive and consume it in your main project without having to create all of its ids during compile time of the main project.
Library projects have to be listed in a settings.gradle
file and all projects taking part in the build can reference any other project listed in that file.
Where the gradle build has its real strength is in creating multiple versions of the same app. For example, a free and a paid version, or different versions for various cpu architectures. I won’t go into detail but you should read all about it in this user guide.
[ Want to develop mobile apps faster? Try Tabris. Download the 30-day trial. ]
Shortcomings
Now that we have discussed some of the strengths of the gradle build system, lets discuss some of the pitfalls:
The gradle build is not yet able to deal with the most common dependency format for library projects: the maven apklib. Currently you can only consume maven artifacts that are packaged as jars. This rules out a lot of high profile dependencies such as the actionbarsherlock or the viewpagerindicator. If you want to depend on these resources you will have to keep a source reference in your project (or package them as an .aar).
The gradle build system offers good support for instrumentation tests you run on your device, but it is currently very hard to run standalone robolectric tests. The main problem is that robolectric does not understand the gradle dependencies so that it cannot gather sub-dependencies, and so on.
Support for the Android Development Tools (ADT) is currently non-existent although this is very likely to change with future releases. The ADT cannot deal with the default folder layout by gradle, nor can it deal with declared dependencies. Therefore, you have to maintain two build infrastructures: one for Eclipse (project.properties etc) and one for the gradle build.
Wrap Up
The “New Build System” build sounds awesome! As long as it can deliver on all its promises. At the moment, I can not recommend it for larger projects due to the lack of robolectric support and problems with maven dependencies. I have discussed the issues raised here with +Xavier Ducrohet, the lead architect of the build system, and he assured me that most of the issues will be addressed. At the Droidcon Berlin I spoke to Hans Dockter, the CEO of Gradleware and co-architect of the “New Build System”, and once gradle becomes the driving engine for the ADT the entire toolchain should be covered. If the Android library ecosystem were to adapt gradle, it would have a very bright future.