A plugin for generating BuildConstants for any kind of Gradle projects: Java, Kotlin, Groovy, etc. Designed for KTS scripts.
890
stars
494
commits
Kotlin
primary language
Sep 7, 2026
updated
A plugin for generating BuildConstants for any kind of Gradle projects: Java, Kotlin, Android, Groovy, etc. Designed for KTS scripts, with experimental support for Kotlin's multi-platform plugin
On your build.gradle.kts add:
plugins {
id("org.jetbrains.kotlin.jvm") version "<kotlin version>"
id("com.github.gmazzo.buildconfig") version "<current version>"
}
buildConfig {
buildConfigField("APP_NAME", project.name)
buildConfigField("APP_VERSION", provider { "\"${project.version}\"" })
buildConfigField("APP_SECRET", "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu")
buildConfigField<String>("OPTIONAL", null)
buildConfigField("FEATURE_ENABLED", true)
buildConfigField("MAGIC_NUMBERS", intArrayOf(1, 2, 3, 4))
buildConfigField("STRING_LIST", arrayOf("a", "b", "c"))
buildConfigField("MAP", mapOf("a" to 1, "b" to 2))
buildConfigField("FILE", File("aFile"))
buildConfigField("URI", uri("https://example.io"))
buildConfigField("com.github.gmazzo.buildconfig.demos.kts.SomeData", "DATA", "SomeData(\"a\", 1)")
}
Will generate BuildConfig.kt:
internal object BuildConfig {
internal const val APP_NAME: String = "kts"
internal const val APP_VERSION: String = "\"0.1.0-demo\""
internal const val APP_SECRET: String = "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu"
internal val OPTIONAL: String? = null
internal const val FEATURE_ENABLED: Boolean = true
internal val MAGIC_NUMBERS: IntArray = intArrayOf(1, 2, 3)
internal val STRING_LIST: Array<String> = arrayOf("a", "b", "c")
internal val MAP: Map<String, Int> = mapOf("a" to 1, "b" to 2)
internal val FILE: File = java.io.File("aFile")
internal val URI: URI = java.net.URI.create("https://example.io")
internal val DATA: SomeData = SomeData("a", 1)
}
On your build.gradle add:
plugins {
id 'java'
id 'com.github.gmazzo.buildconfig' version < current version >
}
buildConfig {
buildConfigField(String, 'APP_NAME', project.name)
buildConfigField(String, "APP_VERSION", provider { project.version })
buildConfigField(String, 'APP_SECRET', "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu")
buildConfigField(String, 'OPTIONAL', null)
buildConfigField(boolean, 'FEATURE_ENABLED', true)
buildConfigField(int[], "MAGIC_NUMBERS", [1, 2, 3])
buildConfigField('List<String>', "STRING_LIST", ["a", "b", "c"])
buildConfigField(Map.class, "MAP", [a: 1, b: 2])
buildConfigField(File.class, "FILE", new File("aFile"))
buildConfigField(URI.class, "URI", uri("https://example.io"))
buildConfigField("com.github.gmazzo.buildconfig.demos.groovy.SomeData", "DATA", "new SomeData(\"a\", 1)")
}
Will generate BuildConfig.java:
final class BuildConfig {
public static final String APP_NAME = "groovy";
public static final String APP_VERSION = "0.1.0-demo";
public static final String APP_SECRET = "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu";
public static final String OPTIONAL = null;
public static final boolean FEATURE_ENABLED = true;
public static final int[] MAGIC_NUMBERS = {1, 2, 3};
public static final String[] STRING_LIST = {"a", "b", "c"};
public static final Map<String, Integer> MAP = java.util.Map.of("a", 1, "b", 2);
public static final File FILE = new java.io.File("aFile");
public static final URI URI = java.net.URI.create("https://example.io");
public static final SomeData DATA = new SomeData("a", 1);
}
If you add in your build.gradle.kts:
buildConfig {
className("MyConfig") // forces the class name. Defaults to 'BuildConfig'
packageName("com.foo") // forces the package. Defaults to '${project.group}'
useJavaOutput() // forces the outputType to 'java'
useKotlinOutput() // forces the outputType to 'kotlin', generating an `object`
useKotlinOutput {
topLevelConstants = true
} // forces the outputType to 'kotlin', generating top-level declarations
useKotlinOutput { internalVisibility = false } // makes `BuildConfig` class `public` (defaults to `internal`)
}
Will generate com.foo.MyConfig in a MyConfig.java file.
Sometimes one generated does not fits your needs or code style. You may add multiple classes with the following syntax:
buildConfig {
buildConfigField("FIELD1", "field1")
forClass("OtherClass") {
buildConfigField("FIELD2", "field2")
}
forClass(packageName = "", className = "RootConfig") {
buildConfigField("FIELD3", "field3")
}
}
Will generate the files:
com.github.gmazzo.BuildConfigcom.github.gmazzo.OtherClassRootConfig (in the root package)On your build.gradle.kts add:
buildConfig {
useKotlinOutput { topLevelConstants = true }
buildConfigField("APP_NAME", project.name)
buildConfigField("APP_VERSION", provider { project.version })
}
Will generate BuildConfig.kt:
const val APP_NAME: String = "example-kts"
const val APP_VERSION: String = "0.0.1"
expect/actual support on Kotlin Multiplatform projectsSimilar to Android's buildConfigField, you can consume an expect BuildConfig class from common code,
and provide different values for each platform target:
buildConfig {
buildConfigField("COMMON_VALUE", "aCommonValue") // any constant value will be automatically 'expect'ed and propagated to the actual classes
buildConfigField("IS_MOBILE", expect(false)) // with a default
buildConfigField("PLATFORM", expect<String>()) // without a default
sourceSets.named("androidMain") {
buildConfigField("PLATFORM", "android")
buildConfigField("IS_MOBILE", true)
buildConfigField("ANDROID_VALUE", "anAndroidValue")
}
sourceSets.named("jvmMain") {
buildConfigField("PLATFORM", "jvm")
buildConfigField("JVM_VALUE", "aJVMValue")
}
}
It will generate at commonMain:
expect object BuildConfig {
val COMMON_VALUE: String
val IS_MOBILE: Boolean
val PLATFORM: String
}
At androidMain sourceSet:
actual object BuildConfig {
actual const val COMMON_VALUE: String = "aCommonValue"
actual const val PLATFORM: String = "android"
actual const val IS_MOBILE: Boolean = true
const val ANDROID_VALUE: String = "anAndroidValue"
}
And at jvmMain sourceSet:
actual object BuildConfig {
actual const val COMMON_VALUE: String = "aCommonValue"
actual const val PLATFORM: String = "jvm"
actual const val IS_MOBILE: Boolean = false
const val JVM_VALUE: String = "aJVMValue"
}
[!NOTE] This is only available for Kotlin Multiplatform projects, since it relies on
expect/actualmechanism.
On your build.gradle.kts add:
buildConfig {
documentation.set("Generated by BuildConfig plugin")
}
[!NOTE]
documentationapplies independently for each generated class
By default, all BuildConfigTasks will be run as part of the Gradle Sync phase, to improve the developer experiece by
having always an up-to-date version of the generated BuildConfig classes.
You can turn this behavior by setting the com.github.gmazzo.buildconfig.generateAtSync property to false in your
gradle.properties file or by using the extension DSL:
buildConfig {
generateAtSync = false
}
If you add in your build.gradle.kts:
buildConfig {
sourceSets.getByName("test") {
buildConfigField("TEST_CONSTANT", "aTestValue")
}
}
Will generate in TestBuildConfig.kt:
object TestBuildConfig {
const val TEST_CONSTANT: String = "aTestValue"
}
sourceSets {
test {
buildConfig {
buildConfigField(String, 'TEST_CONSTANT', 'aTestValue')
}
}
}
Assuming you have the following structure:
myproject
- src
- main
- resources
- config
- local.properties
- prod.properties
- file1.json
- file1.json
If you add in your build.gradle.kts:
buildConfig.forClass("BuildResources") {
buildConfigField("A_CONSTANT", "aConstant")
sourceSets["main"].resources.asFileTree.visit {
if (!isDirectory) {
val name = path.uppercase().replace("\\W".toRegex(), "_")
buildConfigField(name, File(path))
}
}
}
Will generate in BuildResources.kt:
object BuildResources {
val CONFIG_LOCAL_PROPERTIES: File = File("config/local.properties")
val CONFIG_PROD_PROPERTIES: File = File("config/prod.properties")
val FILE1_JSON: File = File("file1.json")
val FILE2_JSON: File = File("file2.json")
}
def buildResources = buildConfig.forClass("BuildResources")
def generateResourcesConstants = tasks.register("generateResourcesConstants") {
def resources = sourceSets["main"].resources.asFileTree
inputs.files(resources)
doFirst {
resources.visit { file ->
def name = file.path.toUpperCase().replaceAll("\\W", "_")
buildResources.buildConfigField("java.io.File", name, "new File(\"$file.path\")")
}
}
}
tasks.generateBuildConfigClasses {
dependsOn(generateResourcesConstants)
}
Will generate in BuildResources.java:
public static final File CONFIG_LOCAL_PROPERTIES = new File("config/local.properties");
public static final File CONFIG_PROD_PROPERTIES = new File("config/prod.properties");
public static final File FILE2_JSON = new File("file2.json");
public static final File FILE1_JSON = new File("file1.json");
Kotlin
91.2%
Java
8.8%
A plugin for generating BuildConstants for any kind of Gradle projects: Java, Kotlin, Groovy, etc. Designed for KTS scripts.
890
stars
494
commits
Kotlin
primary language
Sep 7, 2026
updated
A plugin for generating BuildConstants for any kind of Gradle projects: Java, Kotlin, Android, Groovy, etc. Designed for KTS scripts, with experimental support for Kotlin's multi-platform plugin
On your build.gradle.kts add:
plugins {
id("org.jetbrains.kotlin.jvm") version "<kotlin version>"
id("com.github.gmazzo.buildconfig") version "<current version>"
}
buildConfig {
buildConfigField("APP_NAME", project.name)
buildConfigField("APP_VERSION", provider { "\"${project.version}\"" })
buildConfigField("APP_SECRET", "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu")
buildConfigField<String>("OPTIONAL", null)
buildConfigField("FEATURE_ENABLED", true)
buildConfigField("MAGIC_NUMBERS", intArrayOf(1, 2, 3, 4))
buildConfigField("STRING_LIST", arrayOf("a", "b", "c"))
buildConfigField("MAP", mapOf("a" to 1, "b" to 2))
buildConfigField("FILE", File("aFile"))
buildConfigField("URI", uri("https://example.io"))
buildConfigField("com.github.gmazzo.buildconfig.demos.kts.SomeData", "DATA", "SomeData(\"a\", 1)")
}
Will generate BuildConfig.kt:
internal object BuildConfig {
internal const val APP_NAME: String = "kts"
internal const val APP_VERSION: String = "\"0.1.0-demo\""
internal const val APP_SECRET: String = "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu"
internal val OPTIONAL: String? = null
internal const val FEATURE_ENABLED: Boolean = true
internal val MAGIC_NUMBERS: IntArray = intArrayOf(1, 2, 3)
internal val STRING_LIST: Array<String> = arrayOf("a", "b", "c")
internal val MAP: Map<String, Int> = mapOf("a" to 1, "b" to 2)
internal val FILE: File = java.io.File("aFile")
internal val URI: URI = java.net.URI.create("https://example.io")
internal val DATA: SomeData = SomeData("a", 1)
}
On your build.gradle add:
plugins {
id 'java'
id 'com.github.gmazzo.buildconfig' version < current version >
}
buildConfig {
buildConfigField(String, 'APP_NAME', project.name)
buildConfigField(String, "APP_VERSION", provider { project.version })
buildConfigField(String, 'APP_SECRET', "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu")
buildConfigField(String, 'OPTIONAL', null)
buildConfigField(boolean, 'FEATURE_ENABLED', true)
buildConfigField(int[], "MAGIC_NUMBERS", [1, 2, 3])
buildConfigField('List<String>', "STRING_LIST", ["a", "b", "c"])
buildConfigField(Map.class, "MAP", [a: 1, b: 2])
buildConfigField(File.class, "FILE", new File("aFile"))
buildConfigField(URI.class, "URI", uri("https://example.io"))
buildConfigField("com.github.gmazzo.buildconfig.demos.groovy.SomeData", "DATA", "new SomeData(\"a\", 1)")
}
Will generate BuildConfig.java:
final class BuildConfig {
public static final String APP_NAME = "groovy";
public static final String APP_VERSION = "0.1.0-demo";
public static final String APP_SECRET = "Z3JhZGxlLWphdmEtYnVpbGRjb25maWctcGx1Z2lu";
public static final String OPTIONAL = null;
public static final boolean FEATURE_ENABLED = true;
public static final int[] MAGIC_NUMBERS = {1, 2, 3};
public static final String[] STRING_LIST = {"a", "b", "c"};
public static final Map<String, Integer> MAP = java.util.Map.of("a", 1, "b", 2);
public static final File FILE = new java.io.File("aFile");
public static final URI URI = java.net.URI.create("https://example.io");
public static final SomeData DATA = new SomeData("a", 1);
}
If you add in your build.gradle.kts:
buildConfig {
className("MyConfig") // forces the class name. Defaults to 'BuildConfig'
packageName("com.foo") // forces the package. Defaults to '${project.group}'
useJavaOutput() // forces the outputType to 'java'
useKotlinOutput() // forces the outputType to 'kotlin', generating an `object`
useKotlinOutput {
topLevelConstants = true
} // forces the outputType to 'kotlin', generating top-level declarations
useKotlinOutput { internalVisibility = false } // makes `BuildConfig` class `public` (defaults to `internal`)
}
Will generate com.foo.MyConfig in a MyConfig.java file.
Sometimes one generated does not fits your needs or code style. You may add multiple classes with the following syntax:
buildConfig {
buildConfigField("FIELD1", "field1")
forClass("OtherClass") {
buildConfigField("FIELD2", "field2")
}
forClass(packageName = "", className = "RootConfig") {
buildConfigField("FIELD3", "field3")
}
}
Will generate the files:
com.github.gmazzo.BuildConfigcom.github.gmazzo.OtherClassRootConfig (in the root package)On your build.gradle.kts add:
buildConfig {
useKotlinOutput { topLevelConstants = true }
buildConfigField("APP_NAME", project.name)
buildConfigField("APP_VERSION", provider { project.version })
}
Will generate BuildConfig.kt:
const val APP_NAME: String = "example-kts"
const val APP_VERSION: String = "0.0.1"
expect/actual support on Kotlin Multiplatform projectsSimilar to Android's buildConfigField, you can consume an expect BuildConfig class from common code,
and provide different values for each platform target:
buildConfig {
buildConfigField("COMMON_VALUE", "aCommonValue") // any constant value will be automatically 'expect'ed and propagated to the actual classes
buildConfigField("IS_MOBILE", expect(false)) // with a default
buildConfigField("PLATFORM", expect<String>()) // without a default
sourceSets.named("androidMain") {
buildConfigField("PLATFORM", "android")
buildConfigField("IS_MOBILE", true)
buildConfigField("ANDROID_VALUE", "anAndroidValue")
}
sourceSets.named("jvmMain") {
buildConfigField("PLATFORM", "jvm")
buildConfigField("JVM_VALUE", "aJVMValue")
}
}
It will generate at commonMain:
expect object BuildConfig {
val COMMON_VALUE: String
val IS_MOBILE: Boolean
val PLATFORM: String
}
At androidMain sourceSet:
actual object BuildConfig {
actual const val COMMON_VALUE: String = "aCommonValue"
actual const val PLATFORM: String = "android"
actual const val IS_MOBILE: Boolean = true
const val ANDROID_VALUE: String = "anAndroidValue"
}
And at jvmMain sourceSet:
actual object BuildConfig {
actual const val COMMON_VALUE: String = "aCommonValue"
actual const val PLATFORM: String = "jvm"
actual const val IS_MOBILE: Boolean = false
const val JVM_VALUE: String = "aJVMValue"
}
[!NOTE] This is only available for Kotlin Multiplatform projects, since it relies on
expect/actualmechanism.
On your build.gradle.kts add:
buildConfig {
documentation.set("Generated by BuildConfig plugin")
}
[!NOTE]
documentationapplies independently for each generated class
By default, all BuildConfigTasks will be run as part of the Gradle Sync phase, to improve the developer experiece by
having always an up-to-date version of the generated BuildConfig classes.
You can turn this behavior by setting the com.github.gmazzo.buildconfig.generateAtSync property to false in your
gradle.properties file or by using the extension DSL:
buildConfig {
generateAtSync = false
}
If you add in your build.gradle.kts:
buildConfig {
sourceSets.getByName("test") {
buildConfigField("TEST_CONSTANT", "aTestValue")
}
}
Will generate in TestBuildConfig.kt:
object TestBuildConfig {
const val TEST_CONSTANT: String = "aTestValue"
}
sourceSets {
test {
buildConfig {
buildConfigField(String, 'TEST_CONSTANT', 'aTestValue')
}
}
}
Assuming you have the following structure:
myproject
- src
- main
- resources
- config
- local.properties
- prod.properties
- file1.json
- file1.json
If you add in your build.gradle.kts:
buildConfig.forClass("BuildResources") {
buildConfigField("A_CONSTANT", "aConstant")
sourceSets["main"].resources.asFileTree.visit {
if (!isDirectory) {
val name = path.uppercase().replace("\\W".toRegex(), "_")
buildConfigField(name, File(path))
}
}
}
Will generate in BuildResources.kt:
object BuildResources {
val CONFIG_LOCAL_PROPERTIES: File = File("config/local.properties")
val CONFIG_PROD_PROPERTIES: File = File("config/prod.properties")
val FILE1_JSON: File = File("file1.json")
val FILE2_JSON: File = File("file2.json")
}
def buildResources = buildConfig.forClass("BuildResources")
def generateResourcesConstants = tasks.register("generateResourcesConstants") {
def resources = sourceSets["main"].resources.asFileTree
inputs.files(resources)
doFirst {
resources.visit { file ->
def name = file.path.toUpperCase().replaceAll("\\W", "_")
buildResources.buildConfigField("java.io.File", name, "new File(\"$file.path\")")
}
}
}
tasks.generateBuildConfigClasses {
dependsOn(generateResourcesConstants)
}
Will generate in BuildResources.java:
public static final File CONFIG_LOCAL_PROPERTIES = new File("config/local.properties");
public static final File CONFIG_PROD_PROPERTIES = new File("config/prod.properties");
public static final File FILE2_JSON = new File("file2.json");
public static final File FILE1_JSON = new File("file1.json");
Kotlin
91.2%
Java
8.8%