Conditional Gradle Configuration by Build Variant

Conditional Gradle Configuration by Build Variant

Oliver Spryn
October 19, 2018

Leverage the advantages of Groovy to conditionally include and exclude entire Gradle plugins based on your build type, and keep your build times low.

Gradle is a powerful build tool that reigns as the dominant choice among Android developers. Despite its popularity, the complexity of fine-tuned optimizations can sometimes baffle newer engineers.

One circumstance had me and my team at UPMC Enterprises scratching our heads for weeks. We needed to conditionally include or exclude entire plugins and their associated configurations from our build based on the selected type or product flavor.

Establishing a Use Case from Experience

Anyone who uses Gradle should know that most builds include at least one plugin. For Android, at least, it is common to see these plugins applied at the top of a configuration file:

In many cases, these plugins are necessary. However, my team and I encountered a plugin that triplicated our build times each time we included it in our project, regardless of its settings.

The culprit, we found, was a plugin called Dynatrace. The only way we knew we could alleviate ourselves from unnecessarily long development builds was to comment it out each time or wait an extra precious four minutes. No amount of hiding this plugin inside of `buildTypes` or `productFlavors` kept it from running.

Thus, we established our need to include or exclude code in our Gradle file conditionally.

A Fundamental Misunderstanding

Forcing a plugin and its relevant configuration to the confines of product flavor or build type may seem like the logical path forward. It certainly did to my team.

We failed to understand how Gradle operates. Before compiling any code, it evaluates each product flavor and build type as it calculates a task graph for subsequent execution during compilation. Therefore, even though we hid Dynatrace inside of only a few variants, it still ran and imported the plugin regardless of our selected build type.

Gradle Task Nomenclature

Before diving into our solution, it is essential to know how Gradle structures its variant-specific tasks. Consider this snippet:

One might run this simple command on CI machine without a second thought, but the naming convention makes it quite clear what the task is expected to do. It breaks down like this:

<task name> + (<product flavor> + <build type>) =
<task name> + <build variant>

In our project, we have several product flavors:

  • `noDynatrace`
  • `dynatraceDev`
  • `dynatraceProd`

… and several build types:

  • `debug`
  • `staging`
  • `release`

Therefore, I know that I can run the variant-specific task `assemble` with a `noDynatrace` flavor and in `debug` mode with `assembleNoDynatraceDebug`. The build console in Android Studio clearly shows this name.

The build variant window in Android Studio, highlighting the selected noDynatraceDebug variant

This information supplied the final clue we needed to optimize our build time.

The Solution

The name of the task, which was assembleNoDynatraceDebug, in our case, is passed as a parameter to the Gradle script. Therefore, it is only necessary to verify the task name to make our important decision. Since Gradle configuration scripts are simply Groovy files at heart, this task became trivial.

Since we only pass a single task to our build tool, the solution was a simple as:

Conclusion

Our initial attempt to hide the offending code in a `productFlavor` or `buildType` block failed to improve our build times. We did not realize Gradle evaluated every block during the task graph calculation phase.

However, once we learned that the task name was available to us within the script, we were able to use some plain old Groovy to filter out the plugin and regain our precious four minutes.

ABOUT THE AUTHOR
Oliver Spryn

I'm teaching 100k how to fast-track their Android development process to build chart-topping apps the right way, the first time. Subscribe on Twitter or LinkedIn for daily engineering tips and on YouTube for weekly in-depth Android tutorials.

YouTube logoTwitter logoLinkedIn logo
Go Further

Jump ahead 5 years, right now

Build your next Android app in less time, the right way, the first time

Free 15-min consult

1 on 1 assitance

Access premium courses

Get Access