diff --git a/buildSrc/src/main/kotlin/mordant-js-conventions.gradle.kts b/buildSrc/src/main/kotlin/mordant-js-conventions.gradle.kts index fa442add..490f3bc2 100644 --- a/buildSrc/src/main/kotlin/mordant-js-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/mordant-js-conventions.gradle.kts @@ -20,7 +20,7 @@ kotlin { sourceSets { val jsCommonMain by creating { dependsOn(commonMain.get()) } jsMain.get().dependsOn(jsCommonMain) - getByName("wasmJsMain").dependsOn(jsCommonMain) + wasmJsMain.get().dependsOn(jsCommonMain) } } diff --git a/buildSrc/src/main/kotlin/mordant-mpp-conventions.gradle.kts b/buildSrc/src/main/kotlin/mordant-mpp-conventions.gradle.kts index b1e206bc..28a69e3f 100644 --- a/buildSrc/src/main/kotlin/mordant-mpp-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/mordant-mpp-conventions.gradle.kts @@ -1,9 +1,5 @@ plugins { id("mordant-kotlin-conventions") - id("mordant-js-conventions") id("mordant-native-conventions") -} - -kotlin { - jvm() + id("mordant-js-conventions") } diff --git a/buildSrc/src/main/kotlin/mordant-native-conventions.gradle.kts b/buildSrc/src/main/kotlin/mordant-native-conventions.gradle.kts index 97e28042..4f49e2e9 100644 --- a/buildSrc/src/main/kotlin/mordant-native-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/mordant-native-conventions.gradle.kts @@ -1,5 +1,4 @@ plugins { - kotlin("multiplatform") id("mordant-native-core-conventions") } @@ -12,13 +11,4 @@ kotlin { watchosArm64() watchosX64() watchosSimulatorArm64() - - sourceSets { - for (target in listOf( - "tvosX64", "tvosArm64", "tvosSimulatorArm64", - "watchosArm32", "watchosArm64", "watchosX64", "watchosSimulatorArm64", - )) { - sourceSets.getByName(target + "Main").kotlin.srcDirs("src/posixSharedMain/kotlin") - } - } } diff --git a/buildSrc/src/main/kotlin/mordant-native-core-conventions.gradle.kts b/buildSrc/src/main/kotlin/mordant-native-core-conventions.gradle.kts index 780a1107..2ede7913 100644 --- a/buildSrc/src/main/kotlin/mordant-native-core-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/mordant-native-core-conventions.gradle.kts @@ -3,6 +3,8 @@ plugins { } kotlin { + applyDefaultHierarchyTemplate() + linuxX64() linuxArm64() macosX64() @@ -21,27 +23,4 @@ kotlin { // watchosDeviceArm64() // watchosX64() // watchosSimulatorArm64() - - applyDefaultHierarchyTemplate() - - // https://kotlinlang.org/docs/multiplatform-hierarchy.html#see-the-full-hierarchy-template - sourceSets { - val posixMain by creating { dependsOn(nativeMain.get()) } - linuxMain.get().dependsOn(posixMain) - appleMain.get().dependsOn(posixMain) - val appleNonDesktopMain by creating { dependsOn(appleMain.get()) } - for (target in listOf(iosMain, tvosMain, watchosMain)) { - target.get().dependsOn(appleNonDesktopMain) - } - // Kotlin 2.0 changed the way MPP is compiled, so instead of copying shared sources to each - // target, it compiles intermediate sources separately. That means that code that previously - // compiled is broken due to errors like "declaration is using numbers with different bit - // widths". So we copy the shared sources to each target manually. - for (target in listOf( - "linuxX64", "linuxArm64", - "macosX64", "macosArm64", - )) { - sourceSets.getByName(target + "Main").kotlin.srcDirs("src/posixSharedMain/kotlin") - } - } } diff --git a/mordant-coroutines/build.gradle.kts b/mordant-coroutines/build.gradle.kts index add6b4fa..1a6231a9 100644 --- a/mordant-coroutines/build.gradle.kts +++ b/mordant-coroutines/build.gradle.kts @@ -4,6 +4,7 @@ plugins { } kotlin { + jvm() sourceSets { commonMain.dependencies { api(project(":mordant")) diff --git a/mordant-omnibus/api/mordant-omnibus.api b/mordant-omnibus/api/mordant-omnibus.api new file mode 100644 index 00000000..e69de29b diff --git a/mordant-omnibus/build.gradle.kts b/mordant-omnibus/build.gradle.kts index c76bf60b..35e79c71 100644 --- a/mordant-omnibus/build.gradle.kts +++ b/mordant-omnibus/build.gradle.kts @@ -1,10 +1,18 @@ +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl + +// We don't use all the conventions plugins here since applying the mpp=convention results in +// "IllegalStateException: Configuration already finalized for previous property values" plugins { - id("mordant-kotlin-conventions") + kotlin("multiplatform") + id("mordant-native-conventions") id("mordant-publishing-conventions") } kotlin { jvm() + js { nodejs() } // we don't have any code, but it's an error not to pick aa JS environment + @OptIn(ExperimentalWasmDsl::class) + wasmJs { nodejs() } sourceSets { commonMain.dependencies { api(project(":mordant")) diff --git a/mordant-omnibus/src/commonMain/kotlin/com/github/ajalt/mordant/internal/OmibusInternal.kt b/mordant-omnibus/src/commonMain/kotlin/com/github/ajalt/mordant/internal/OmibusInternal.kt new file mode 100644 index 00000000..a7b3ba75 --- /dev/null +++ b/mordant-omnibus/src/commonMain/kotlin/com/github/ajalt/mordant/internal/OmibusInternal.kt @@ -0,0 +1,4 @@ +package com.github.ajalt.mordant.internal + +// This intentionally empty file is a workaround for KT-52344, which fails to publish a target with +// no source files diff --git a/mordant/build.gradle.kts b/mordant/build.gradle.kts index 5153aa2c..097d0c35 100644 --- a/mordant/build.gradle.kts +++ b/mordant/build.gradle.kts @@ -4,6 +4,7 @@ plugins { } kotlin { + jvm() sourceSets { all { languageSettings.optIn("kotlinx.cinterop.ExperimentalForeignApi") @@ -19,5 +20,27 @@ kotlin { jvmTest.dependencies { api(libs.systemrules) } + // Kotlin 2.0 changed the way MPP is compiled, so instead of copying shared sources to each + // target, it compiles intermediate sources separately. That means that code that previously + // compiled is broken due to errors like "declaration is using numbers with different bit + // widths". So we copy the shared sources to each target manually. + sourceSets { + // https://kotlinlang.org/docs/multiplatform-hierarchy.html#see-the-full-hierarchy-template + val posixMain by creating { dependsOn(nativeMain.get()) } + linuxMain.get().dependsOn(posixMain) + appleMain.get().dependsOn(posixMain) + val appleNonDesktopMain by creating { dependsOn(appleMain.get()) } + for (target in listOf(iosMain, tvosMain, watchosMain)) { + target.get().dependsOn(appleNonDesktopMain) + } + for (target in listOf( + "linuxX64", "linuxArm64", + "macosX64", "macosArm64", + "tvosX64", "tvosArm64", "tvosSimulatorArm64", + "watchosArm32", "watchosArm64", "watchosX64", "watchosSimulatorArm64", + )) { + sourceSets.getByName(target + "Main").kotlin.srcDirs("src/posixSharedMain/kotlin") + } + } } } diff --git a/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppInternal.jvm.kt b/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppInternal.jvm.kt index 31487341..452b6ba6 100644 --- a/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppInternal.jvm.kt +++ b/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppInternal.jvm.kt @@ -157,15 +157,24 @@ internal actual fun readFileIfExists(filename: String): String? { } } +private const val DUMB_RAW_MODE_ERROR = """Cannot find terminal interface that supports raw mode. + +You need at least one of the `:mordant-jvm-*` modules on your classpath. +The `:mordant` module includes all of them as transitive dependencies. +If you're using `:mordant-core` instead, you need to add one or more manually. +If you're using only `:mordant-jvm-ffm`, make sure you're running with JVM 22+, and are passing +`--enable-native-access=ALL-UNNAMED` as a JVM argument. +""" + private object DumbTerminalInterface : StandardTerminalInterface() { override fun stdoutInteractive(): Boolean = true override fun stdinInteractive(): Boolean = true override fun getTerminalSize(): Size? = null override fun enterRawMode(mouseTracking: MouseTracking): AutoCloseable { - throw UnsupportedOperationException("Cannot enter raw mode on this system") + throw UnsupportedOperationException(DUMB_RAW_MODE_ERROR) } override fun readInputEvent(timeout: TimeMark, mouseTracking: MouseTracking): InputEvent? { - throw UnsupportedOperationException("Cannot read input on this system") + throw UnsupportedOperationException(DUMB_RAW_MODE_ERROR) } }