【问题标题】:Use Gradle sub-projects with Kotlin multiplatform将 Gradle 子项目与 Kotlin 多平台一起使用
【发布时间】:2018-06-20 01:04:03
【问题描述】:

我正在使用 Kotlin 多平台(JVM 和 JS),它在 IDEA 中创建了三个项目:demodemo-jsdemo-jvm

我想将通用代码拆分成更多的子项目/子模块。假设我添加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')
}

【问题讨论】:

  • 我不知道这是否仍然与您相关,但 this project 包含一个完整的示例,其中包含您可能需要的所有花里胡哨。
  • 看起来很有趣,尤其是当问题 #10 将得到解决时,谢谢!

标签: kotlin gradle kotlin-multiplatform gradle-dependencies kmm


【解决方案1】:

这花了很多时间,所以我希望这对某人有用!

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

通用模块(alphabeta)需要每个平台的平台模块至少有一个`build.gradle`。

settings.gradle 文件导入所有模块,包括平台模块。

依赖项,例如从 alpha on beta,在通用 alpha 模块和所有 alpha 平台模块中声明。


我学到的一些模式:

  • 每个“普通”(通用)模块都有一个用于每个平台的平台模块。
  • 对于公共模块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 上的代码,因为它真的很长。

【讨论】:

  • 非常感谢您的这些指导,您为我节省了很多时间。我认为,我们应该创建一个功能请求来支持两个通用模块之间的“编译项目('...')”依赖关系。你知道是否已经有一个吗?
  • 我不知道有一个
  • @Andi 你不能在beta-common 中使用compile project(':alpha-common') 吗?至少可以使用compile "some.groupid:some.artifactid:1.0.0"
  • 这是关键信息:“依赖关系,例如从 alpha 到 beta,在通用 alpha 模块和所有 alpha 平台模块中声明。”
  • 我参加聚会可能有点晚了@SimonForsberg,但是,我有一个回答你的问题“你不能在 beta-common 中使用 compile project(':alpha-common')”。是的,您可以,但是当您将依赖项添加到公共模块时,将各个平台特定的模块添加到您的公共拥有的特定平台的实际版本中。希望这可以帮助某人
【解决方案2】:

对于来自 Google 搜索的任何人:

“实际函数/类/伴生对象/等没有对应的预期声明”

尝试清理和重建项目,对我来说,这揭示了许多其他阻止构建的错误。

【讨论】:

  • 我在搜索该错误时发现了这一点。错误的意思是编译器找不到actual函数/类是平台特定实现的非平台特定函数/类等。
【解决方案3】:

子模块必须在 sourceSets 的依赖范围内声明。如果子模块定义在通用sourceSet中,则不需要在特定平台中定义,反之则不然。

build.gradle.kts (:kmm_shared:feature_a)

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                api(project(":kmm_shared:domain"))
            }
        }
}

有了这个,android sourceSet 也不需要包含依赖项。

GL

【讨论】:

    猜你喜欢
    • 2019-04-08
    • 2020-04-06
    • 2021-11-24
    • 2020-07-29
    • 2020-09-05
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多