Skip to content

Commit cd36d9e

Browse files
committed
Fixed krpc compatibility tests by separating different versions into modules, isolating classpaths and using BTA to set the Kotlin compiler version during the compilation
1 parent 5609dce commit cd36d9e

File tree

23 files changed

+388
-548
lines changed

23 files changed

+388
-548
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@ detekt/reports/**
3939
local.properties
4040
scan-journal.log
4141

42+
# krpc compat tests
43+
tests/krpc-protocol-compatibility-tests/v*
44+
gradle-conventions/src/main/kotlin/util/krpc_compat/versions.kt

gradle-conventions-settings/settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rootProject.name = "gradle-conventions-settings"
1212
// Code below is a hack because a chicken-egg problem, I can't use myself as a settings-plugin
1313
apply(from = "src/main/kotlin/conventions-repositories.settings.gradle.kts")
1414
apply(from = "src/main/kotlin/conventions-version-resolution.settings.gradle.kts")
15+
apply(from = "src/main/kotlin/krpc-compat-tests.settings.gradle.kts")
1516

1617
include(":develocity")
1718

gradle-conventions-settings/src/main/kotlin/conventions-version-resolution.settings.gradle.kts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ fun VersionCatalogBuilder.resolveKotlinVersion(versionCatalog: Map<String, Strin
139139

140140
// Resolves a core kotlinx.rpc version (without a Kotlin version prefix) from the Version Catalog.
141141
// Uses LIBRARY_VERSION_ENV_VAR_NAME instead if present
142-
fun VersionCatalogBuilder.resolveLibraryVersion(versionCatalog: Map<String, String>) {
142+
fun resolveLibraryVersion(versionCatalog: Map<String, String>): String {
143143
val libraryCoreVersion: String = System.getenv(SettingsConventions.LIBRARY_VERSION_ENV_VAR_NAME)
144144
?.takeIf { it.isNotBlank() }
145145
?: versionCatalog[SettingsConventions.LIBRARY_CORE_VERSION_ALIAS]
@@ -158,27 +158,31 @@ fun VersionCatalogBuilder.resolveLibraryVersion(versionCatalog: Map<String, Stri
158158
else -> libraryCoreVersion.substringBefore('-') + eapVersion
159159
}
160160

161-
version(SettingsConventions.LIBRARY_CORE_VERSION_ALIAS, resultingVersion)
161+
return resultingVersion
162162
}
163163

164164
fun String.kotlinVersionParsed(): KotlinVersion {
165165
val (major, minor, patch) = substringBefore('-').split(".").map { it.toInt() }
166166
return KotlinVersion(major, minor, patch)
167167
}
168168

169+
val currentPath: Path = file(".").toPath().toAbsolutePath()
170+
val rootDir = findGlobalRootDirPath(currentPath)
171+
val versionCatalog = resolveVersionCatalog(rootDir)
172+
val libVersion = resolveLibraryVersion(versionCatalog)
173+
174+
extra["libVersion"] = libVersion
175+
169176
dependencyResolutionManagement {
170177
versionCatalogs {
171178
create("libs") {
172-
val currentPath = file(".").toPath().toAbsolutePath()
173-
val rootDir = findGlobalRootDirPath(currentPath)
174-
175179
from(files("$rootDir/${SettingsConventions.LIBS_VERSION_CATALOG_PATH}"))
176180

177181
val versionCatalog = resolveVersionCatalog(rootDir)
178182

179183
val (kotlinVersion, compilerVersion) = resolveKotlinVersion(versionCatalog)
180184

181-
resolveLibraryVersion(versionCatalog)
185+
version(SettingsConventions.LIBRARY_CORE_VERSION_ALIAS, libVersion)
182186

183187
val kotlinVersionParsed = kotlinVersion.kotlinVersionParsed()
184188

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
import kotlin.io.path.createDirectories
6+
import kotlin.io.path.writeText
7+
8+
// ADD NEW VERSIONS HERE
9+
val versionDirs = mapOf(
10+
"v0_8" to CompatVersion("0.8.1", "2.2.0"),
11+
"v0_9" to CompatVersion("0.9.1", "2.2.0"),
12+
"v0_10" to CompatVersion("0.10.0", "2.2.20"),
13+
)
14+
15+
// DON'T MODIFY BELOW THIS LINE
16+
17+
val globalRootDirValue: String = extra["globalRootDir"] as? String
18+
?: error("globalRootDir property is not set")
19+
20+
val globalRootDir: java.nio.file.Path = java.nio.file.Path.of(globalRootDirValue)
21+
22+
val compatDir: java.nio.file.Path = globalRootDir
23+
.resolve("tests")
24+
.resolve("krpc-protocol-compatibility-tests")
25+
26+
val libVersion = settings.extra["libVersion"] as? String
27+
?: error("libVersion property is not set")
28+
29+
class CompatVersion(
30+
val rpc: String,
31+
val kotlin: String,
32+
)
33+
34+
versionDirs.forEach { (dir, version) ->
35+
val moduleDir = compatDir.resolve(dir)
36+
moduleDir.createDirectories()
37+
val buildFile = moduleDir.resolve("build.gradle.kts")
38+
buildFile.writeText(
39+
"""
40+
/* THIS FILE IS AUTO-GENERATED, DO NOT EDIT! */
41+
42+
import util.krpc_compat.setupCompat
43+
44+
setupCompat("${version.rpc}", "${version.kotlin}")
45+
46+
""".trimIndent()
47+
)
48+
val propertiesFile = moduleDir.resolve("gradle.properties")
49+
propertiesFile.writeText(
50+
"""
51+
/* THIS FILE IS AUTO-GENERATED, DO NOT EDIT! */
52+
53+
kotlin.compiler.runViaBuildToolsApi=true
54+
55+
""".trimIndent()
56+
)
57+
58+
logger.lifecycle("Generating :tests:krpc-protocol-compatibility-tests:$dir")
59+
include(":tests:krpc-protocol-compatibility-tests:$dir")
60+
}
61+
62+
val versionsConventionsFile: java.nio.file.Path = globalRootDir
63+
.resolve("gradle-conventions")
64+
.resolve("src")
65+
.resolve("main")
66+
.resolve("kotlin")
67+
.resolve("util")
68+
.resolve("krpc_compat")
69+
.resolve("versions.kt")
70+
71+
logger.lifecycle("Generating krpc_compat/versions.kt")
72+
versionsConventionsFile.writeText(
73+
"""
74+
|/* THIS FILE IS AUTO-GENERATED, DO NOT EDIT! */
75+
|
76+
|package util.krpc_compat
77+
|
78+
|val krpcCompatVersions = mapOf(
79+
| ${versionDirs.entries.joinToString("\n| ") { "\"${it.key}\" to \"${it.value.rpc}\"," }}
80+
|
81+
| "Latest" to "$libVersion", // current version
82+
|)
83+
|
84+
""".trimMargin()
85+
)

gradle-conventions/src/main/kotlin/compiler-specific-module.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ val processCsmTemplates =
2424
tasks.register<ProcessCsmTemplate>(
2525
"processCsmTemplates",
2626
libs.versions.kotlin.compiler.get(),
27+
emptyMap<String, String>(),
2728
templatesDir,
2829
sourcesDir,
2930
)

gradle-conventions/src/main/kotlin/util/csm/task.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import kotlin.io.path.writeLines
2121

2222
abstract class ProcessCsmTemplate @Inject constructor(
2323
@get:Input val kotlinComplierVersion: String,
24+
@get:Input val replacementMap: Map<String, String>,
2425
@get:InputDirectory val templatesDir: Provider<Path>,
2526
@get:OutputDirectory val sourcesDir: Provider<Path>,
2627
) : DefaultTask() {
@@ -43,6 +44,7 @@ abstract class ProcessCsmTemplate @Inject constructor(
4344
val lines = CsmTemplateProcessor.process(
4445
lines = file.readLines(Charsets.UTF_8),
4546
kotlinCompilerVersion = kotlinComplierVersion,
47+
replacementMap = replacementMap,
4648
logger = logger,
4749
)
4850
out.parent.toFile().mkdirs()

gradle-conventions/src/main/kotlin/util/csm/template.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import org.gradle.api.GradleException
88
import org.slf4j.Logger
99

1010
object CsmTemplateProcessor {
11-
fun process(lines: List<String>, kotlinCompilerVersion: String, logger: Logger): List<String> {
11+
fun process(lines: List<String>, kotlinCompilerVersion: String, logger: Logger, replacementMap: Map<String, String>): List<String> {
1212
val result = mutableListOf<String>()
1313

1414
val tags: ArrayDeque<String> = ArrayDeque()
@@ -21,7 +21,7 @@ object CsmTemplateProcessor {
2121
val defaultBuffer = mutableListOf<String>()
2222
val specificBuffer = mutableListOf<String>()
2323

24-
lines.forEachIndexed { i, line ->
24+
lines.map { it.applyReplacements(replacementMap) }.forEachIndexed { i, line ->
2525
val trimmed = line.trim()
2626
when {
2727
trimmed.startsWith("//##csm") -> {
@@ -179,3 +179,11 @@ object CsmTemplateProcessor {
179179
Skip, Apply;
180180
}
181181
}
182+
183+
private fun String.applyReplacements(replacementMap: Map<String, String>): String {
184+
var result = this
185+
replacementMap.forEach { (from, to) ->
186+
result = result.replace(from, to)
187+
}
188+
return result
189+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package util.krpc_compat
6+
7+
import org.gradle.api.Project
8+
import org.gradle.jvm.tasks.Jar
9+
import org.gradle.kotlin.dsl.named
10+
import org.jetbrains.kotlin.buildtools.api.ExperimentalBuildToolsApi
11+
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
12+
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
13+
import util.withKotlinJvmExtension
14+
15+
private fun kcp(suffix: String, version: String): String {
16+
return "org.jetbrains.kotlinx:kotlinx-rpc-compiler-plugin-$suffix:$version"
17+
}
18+
19+
fun Project.setupCompat(rpcVersion: String, kotlinVersion: String) {
20+
plugins.apply("org.jetbrains.kotlin.jvm")
21+
22+
dependencies.apply {
23+
add("compileOnly", project(":tests:krpc-protocol-compatibility-tests:test-api"))
24+
25+
add("implementation", "org.jetbrains.kotlinx:kotlinx-rpc-krpc-client:$rpcVersion")
26+
add("implementation", "org.jetbrains.kotlinx:kotlinx-rpc-krpc-server:$rpcVersion")
27+
add("implementation", "org.jetbrains.kotlinx:kotlinx-rpc-krpc-serialization-json:$rpcVersion")
28+
29+
val kcpVersion = "$kotlinVersion-$rpcVersion"
30+
add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, kcp("common", kcpVersion))
31+
add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, kcp("cli", kcpVersion))
32+
add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, kcp("backend", kcpVersion))
33+
add(PLUGIN_CLASSPATH_CONFIGURATION_NAME, kcp("k2", kcpVersion))
34+
}
35+
36+
withKotlinJvmExtension {
37+
@OptIn(ExperimentalBuildToolsApi::class, ExperimentalKotlinGradlePluginApi::class)
38+
compilerVersion.set(kotlinVersion)
39+
40+
sourceSets.named("main") {
41+
kotlin.srcDirs(layout.buildDirectory.dir("generated-sources").map { it.asFile.resolve("csm") })
42+
}
43+
}
44+
45+
tasks.named<Jar>("jar") {
46+
archiveVersion.set(rpcVersion)
47+
}
48+
49+
tasks.named("compileKotlin").configure {
50+
dependsOn(":tests:krpc-protocol-compatibility-tests:process_template_${project.name}")
51+
}
52+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package util.other
6+
7+
import org.gradle.api.DefaultTask
8+
import org.gradle.api.NamedDomainObjectContainer
9+
import org.gradle.api.NamedDomainObjectProvider
10+
import org.gradle.api.Project
11+
import org.gradle.api.tasks.Input
12+
import org.gradle.api.tasks.OutputDirectory
13+
import org.gradle.api.tasks.TaskAction
14+
import org.gradle.kotlin.dsl.register
15+
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
16+
import util.withKotlinJvmExtension
17+
import util.withKotlinKmpExtension
18+
import java.io.File
19+
import javax.inject.Inject
20+
21+
abstract class GenerateSourceTask @Inject constructor(
22+
@get:Input val filename: String,
23+
@get:Input val text: String,
24+
@get:OutputDirectory val sourcesDir: File,
25+
) : DefaultTask() {
26+
@TaskAction
27+
fun generate() {
28+
val sourceFile = File(sourcesDir, "${filename}.kt")
29+
sourceFile.writeText(text)
30+
}
31+
}
32+
33+
fun Project.generateSource(
34+
name: String,
35+
text: String,
36+
chooseSourceSet: NamedDomainObjectContainer<KotlinSourceSet>.() -> NamedDomainObjectProvider<KotlinSourceSet>,
37+
) {
38+
val sourcesDir = File(project.layout.buildDirectory.asFile.get(), "generated-sources/kotlin")
39+
40+
val generatePluginVersionTask =
41+
tasks.register<GenerateSourceTask>("generateSources_$name", name, text, sourcesDir)
42+
43+
withKotlinJvmExtension {
44+
chooseSourceSet(sourceSets).configure {
45+
kotlin.srcDir(generatePluginVersionTask.map { it.sourcesDir })
46+
}
47+
}
48+
49+
withKotlinKmpExtension {
50+
chooseSourceSet(sourceSets).configure {
51+
kotlin.srcDir(generatePluginVersionTask.map { it.sourcesDir })
52+
}
53+
}
54+
}

gradle-plugin/build.gradle.kts

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
6+
import util.other.generateSource
67

78
/*
89
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
@@ -55,36 +56,15 @@ gradlePlugin {
5556
}
5657
}
5758

58-
abstract class GeneratePluginVersionTask @Inject constructor(
59-
@get:Input val pluginVersion: String,
60-
@get:OutputDirectory val sourcesDir: File
61-
) : DefaultTask() {
62-
@TaskAction
63-
fun generate() {
64-
val sourceFile = File(sourcesDir, "Versions.kt")
65-
66-
sourceFile.writeText(
67-
"""
68-
package kotlinx.rpc
69-
70-
public const val PLUGIN_VERSION: String = "$pluginVersion"
71-
72-
""".trimIndent()
73-
)
74-
}
75-
}
76-
77-
val sourcesDir = File(project.layout.buildDirectory.asFile.get(), "generated-sources/pluginVersion")
78-
79-
val generatePluginVersionTask =
80-
tasks.register<GeneratePluginVersionTask>("generatePluginVersion", version.toString(), sourcesDir)
81-
82-
kotlin {
83-
sourceSets {
84-
main {
85-
kotlin.srcDir(generatePluginVersionTask.map { it.sourcesDir })
86-
}
87-
}
88-
}
59+
generateSource(
60+
name = "Versions",
61+
text = """
62+
package kotlinx.rpc
63+
64+
public const val PLUGIN_VERSION: String = "$version"
65+
66+
""".trimIndent(),
67+
chooseSourceSet = { main }
68+
)
8969

9070
logger.lifecycle("[Gradle Plugin] kotlinx.rpc project version: $version")

0 commit comments

Comments
 (0)