Stop generating the BuildConfig on your Android modules
Why generating the BuildConfig class is a bad idea

This article will explain why I believe that generating the BuildConfig
class for Android library modules is a bad idea. It’s important to highlight that I am not talking about the app module BuildConfig
, I am talking about all the other BuildConfig
files generated by each android module.
First of all, I would like to clarify some terms, so you better understand this article:
- when I say
debug
code, I am talking about the code available on the local builds used by developers when they pick thedebug
variant. It is typically located atsrc/main
&src/debug
source sets. - when I say
release
code, I am talking about the code distributed on your release APK/AAB. It means therelease
variant. It is typically located atsrc/main
&src/release
source sets.
The Reasons
These are the main reasons to disable BuildConfig.java
generation:
- Generating the
BuildConfig
file for each module has a build speed penalty BuildConfig
is generated as a Java file. But having a module with mixedJava
&Kotlin
code impacts on build speed. You can read more about this, in this great article.- Having a
BuildConfig
per module could be confusing for developers when they need to pick which one to use BuildConfig
presence stimulates developers to useBuildConfig.DEBUG
and havedebug
code mixed withrelease
code
The last reason is very important, so I would like to clarify it.
The more common usage of theBuildConfig
is to do something like this:
if (BuildConfig.DEBUG) {
// do something for debug only
}
But that kind of logic has some issues:
- It adds complexity to your code because you have mixed
release
&debug
logic in the same place. - It stimulates developers to add more
debug
code in thesrc/main
source set. This is not good, the code you use in your local environment (debug variant) should be as close as possible to your production code (release variant). - This could potentially increase the size of your production code. I say “potentially” because after some compiler optimizations + Proguard/R8 most of the debug code will be probably removed from the released AAB.
- If you decide to migrate your module code to an external android library, you are not going to be able to continue using
BuildConfig.DEBUG
, because you probably are going to have just one variant of your library published on a maven repository.
The proposal
As a first step, you could migrate all your debug
code from the src/main
to the src/debug
source set.
Remember that all the code you put on the src/debug
is not going to be included on the release APK/AAB.
You can use some tricks like class overriding between different variants. For example:
On src/main/com/sample/App.kt
class App {
fun doSomething() {
Executor.execute()
}
}
On src/debug/com/sample/Executor.kt
class Excecutor {
fun execute() {
// This code will be executed only on the debug APK/AAB
}
}
On src/release/com/sample/Executor.kt
class Executor {
fun execute() {
// This code will be executed only on the release APK/AAB
}
}
As you can see, with that approach your debug
and release
code is properly separated, giving clarity to your code. According to the picked variant, the proper Executor
class will be used.
You can use the same approach if, for example, you need to use different backend URLs for debug
& release
and you are currently configuring them on a module’s BuildConfig
. For example:
On src/debug/com/sample/Server.kt
object Server {
const val SERVER_URL = "http://dev.sample.com"
}
On src/release/com/sample/Server.kt
object Server {
const val SERVER_URL = "http://production.sample.com"
}
Once you finished with the migration of all the debug
code, you can configure your gradle.properties
to stop generating the BuildConfig
file by default on all your android modules:
android.defaults.buildfeatures.buildconfig = false
Take into account that the BuildConfig
on your app
module is useful. It has the app version code, version name, application id and any custom flag you decided to add. So, I recommend to keep it (but remember to avoid using BuildConfig.DEBUG
). So, to override the default behavior defined on gradle.properties
, just add the following configuration to yourapp/build.gradle
android {
buildFeatures {
buildConfig = true
}
}
After that, you will only have one generatedBuildConfig
for the whole app and your code will be properly distributed between debug
& release
source sets.
You can follow our Dipien
Medium Publication for more productivity tools & ideas for Android, Kotlin & Gradle developers.
If you enjoyed this article, you might get value out of these as well!