Sering kali kita ingin menghasilkan beberapa versi build dari satu basis kode: versi debug dengan logging ekstra, versi release yang dioptimasi, atau versi free dan pro dengan fitur berbeda. Gradle menyediakan mekanisme build variants untuk mengelola hal ini. Konsep ini paling matang di Android Gradle Plugin, tetapi prinsipnya berlaku juga untuk proyek Kotlin/JVM murni. Pada chapter ini kita akan membahas konsep buildType, flavor, variant, serta bagaimana source set per variant diorganisir.
Konsep Build Variants #
Tiga konsep yang saling membentuk:
- Build type: tipe build berdasarkan tujuan pengembangan. Default:
debugdanrelease. Build type menentukan optimisasi compiler, debuggable flag, proguard, dsb. - Product flavor: dimensi varian produk. Mis.
tierdengan nilaifree/pro, atauenvdengan nilaidev/staging/prod. - Variant: kombinasi build type × flavor. Mis.
freeDebug,proRelease.
Untuk build type dan flavor tunggal, jumlah variant = buildType × flavor1 × flavor2 × .... Mis. dengan 2 build type dan 2 dimensi flavor (masing-masing 2 nilai), kita memperoleh 8 variant.
Source Set per Variant #
Setiap variant memiliki source set sendiri. Gradle menggabungkan source set saat kompilasi dengan prioritas: variant > buildType > flavor > main.
src/
├── main/kotlin/ # kode bersama
├── debug/kotlin/ # kode khusus buildType debug
├── release/kotlin/ # kode khusus buildType release
├── free/kotlin/ # kode khusus flavor free
├── pro/kotlin/ # kode khusus flavor pro
└── freeDebug/kotlin/ # kode khusus variant freeDebugKode di src/free/kotlin akan dikompilasi untuk freeDebug dan freeRelease. Kode di src/freeDebug/kotlin hanya dikompilasi untuk variant freeDebug.
Android Gradle Plugin #
Pada Android Gradle Plugin, build variants dideklarasikan di build.gradle.kts:
android {
buildTypes {
getByName("debug") {
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
isDebuggable = true
}
getByName("release") {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
flavorDimensions += listOf("tier")
productFlavors {
create("free") { dimension = "tier" }
create("pro") { dimension = "tier" }
}
}Mari kita bedah contoh di atas:
applicationIdSuffix = ".debug": ID aplikasi menjadicom.example.app.debuguntuk debug. Memungkinkan dua build (debug + release) terpasang bersamaan di satu ponsel.isMinifyEnabled = truepada release: mengaktifkan R8/ProGuard untuk mengoptimasi dan mengobfuscate kode.flavorDimensions: dimensi yang dipakai. Bila ada beberapa dimensi (mis.tier+env), seluruh dimensi harus dideklarasikan di sini.productFlavors: deklarasi nilai per dimensi. Bila ada dimensi yang tidak diisi, Gradle memunculkan galat.
Demonstrasi Build Variants #
Kode berikut mencantumkan konsep dan source set per variant.
fun main() {
println("=== Build Variants ===")
println()
println("Build variants memungkinkan satu proyek menghasilkan multiple build")
println("dengan konfigurasi berbeda (debug vs release, free vs pro).")
println()
println("Konsep kunci:")
println(" buildType : debug / release (umumnya 2)")
println(" flavor : dimensinya (mis. tier = free/pro, env = dev/staging/prod)")
println(" variant = buildType x flavor (mis. freeDebug, proRelease)")
println()
println("Source set per variant:")
println(" src/main/kotlin - kode bersama")
println(" src/debug/kotlin - kode khusus debug")
println(" src/release/kotlin - kode khusus release")
println(" src/free/kotlin - kode khusus flavor free")
println(" src/freeDebug/kotlin - kode khusus variant freeDebug")
println()
println("Pengaturan Android (Android Gradle Plugin):")
println(" buildTypes { debug { applicationIdSuffix = \".debug\" } }")
println(" productFlavors { free {} pro {} }")
println()
println("Pengaturan Kotlin/JVM (tanpa AGP): pakai sourceSets + custom configurations")
}Output yang Dihasilkan:
=== Build Variants ===
Build variants memungkinkan satu proyek menghasilkan multiple build
dengan konfigurasi berbeda (debug vs release, free vs pro).
Konsep kunci:
buildType : debug / release (umumnya 2)
flavor : dimensinya (mis. tier = free/pro, env = dev/staging/prod)
variant = buildType x flavor (mis. freeDebug, proRelease)
Source set per variant:
src/main/kotlin - kode bersama
src/debug/kotlin - kode khusus debug
src/release/kotlin - kode khusus release
src/free/kotlin - kode khusus flavor free
src/freeDebug/kotlin - kode khusus variant freeDebug
Pengaturan Android (Android Gradle Plugin):
buildTypes { debug { applicationIdSuffix = ".debug" } }
productFlavors { free {} pro {} }
Pengaturan Kotlin/JVM (tanpa AGP): pakai sourceSets + custom configurationsMari kita telaah kode di atas:
- Tiga konsep kunci: buildType, flavor, dan variant. Variant adalah produk akhir yang sebenarnya dibangun. Tanpa flavor, hanya ada
debugdanrelease. - Hierarki source set: kode di
src/freeDebug/kotlinmeng-override kode disrc/free/kotlinyang meng-overridesrc/main/kotlin. Gradle menggabungkan source set dengan urutan prioritas ini. - Konfigurasi AGP: blok
android { buildTypes { ... }; productFlavors { ... } }adalah sintaksis Android Gradle Plugin. Untuk proyek Kotlin/JVM murni tanpa AGP, pendekatan berbeda dipakai.
Build Variants untuk Kotlin/JVM #
Tanpa AGP, proyek Kotlin/JVM murni tidak punya blok buildTypes dan productFlavors bawaan. Namun, kita dapat mensimulasikan via custom source sets dan configurations:
sourceSets {
create("dev") {
kotlin.srcDir("src/dev/kotlin")
}
create("prod") {
kotlin.srcDir("src/prod/kotlin")
}
}
val devImplementation: Configuration by configurations.creating
val prodImplementation: Configuration by configurations.creating
tasks.register<Jar>("devJar") {
from(sourceSets["dev"].output)
archiveClassifier.set("dev")
}
tasks.register<Jar>("prodJar") {
from(sourceSets["prod"].output)
archiveClassifier.set("prod")
}Pendekatan ini lebih manual tetapi memberi kontrol penuh. Untuk sebagian besar proyek server Kotlin/JVM, variant terbatas pada environment (dev/prod) yang dikelola via file konfigurasi eksternal daripada build variants.
Pengaturan umum per Variant #
Beberapa hal yang biasanya berbeda per variant:
| Aspek | Debug | Release |
|---|---|---|
isDebuggable | true | false |
isMinifyEnabled (R8) | false | true |
| Signing | Debug key (auto) | Release key (rahasia) |
| Version name suffix | -debug | (tidak ada) |
| Application ID | com.example.app.debug | com.example.app |
| Logging level | DEBUG/TRACE | WARN/ERROR |
Referensi Lanjutan #
- Gradle User Guide — buku panduan Gradle untuk build variants, source set, dan build type
- Gradle — rujukan Kotlin + Gradle untuk konfigurasi varian build pada proyek Kotlin/JVM
Penutup #
Build variants adalah mekanisme yang matang di ekosistem Gradle, terutama untuk Android. Pemahaman source set per variant dan applicationIdSuffix menjadi bekal untuk mengelola aplikasi dengan multiple build. Pada chapter berikutnya kita akan membahas reproducible builds, konsep bahwa input yang sama harus menghasilkan output identik dari build ke build.