BuildConfig for Kotlin Multiplatform Project
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 2 个月前 | ||
| 1 个月前 | ||
| 4 年前 | ||
| 3 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 3 个月前 | ||
| 4 个月前 | ||
| 2 个月前 | ||
| 4 个月前 | ||
| 2 个月前 | ||
| 4 个月前 | ||
| 7 年前 | ||
| 2 个月前 | ||
| 5 年前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 4 个月前 | ||
| 4 个月前 | ||
| 4 年前 |
BuildKonfig
适用于 Kotlin Multiplatform 和 Kotlin/JVM 项目的 BuildConfig。
目前支持从 gradle 文件嵌入值。
目录
动机
从 Android/iOS 或其他平台代码传递值虽然可行,但过程繁琐。
在 Android 中设置从属性读取值并添加到 BuildConfig,然后在 iOS 中执行类似操作?
我更希望只需配置一次。
使用方法
要求
- Kotlin 2.1.0 或更高版本
- 已应用以下任一插件的项目:Kotlin Multiplatform 或 Kotlin/JVM(通过 KMP 的
js()目标使用 Kotlin/JS) - Gradle 8 或更高版本
Gradle 配置
简单配置
Kotlin DSL
import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.20")
classpath("com.codingfeline.buildkonfig:buildkonfig-gradle-plugin:latest_version")
}
}
plugins {
kotlin("multiplatform")
id("com.codingfeline.buildkonfig")
}
kotlin {
// your target config...
androidTarget()
iosX64('ios')
}
buildkonfig {
packageName = "com.example.app"
// objectName = "YourAwesomeConfig"
// exposeObjectWithName = "YourAwesomePublicConfig"
defaultConfigs {
buildConfigField(STRING, "name", "value")
}
}
Groovy DSL
buildScript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.20'
classpath 'com.codingfeline.buildkonfig:buildkonfig-gradle-plugin:latest_version'
}
}
apply plugin: 'org.jetbrains.kotlin.multiplatform'
apply plugin: 'com.codingfeline.buildkonfig'
kotlin {
// your target config...
androidTarget()
iosX64('ios')
}
buildkonfig {
packageName = 'com.example.app'
// objectName = 'YourAwesomeConfig'
// exposeObjectWithName = 'YourAwesomePublicConfig'
defaultConfigs {
buildConfigField 'STRING', 'name', 'value'
}
}
packageName设置 BuildKonfig 所在的包名。必填项。objectName设置生成的对象名称。默认为BuildKonfig。exposeObjectWithName设置生成的对象名称,并将其设为公开。defaultConfigs设置您希望共有的值。如果省略,将记录警告并跳过代码生成。
要生成 BuildKonfig 文件,请运行 generateBuildKonfig 任务。
此任务将在执行 Kotlin 编译任务时自动运行。
上述配置将生成以下简单对象。
// commonMain
package com.example.app
internal object BuildKonfig {
val name: String = "value"
}
配置 target 相关值
如果您想根据目标更改值,可以使用 targetConfigs 来定义目标相关值。
Kotlin DSL
import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.20")
classpath("com.codingfeline.buildkonfig:buildkonfig-gradle-plugin:latest_version")
}
}
plugins {
kotlin("multiplatform")
id("com.codingfeline.buildkonfig")
}
kotlin {
// your target config...
androidTarget()
iosX64('ios')
}
buildkonfig {
packageName = "com.example.app"
// default config is required
defaultConfigs {
buildConfigField(STRING, "name", "value")
}
targetConfigs {
// names in create should be the same as target names you specified
create("android") {
buildConfigField(STRING, "name2", "value2")
buildConfigField(STRING, "nullableField", "NonNull-value", nullable = true)
}
create("ios") {
buildConfigField(STRING, "name", "valueForNative")
}
}
}
Groovy DSL
buildScript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.20'
classpath 'com.codingfeline.buildkonfig:buildkonfig-gradle-plugin:latest_version'
}
}
apply plugin: 'org.jetbrains.kotlin.multiplatform'
apply plugin: 'com.codingfeline.buildkonfig'
kotlin {
// your target config...
androidTarget()
iosX64('ios')
}
buildkonfig {
packageName = 'com.example.app'
// default config is required
defaultConfigs {
buildConfigField 'STRING', 'name', 'value'
buildConfigField 'STRING', 'nullableField', null, nullable: true
}
targetConfigs {
// this name should be the same as target names you specified
android {
buildConfigField 'STRING', 'name2', 'value2'
buildConfigField 'STRING', 'nullableField', 'NonNull-value', nullable: true
}
ios {
buildConfigField 'STRING', 'name', 'valueForNative'
}
}
}
packageName- 设置 BuildKonfig 放置的包名。必填项。
objectName- 设置生成对象的名称。默认为
BuildKonfig。
- 设置生成对象的名称。默认为
exposeObjectWithName- 设置生成对象的名称,并将其设为公开。
defaultConfigs- 设置您希望共有的值。如果省略,将记录警告并跳过代码生成。
targetConfigs- 以闭包形式设置特定于目标的值。您可以覆盖在
defaultConfigs中指定的值。
- 以闭包形式设置特定于目标的值。您可以覆盖在
buildConfigField(type: String, name: String, value: String)- 添加新值或覆盖现有值。
buildConfigField(type: String, name: String, value: String, nullable: Boolean = false, const: Boolean = false)- 除上述方法外,此方法还可以配置
nullable(可空)和const(常量)声明。
- 除上述方法外,此方法还可以配置
Note
当存在 targetConfigs 时,BuildKonfig 会生成为 expect/actual 形式。K2 编译器(Kotlin 2.x)不允许 expect const val,因此即使您设置 const = true,公共端声明也会生成为普通 val。每个目标的 actual 声明仍然使用 actual const val,因此该值在特定于目标的源代码集中是编译时常量 — 但公共代码不能将其作为编译时常量引用(例如,在需要常量的 when 分支中,或注解参数中)。生成时会为受影响的字段记录警告。
上述配置将生成以下代码。
// commonMain
package com.example.app
internal expect object BuildKonfig {
val name: String
val nullableField: String?
}
// androidMain
package com.example.app
internal actual object BuildKonfig {
actual val name: String = "value"
actual val nullableField: String? = "NonNull-value"
val name2: String = "value2"
}
// iosMain
package com.example.app
internal actual object BuildKonfig {
actual val name: String = "valueForNative"
actual val nullableField: String? = null
}
非多平台项目
BuildKonfig 同样适用于独立的 Kotlin/JVM 项目。
使用 org.jetbrains.kotlin.jvm 插件替代多平台插件,并使用相同的 buildkonfig { ... } 配置块。
对于 Kotlin/JS,请使用带有 js() 目标的 Kotlin Multiplatform 插件——独立的 org.jetbrains.kotlin.js 插件已在 Kotlin 2.4.0 中移除。
Kotlin DSL
import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING
plugins {
kotlin("jvm")
id("com.codingfeline.buildkonfig")
}
buildkonfig {
packageName = "com.example.app"
defaultConfigs {
buildConfigField(STRING, "name", "value")
}
}
Groovy DSL
apply plugin: 'org.jetbrains.kotlin.jvm'
apply plugin: 'com.codingfeline.buildkonfig'
buildkonfig {
packageName = 'com.example.app'
defaultConfigs {
buildConfigField 'STRING', 'name', 'value'
}
}
单个具体对象会生成到 main 源代码集中——不存在 expect/actual 分离,因为只有一个目标。
// src/main/kotlin (generated)
package com.example.app
internal object BuildKonfig {
val name: String = "value"
}
defaultConfigs 块(包括 flavor)得到完全支持。对于单目标项目,targetConfigs 没有意义;如果声明了它们,会记录一条警告并忽略它们。
产品 Flavor?
可以(某种程度上)。
Kotlin 多平台项目不支持产品 flavor。项目的 Kotlin/Native 部分有 release/debug 的区别,但这不是全局的。
因此,为了模拟 Android 的产品 flavor 功能,我们需要提供额外的属性来确定 flavor。
在 gradle.properties 中指定默认 flavor。
# ROOT_DIR/gradle.properties
buildkonfig.flavor=dev
Kotlin DSL
import com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING
import com.codingfeline.buildkonfig.gradle.TargetConfigDsl
buildkonfig {
packageName = "com.example.app"
// default config is required
defaultConfigs {
buildConfigField(STRING, "name", "value")
}
// flavor is passed as a first argument of defaultConfigs
defaultConfigs("dev") {
buildConfigField(STRING, "name", "devValue")
}
targetConfigs {
create("android") {
buildConfigField(STRING, "name2", "value2")
}
create("ios") {
buildConfigField(STRING, "name", "valueIos")
}
}
// flavor is passed as a first argument of targetConfigs
targetConfigs("dev") {
create("ios") {
buildConfigField(STRING, "name", "devValueIos")
}
}
}
Groovy DSL
// ./kmp_project/build.gradle
buildkonfig {
packageName = 'com.example.app'
// default config is required
defaultConfigs {
buildConfigField 'STRING', 'name', 'value'
}
// flavor is passed as a first argument of defaultConfigs
defaultConfigs("dev") {
buildConfigField 'STRING', 'name', 'devValue'
}
targetConfigs {
android {
buildConfigField 'STRING', 'name2', 'value2'
}
ios {
buildConfigField 'STRING', 'name', 'valueIos'
}
}
// flavor is passed as a first argument of targetConfigs
targetConfigs("dev") {
ios {
buildConfigField 'STRING', 'name', 'devValueIos'
}
}
}
在开发阶段,你可以随意修改 gradle.properties 中的值。
在 CI 环境中,你可以通过 CLI 传入值,例如 $ ./gradlew build -Pbuildkonfig.flavor=release
覆盖值
如果你在多个 defaultConfigs 和 targetConfigs 中配置了相同的字段,那么带有 flavor 的 targetConfigs 优先级最高。
从左到右,优先级依次降低。
Flavored TargetConfig > TargetConfig > Flavored DefaultConfig > DefaultConfig
HMPP 支持
也称为“中间源代码集”。(详见在平台间共享代码。)
BuildKonfig 支持 HMPP,但存在一些限制。
当你为中间源代码集添加 targetConfigs 时,不能为其子源代码集定义其他 targetConfigs。
例如,假设你有如下的源代码集结构。
- commonMain
- appMain
- androidMain
- desktopMain
- macosArm64Main
- linuxX64Main
- mingwX64Main
- jsCommonMain
- browserMain
- nodeMain
- iosMain
- iosArm64Main
- iosX64Main
如果你为 appMain 添加了 targetConfigs,就不能再为 androidMain、desktopMain 或 desktopMain 的子级添加配置了。这是因为 BuildKonfig 使用 expect/actual 为每个 BuildKonfig 对象提供不同的值。当你为 appMain 提供配置时,BuildKonfig 对象的 actual 声明会在 appMain 中创建。因此,在子 SourceSet 中添加任何额外的 actual 声明都会导致编译时错误。
支持的类型
- String
- Int
- Long
- Float
- Boolean
试用示例
有两个示例:sample 和 sample-kts。顾名思义,sample-kts 是 Kotlin DSL 示例,另一个是传统的 Groovy DSL 示例。
可以查看 ./sample 目录。
# Publish the latest version of the plugin to test maven repository(./build/localMaven)
$ ./gradlew publishAllPublicationsToTestMavenRepository -PRELEASE_SIGNING_ENABLED=false
# Try out the samples.
# BuildKonfig will be generated in ./sample/build/buildkonfig
$ ./gradlew -p sample generateBuildKonfig