KMM中如何定义/访问BuildTypes、BuildConfig参数及Build变体?
在KMM中,Android的Build Type、BuildConfig、Build Variant没有直接的跨平台等价物,下面是针对iOS端的具体实现方案,以及跨平台统一配置的解决思路:
一、Build Type(构建类型)的处理
Android的debug/release构建类型,iOS没有原生对应,但可以通过Gradle给iOS目标注入编译标记,结合代码层的条件判断实现区分:
1. 在Gradle中配置编译参数
在共享模块的build.gradle.kts中,为iOS的debug和release构建添加不同的编译选项:
kotlin { ios { binaries { framework { // Debug构建添加DEBUG宏,开启调试相关逻辑 debug.get().compilerOpts.add("-DDEBUG") // Release构建开启代码优化 release.get().compilerOpts.add("-O") } } } }
2. 代码层区分构建类型
在共享代码中用expect/actual定义调试状态:
// commonMain expect val isDebug: Boolean // androidMain actual val isDebug: Boolean = com.yourpackage.BuildConfig.DEBUG // iOSMain actual val isDebug: Boolean = System.getProperty("DEBUG")?.toBoolean() ?: false
在iOS原生代码中,也可以用#ifdef DEBUG来编写平台特有的调试逻辑。
二、BuildConfig的跨平台替代方案
Android的BuildConfig是自动生成的配置类,KMM无法直接跨平台复用,推荐两种通用方案:
方案1:Gradle生成通用配置类
通过Gradle任务自动生成跨平台可用的配置类,确保Android和iOS使用同一套配置:
// 共享模块build.gradle.kts tasks.register("generateCommonConfig") { val outputDir = file("src/commonMain/kotlin/com/yourpackage/config") outputs.dir(outputDir) doLast { outputDir.mkdirs() val configContent = """ package com.yourpackage.config object CommonConfig { const val API_BASE_URL = "${project.findProperty("apiBaseUrl") ?: "https://default.api.com"}" const val IS_DEBUG = ${project.hasProperty("debug")} const val APP_VERSION = "${project.version}" } """.trimIndent() file("$outputDir/CommonConfig.kt").writeText(configContent) } } // 让编译任务依赖配置生成任务 tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach { dependsOn("generateCommonConfig") }
运行时可以通过Gradle参数覆盖默认配置:
./gradlew assembleDebug -PapiBaseUrl=https://dev.api.com -Pdebug=true
方案2:Expect/Actual结合Gradle参数传递
通过expect/actual定义配置接口,Android端复用原生BuildConfig,iOS端通过Gradle注入参数:
// commonMain expect object AppConfig { val apiBaseUrl: String val isDebug: Boolean } // androidMain actual object AppConfig { actual val apiBaseUrl: String = com.yourpackage.BuildConfig.API_BASE_URL actual val isDebug: Boolean = com.yourpackage.BuildConfig.DEBUG } // iOSMain actual object AppConfig { actual val apiBaseUrl: String = System.getProperty("apiBaseUrl") ?: "https://default.api.com" actual val isDebug: Boolean = System.getProperty("isDebug")?.toBoolean() ?: false }
在Gradle中为iOS目标注入参数:
kotlin { ios { binaries { framework { val apiUrl = project.findProperty("apiBaseUrl") ?: "https://default.api.com" val debugMode = project.hasProperty("debug") debug.get().compilerOpts.add("-DapiBaseUrl=$apiUrl") debug.get().compilerOpts.add("-DisDebug=$debugMode") release.get().compilerOpts.add("-DapiBaseUrl=$apiUrl") release.get().compilerOpts.add("-DisDebug=$debugMode") } } } }
三、Build Variant(构建变体)的处理
Android的变体是Build Type + Product Flavor的组合,iOS没有Flavor概念,需要通过代码层标识结合Gradle参数来实现:
1. Gradle传递变体标识
在gradle.properties中配置当前变体,或者运行时传递:
# gradle.properties buildVariant=dev
在共享模块Gradle中传递给iOS:
kotlin { ios { binaries { framework { val variant = project.findProperty("buildVariant") ?: "dev" compilerOpts.add("-DBUILD_VARIANT=$variant") } } } }
2. 代码层识别变体
通过expect/actual定义变体获取方法,统一跨平台逻辑:
// commonMain expect fun getCurrentVariant(): String enum class AppVariant { DEV, STAGING, PROD } val activeVariant: AppVariant get() = when(getCurrentVariant()) { "staging" -> AppVariant.STAGING "prod" -> AppVariant.PROD else -> AppVariant.DEV } // androidMain actual fun getCurrentVariant(): String = com.yourpackage.BuildConfig.FLAVOR // iOSMain actual fun getCurrentVariant(): String = System.getProperty("BUILD_VARIANT") ?: "dev"
3. 配合iOS的XCConfig文件
如果iOS项目本身用XCConfig管理环境配置,可以在Gradle中读取XCConfig参数,实现配置同步:
// 读取XCConfig文件的工具方法 fun readXcConfig(configPath: String): Map<String, String> { val configFile = file(configPath) return configFile.readLines() .filter { it.isNotEmpty() && !it.startsWith("//") } .associate { line -> val parts = line.split("=", limit = 2) parts[0].trim() to parts[1].trim().removeSurrounding("\"") } } // 在iOS目标中应用XCConfig参数 kotlin { ios { val xcConfig = readXcConfig("../iosApp/Configs/Dev.xcconfig") binaries { framework { compilerOpts.add("-DAPI_BASE_URL=${xcConfig["API_BASE_URL"]}") compilerOpts.add("-DBUILD_VARIANT=${xcConfig["BUILD_VARIANT"]}") } } } }
四、commonMain/iOSMain访问配置的核心原则
- 绝对不要在共享代码中直接依赖Android的
BuildConfig,避免平台绑定 - 优先用通用配置类或expect/actual模式实现跨平台配置统一
- 所有配置参数尽量通过Gradle集中管理,确保Android和iOS的配置来源一致
内容的提问来源于stack exchange,提问作者Sandipkumar Savani

