diff --git a/docs/pages/kotlinx-rpc/topics/platforms.topic b/docs/pages/kotlinx-rpc/topics/platforms.topic
index 1511fbaaa..8470157bc 100644
--- a/docs/pages/kotlinx-rpc/topics/platforms.topic
+++ b/docs/pages/kotlinx-rpc/topics/platforms.topic
@@ -1,4 +1,8 @@
+
+
@@ -47,8 +51,13 @@
- The following table contains a list of all published modules and their supported platforms:
+ The following table contains a list of all published modules and their supported platforms.
+
+ Targets marked with the [stub] tag have published artifacts,
+ but their runtime functionally is not supported.
+ This is done to make sure that user projects sync without errors when some target is not present.
+
Module |
diff --git a/gradle-conventions/src/main/kotlin/util/targets/kmpConfig.kt b/gradle-conventions/src/main/kotlin/util/targets/kmpConfig.kt
index 66085b95d..a0451a821 100644
--- a/gradle-conventions/src/main/kotlin/util/targets/kmpConfig.kt
+++ b/gradle-conventions/src/main/kotlin/util/targets/kmpConfig.kt
@@ -56,7 +56,7 @@ class KmpConfig(
private val excludeJvm: Boolean by optionalProperty("exclude")
private val excludeJs: Boolean by optionalProperty("exclude")
private val excludeWasmJs: Boolean by optionalProperty("exclude")
- private val excludeWasmJsD8: Boolean by optionalProperty("exclude")
+ private val excludeWasmJsD8: Boolean by optionalProperty("exclude", "wasmJs")
private val excludeWasmWasi: Boolean by optionalProperty("exclude")
val excludeNative: Boolean by optionalProperty("exclude")
diff --git a/gradle-conventions/src/main/kotlin/util/tasks/platformTable.kt b/gradle-conventions/src/main/kotlin/util/tasks/platformTable.kt
index e49005a61..089e97bcc 100644
--- a/gradle-conventions/src/main/kotlin/util/tasks/platformTable.kt
+++ b/gradle-conventions/src/main/kotlin/util/tasks/platformTable.kt
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
import util.KOTLIN_JVM_PLUGIN_ID
import util.KOTLIN_MULTIPLATFORM_PLUGIN_ID
import util.other.isPublicModule
+import util.other.optionalPropertyValue
import java.io.File
import java.nio.file.Files
@@ -38,13 +39,15 @@ enum class TableColumn {
sealed interface PlatformTarget {
val name: String
val subtargets: List
+ val stub: Boolean get() = false
class Group(
override val name: String,
override val subtargets: List,
+ override val stub: Boolean,
) : PlatformTarget
- class LeafTarget(override val name: String) : PlatformTarget {
+ class LeafTarget(override val name: String, override val stub: Boolean) : PlatformTarget {
override val subtargets: List = emptyList()
}
}
@@ -113,32 +116,44 @@ abstract class DumpPlatformsTask : DefaultTask() {
.mapValues { (platform, targets) ->
when (platform) {
KotlinPlatformType.jvm -> {
- PlatformTarget.LeafTarget(TableColumn.Jvm.name.lowercase())
+ val isStub = subproject.optionalPropertyValue(targets[0].name, "stub")
+ PlatformTarget.LeafTarget(TableColumn.Jvm.name.lowercase(), isStub)
}
KotlinPlatformType.js -> {
- val subtargets = targets.jsOrWasmSubTargets("js", subproject) {
+ val (target, subtargets) = targets.jsOrWasmSubTargets("js", subproject) {
it is KotlinJsIrTarget
- }
+ } ?: return@mapValues null
- PlatformTarget.Group(TableColumn.Js.name, subtargets)
+ val isStub = subproject.optionalPropertyValue(target.name, "stub")
+ PlatformTarget.Group(TableColumn.Js.name, subtargets, isStub)
}
KotlinPlatformType.wasm -> {
- val jsSubtargets = targets.jsOrWasmSubTargets("wasmJs", subproject) {
+ val (jsTarget, jsSubtargets) = targets.jsOrWasmSubTargets("wasmJs", subproject) {
it is KotlinWasmJsTargetDsl && it.wasmTargetType == KotlinWasmTargetType.JS
- }
+ } ?: (null to emptyList())
- val wasiSubtargets = targets.jsOrWasmSubTargets("wasmWasi", subproject) {
+ val (wasiTarget, wasiSubtargets) = targets.jsOrWasmSubTargets("wasmWasi", subproject) {
it is KotlinWasmWasiTargetDsl && it.wasmTargetType == KotlinWasmTargetType.WASI
- }
+ } ?: (null to emptyList())
+
+ val jsIsStub = jsTarget?.name
+ ?.let { subproject.optionalPropertyValue(it, "stub") } ?: false
+
+ val wasiIsStub = wasiTarget?.name
+ ?.let { subproject.optionalPropertyValue(it, "stub") } ?: false
val wasmSubtargets = listOfNotNull(
- PlatformTarget.Group("wasmJs", jsSubtargets).takeIf { jsSubtargets.isNotEmpty() },
- PlatformTarget.Group("wasmWasi", wasiSubtargets).takeIf { wasiSubtargets.isNotEmpty() },
+ PlatformTarget.Group("wasmJs", jsSubtargets, jsIsStub).takeIf { jsSubtargets.isNotEmpty() },
+ PlatformTarget.Group("wasmWasi", wasiSubtargets, wasiIsStub).takeIf { wasiSubtargets.isNotEmpty() },
)
- PlatformTarget.Group(TableColumn.Wasm.name, wasmSubtargets)
+ PlatformTarget.Group(
+ name = TableColumn.Wasm.name,
+ subtargets = wasmSubtargets,
+ stub = subproject.optionalPropertyValue(TableColumn.Wasm.name, "stub"),
+ )
}
KotlinPlatformType.native -> {
@@ -148,15 +163,17 @@ abstract class DumpPlatformsTask : DefaultTask() {
PlatformTarget.Group(
name = "apple",
subtargets = listOf(
- targets.nativeGroup("ios"),
- targets.nativeGroup("macos"),
- targets.nativeGroup("watchos"),
- targets.nativeGroup("tvos"),
+ targets.nativeGroup(subproject, "ios"),
+ targets.nativeGroup(subproject, "macos"),
+ targets.nativeGroup(subproject, "watchos"),
+ targets.nativeGroup(subproject, "tvos"),
),
+ stub = subproject.optionalPropertyValue("apple", "stub"),
),
- targets.nativeGroup("linux"),
- targets.nativeGroup("windows", "mingw"),
- )
+ targets.nativeGroup(subproject, "linux"),
+ targets.nativeGroup(subproject, "windows", "mingw"),
+ ),
+ stub = subproject.optionalPropertyValue(TableColumn.Native.name, "stub"),
)
}
@@ -173,29 +190,34 @@ abstract class DumpPlatformsTask : DefaultTask() {
name: String,
project: Project,
condition: (KotlinTarget) -> Boolean,
- ): List {
+ ): Pair>? {
val foundTargets = filter(condition)
.filterIsInstance()
if (foundTargets.isEmpty()) {
- return emptyList()
+ return null
}
if (foundTargets.size > 1) {
error("Multiple $name targets are not supported (project ${project.name})")
}
- val jsSubtargets = foundTargets.single().subTargets.map { subTargetWithBinary ->
- PlatformTarget.LeafTarget(subTargetWithBinary.name)
+ val target = foundTargets.single()
+ val jsSubtargets = target.subTargets.map { subTargetWithBinary ->
+ val isStub = project.optionalPropertyValue(subTargetWithBinary.name, "stub", target.name)
+ PlatformTarget.LeafTarget(subTargetWithBinary.name, isStub)
}
- return jsSubtargets
+ return target to jsSubtargets
}
- private fun List.nativeGroup(name: String, prefix: String = name): PlatformTarget.Group {
+ private fun List.nativeGroup(subproject: Project, name: String, prefix: String = name): PlatformTarget.Group {
return PlatformTarget.Group(
name = name,
- subtargets = filter { it.name.startsWith(prefix) }.map { PlatformTarget.LeafTarget(it.name) },
+ subtargets = filter { it.name.startsWith(prefix) }.map {
+ PlatformTarget.LeafTarget(it.name, subproject.optionalPropertyValue(it.name, "stub"))
+ },
+ stub = subproject.optionalPropertyValue(name, "stub")
)
}
@@ -224,12 +246,25 @@ abstract class DumpPlatformsTask : DefaultTask() {
is PlatformTarget.LeafTarget -> {
append(target.name)
+ if (target.stub) {
+ append(" [stub]")
+ }
}
is PlatformTarget.Group -> {
- if (!topLevel) {
- append(target.name)
+ when {
+ !topLevel -> {
+ append(target.name)
+ if (target.stub) {
+ append(" [stub]")
+ }
+ }
+
+ target.stub -> {
+ append("[stubs]")
+ }
}
+
append("")
target.subtargets.forEach { subtarget ->
append("")
diff --git a/krpc/gradle.properties b/krpc/gradle.properties
index b41a299a8..babad0fbe 100644
--- a/krpc/gradle.properties
+++ b/krpc/gradle.properties
@@ -1,5 +1,5 @@
#
-# Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
+# Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
#
# https://github.com/oshai/kotlin-logging/issues/433
diff --git a/krpc/krpc-test/gradle.properties b/krpc/krpc-test/gradle.properties
index db06764d8..c77da55e6 100644
--- a/krpc/krpc-test/gradle.properties
+++ b/krpc/krpc-test/gradle.properties
@@ -3,4 +3,4 @@
#
# tests fail with some obscure reason
-kotlinx.rpc.exclude.wasmJsD8=true
+kotlinx.rpc.exclude.wasmJs.d8=true