在 Kotlin 多平台中使用 Gradle 个子项目
Use Gradle sub-projects with Kotlin multiplatform
我正在使用 Kotlin 多平台(JVM 和 JS),它在 IDEA 中创建了三个项目:demo
、demo-js
和 demo-jvm
。
我想将通用代码拆分成更多subprojects/submodules。假设我添加 commonmod
;我如何编译它?
现在 gradle run -p demo-jvm
的错误是:
demo/demo-js/src/main/kotlin/demo/commonmod/example.kt: (3, 12): Actual function 'getPlatform' has no corresponding expected declaration
但我认为我这样做从根本上是错误的,因为我不知道什么应该取决于什么(尽管我尝试了很多迭代)。如果我解决了这个错误,我会得到其他错误,然后再得到其他错误,直到我回到这个错误。
作为一个最小但仍然很大的 example,我有:
demo/settings.gradle:
rootProject.name = 'demo'
include 'demo-jvm', 'demo-js', 'commonmod'
demo/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
compile project(':commonmod')
}
demo/demo-jvm/settings.gradle:
rootProject.name = 'demo'
demo/demo-jvm/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-jvm'
apply plugin: 'application'
repositories {
mavenCentral()
}
mainClassName = "demo.MainKt"
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
expectedBy project(":")
testCompile "junit:junit:4.12"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
demo/demo-js/settings.gradle:
rootProject.name = 'demo'
demo/demo-js/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
expectedBy project(":")
testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
}
demo/commonmod/settings.gradle:
rootProject.name = 'demo'
include 'demo-jvm', 'demo-js'
demo/commonmod/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
compile project(':demo-js')
compile project(':demo-jvm')
}
这花了很多时间,所以我希望这对某人有用!
Github 上有一个功能示例:kotlin_multiplatform_gradle_demo
有几个来源提供了帮助,但很多都是反复试验,所以如果有什么不好的做法,请告诉我!
对于最小的例子,结构是这样的:
├── alpha
│ ├── alpha-js
│ │ └── build.gradle
│ ├── alpha-jvm
│ │ └── build.gradle
│ ├── build.gradle
│ └── src
│ └── main
│ ├── kotlin
│ │ └── demo
│ │ └── alpha
│ │ └── main.kt
├── beta
│ ├── beta-js
│ │ ├── build.gradle
│ │ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── demo
│ │ └── beta
│ │ └── platform.kt
│ ├── beta-jvm
│ │ ├── build.gradle
│ │ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── demo
│ │ └── beta
│ │ └── platform.kt
│ ├── build.gradle
│ └── src
│ └── main
│ └── kotlin
│ └── demo
│ └── beta
│ └── platform.kt
├── build.gradle
└── settings.gradle
公共模块(alpha
和 beta
)需要每个平台的平台模块至少有一个 `build.gradle``。
settings.gradle
文件导入所有模块,包括平台模块。
依赖关系,例如从 alpha 到 beta,在通用 alpha 模块和所有 alpha 平台模块中声明。
我学到的一些模式:
- 每个 'normal'(通用)模块针对每个平台都有一个平台模块。
- 对于通用模块
alpha
,必须调用 javascript 平台模块 alpha-js
(类似于 -jvm
)。
- 如果没有特定于平台的代码,此模块可以只是目录中的一个 gradle 文件。
- 平台模块可以方便地放在公共模块目录中(所以
alpha:alpha-js
)。
- 公共模块不应引用平台模块;平台模块具有依赖性
expectedBy project(":the_common_module")
.
如果模块alpha
依赖于beta
,那么
alpha
必须有 dependencies { compile project(":beta") }
alpha-js
必须有dependencies { compile project(":beta:beta-js") }
(除了expectedBy
)
alpha-jvm
必须有dependencies { compile project(":beta:beta-jvm") }
(除了expectedBy
)等
只有顶层模块有settings.gradle
,包括所有子模块(包括平台子模块)。
- 确保名称正确,因为不正确的名称不会导致错误,它们只会默默地失败。 (看似荒谬,但我想是有原因的。)
- 不要将所有输出放入一个共享的构建目录中 - 这会导致几个奇怪的非确定性错误。
我以前在这里有完整的配置文件,但最好只检查 Github 上的代码,因为它真的很长。
对于来自 Google 搜索的任何人:
"Actual function/class/companion object/etc. has no corresponding expected declaration"
尝试清理并重建项目,对我来说,这揭示了一些阻止构建的其他错误。
子模块必须在 sourceSets 的依赖范围内声明。如果子模块定义在公共sourceSet中,则不需要在特定平台之一中定义,反之亦然。
build.gradle.kts (:kmm_shared:feature_a)
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api(project(":kmm_shared:domain"))
}
}
}
有了这个,android sourceSet 也没有必要包含依赖项。
GL
我正在使用 Kotlin 多平台(JVM 和 JS),它在 IDEA 中创建了三个项目:demo
、demo-js
和 demo-jvm
。
我想将通用代码拆分成更多subprojects/submodules。假设我添加 commonmod
;我如何编译它?
现在 gradle run -p demo-jvm
的错误是:
demo/demo-js/src/main/kotlin/demo/commonmod/example.kt: (3, 12): Actual function 'getPlatform' has no corresponding expected declaration
但我认为我这样做从根本上是错误的,因为我不知道什么应该取决于什么(尽管我尝试了很多迭代)。如果我解决了这个错误,我会得到其他错误,然后再得到其他错误,直到我回到这个错误。
作为一个最小但仍然很大的 example,我有:
demo/settings.gradle:
rootProject.name = 'demo'
include 'demo-jvm', 'demo-js', 'commonmod'
demo/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
compile project(':commonmod')
}
demo/demo-jvm/settings.gradle:
rootProject.name = 'demo'
demo/demo-jvm/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-jvm'
apply plugin: 'application'
repositories {
mavenCentral()
}
mainClassName = "demo.MainKt"
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
expectedBy project(":")
testCompile "junit:junit:4.12"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
demo/demo-js/settings.gradle:
rootProject.name = 'demo'
demo/demo-js/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
expectedBy project(":")
testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
}
demo/commonmod/settings.gradle:
rootProject.name = 'demo'
include 'demo-jvm', 'demo-js'
demo/commonmod/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
compile project(':demo-js')
compile project(':demo-jvm')
}
这花了很多时间,所以我希望这对某人有用!
Github 上有一个功能示例:kotlin_multiplatform_gradle_demo
有几个来源提供了帮助,但很多都是反复试验,所以如果有什么不好的做法,请告诉我!
对于最小的例子,结构是这样的:
├── alpha
│ ├── alpha-js
│ │ └── build.gradle
│ ├── alpha-jvm
│ │ └── build.gradle
│ ├── build.gradle
│ └── src
│ └── main
│ ├── kotlin
│ │ └── demo
│ │ └── alpha
│ │ └── main.kt
├── beta
│ ├── beta-js
│ │ ├── build.gradle
│ │ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── demo
│ │ └── beta
│ │ └── platform.kt
│ ├── beta-jvm
│ │ ├── build.gradle
│ │ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── demo
│ │ └── beta
│ │ └── platform.kt
│ ├── build.gradle
│ └── src
│ └── main
│ └── kotlin
│ └── demo
│ └── beta
│ └── platform.kt
├── build.gradle
└── settings.gradle
公共模块(alpha
和 beta
)需要每个平台的平台模块至少有一个 `build.gradle``。
settings.gradle
文件导入所有模块,包括平台模块。
依赖关系,例如从 alpha 到 beta,在通用 alpha 模块和所有 alpha 平台模块中声明。
我学到的一些模式:
- 每个 'normal'(通用)模块针对每个平台都有一个平台模块。
- 对于通用模块
alpha
,必须调用 javascript 平台模块alpha-js
(类似于-jvm
)。 - 如果没有特定于平台的代码,此模块可以只是目录中的一个 gradle 文件。
- 平台模块可以方便地放在公共模块目录中(所以
alpha:alpha-js
)。 - 公共模块不应引用平台模块;平台模块具有依赖性
expectedBy project(":the_common_module")
. 如果模块
alpha
依赖于beta
,那么alpha
必须有dependencies { compile project(":beta") }
alpha-js
必须有dependencies { compile project(":beta:beta-js") }
(除了expectedBy
)alpha-jvm
必须有dependencies { compile project(":beta:beta-jvm") }
(除了expectedBy
)等
只有顶层模块有
settings.gradle
,包括所有子模块(包括平台子模块)。- 确保名称正确,因为不正确的名称不会导致错误,它们只会默默地失败。 (看似荒谬,但我想是有原因的。)
- 不要将所有输出放入一个共享的构建目录中 - 这会导致几个奇怪的非确定性错误。
我以前在这里有完整的配置文件,但最好只检查 Github 上的代码,因为它真的很长。
对于来自 Google 搜索的任何人:
"Actual function/class/companion object/etc. has no corresponding expected declaration"
尝试清理并重建项目,对我来说,这揭示了一些阻止构建的其他错误。
子模块必须在 sourceSets 的依赖范围内声明。如果子模块定义在公共sourceSet中,则不需要在特定平台之一中定义,反之亦然。
build.gradle.kts (:kmm_shared:feature_a)
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api(project(":kmm_shared:domain"))
}
}
}
有了这个,android sourceSet 也没有必要包含依赖项。
GL