Is there a kmp/cmp way to have different build var...
# compose-ios
c
Is there a kmp/cmp way to have different build variants (like in Android)? Essentially in android, we have a default debug and release. But now I want to have a prodDebug, prodRelease and stagingDebug and stagingRelease in both android and ios.
m
There is nome official afaik. But i researched recently and you can build same functionality with gralde script yourself. Basically you have somewhere a text file where you define current flavor =debug/release and then on build this is read and written into a kotlin object which you access at runtime. I first thought that’s worse than what we have on android but actually - on Android we need to toggle debug/release with on UI-click. In the gradle approach it’s by editing on file. Kind of same effort to me. Once i’m on my computer i can try finding the stackoverflow article how to do that, but maybe just google “gradle android kmp build flavor”
👍 1
*the dimensions debug/release prod/staging you would need to basically build yourself in Kotlin and the gradle script fills some constants in a kotlin object or class file
r
The way I have it: 1. define different gradle tasks for different flavours
Copy code
val markDesktopProd = tasks.register("markDesktopProd") {
    doLast {
        isBrowserOrDesktop.set(true)
        isProdBuild.set(true)
        isLocalBuild.set(false)
        println("Setting desktop to prod")
    }
}
2. the tasks setup the right properties i.e.
Copy code
val customProp: Property<String> = project.objects.property(String::class.java).convention(null)
3. you register and use a task to generate a custom build config used by your targets
Copy code
tasks.register("generateBuildConfig") {
    val versionFile = rootDir.resolve(versionTextFile)
    if (!versionFile.exists()) throw GradleException("Version file does not exist.")
    doLast {
        val (major, minor, patch) = versionFile.readVersion()
        val customPropValue = customProp.get()
        val formattedVersion = "$major.$minor.$patch"
        val fileContent = """
            package $packageName.config

            // Autogenerated, do not modify
            object AppBuildConfig {
                const val VERSION = "$formattedVersion"
                val CUSTOM_PROP: String? = $customPropValue
            }
        """.trimIndent()

        val buildDir = layout.buildDirectory.get().asFile
        val commonMainDir = file("${buildDir}/generated/kotlin/config/")
        commonMainDir.mkdirs()
        val generatedFile = commonMainDir.resolve("AppBuildConfig.kt")
        generatedFile.delete()
        generatedFile.writeText(fileContent)
        val success = generatedFile.setReadOnly()
        if (!success) {
            logger.warn("Failed to set the file as read-only: ${generatedFile.absolutePath}")
        }
    }
}
kotlin.targets.all {
    compilations.all { compileTaskProvider.dependsOn("generateBuildConfig") }
}
kotlin.sourceSets.getByName("commonMain") {
    val buildDir = layout.buildDirectory.get().asFile
    kotlin.srcDir("${buildDir}/generated/kotlin/config")
}
4. Now at runtime, you can refer to the per-flavour setup.
Unrelated, but I would suggest, if possible, not tying a build variant to an environment (only to the defaults). And instead provide a debug screen (accessible only in the right circumstances) to dynamically switch between the environments. Each variant fewer is one headache less to maintain 🙂
👍 1
1
c
Yep. In this case it's basically two variants. Prod and staging (and staging contains the snv switcher to everything else)
159 Views