Skip to content

Commit 3bff839

Browse files
timofey-soloninSpace Team
authored andcommitted
Always pack original .jar for JVM fragment to avoid breaking on MR jars consumption
^KT-81375
1 parent ee51e24 commit 3bff839

File tree

4 files changed

+102
-51
lines changed

4 files changed

+102
-51
lines changed

libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/uklibs/UklibConsumptionIT.kt

Lines changed: 66 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package org.jetbrains.kotlin.gradle.uklibs
99

1010
import com.android.build.api.dsl.LibraryExtension
1111
import org.gradle.api.tasks.JavaExec
12+
import org.gradle.jvm.tasks.Jar
1213
import org.gradle.kotlin.dsl.kotlin
1314
import org.gradle.util.GradleVersion
1415
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
@@ -737,7 +738,7 @@ class UklibConsumptionIT : KGPBaseTest() {
737738
File("empty/build/classes/kotlin/jvm/main"),
738739
File("empty/build/classes/java/jvmMain"),
739740
File("empty/build/processedResources/jvm/main"),
740-
File("transformed/unzipped_uklib_producer.uklib/jvmMain"),
741+
File("transformed/uklib_jar_fragment.jar"),
741742
File("kotlin-stdlib/${defaultBuildOptions.kotlinVersion}/kotlin-stdlib-${defaultBuildOptions.kotlinVersion}.jar"),
742743
File("annotations-13.0.jar"),
743744
)
@@ -821,7 +822,7 @@ class UklibConsumptionIT : KGPBaseTest() {
821822
) to dependency.classpath.map {
822823
RelativePath(
823824
it.relativeTo(consumer.projectPath.toFile().canonicalFile)
824-
.toPath().toList().takeLast(3).map { it.pathString }
825+
.toPath().toList().takeLast(2).map { it.pathString }
825826
)
826827
}
827828
}
@@ -832,15 +833,15 @@ class UklibConsumptionIT : KGPBaseTest() {
832833
first = Coordinate("producer", "empty", "1.0", "commonMain"),
833834
second = mutableListOf(
834835
RelativePath(
835-
mutableListOf("metadata", "kotlinTransformedMetadataLibraries", "uklib-producer-empty-1.0-commonMain-",),
836+
mutableListOf("kotlinTransformedMetadataLibraries", "uklib-producer-empty-1.0-commonMain-",),
836837
),
837838
),
838839
),
839840
"jvmMain" to Pair(
840841
first = Coordinate("producer", "empty", "1.0", "jvm"),
841842
second = mutableListOf(
842843
RelativePath(
843-
mutableListOf("transformed", "unzipped_uklib_empty.uklib", "jvmMain"),
844+
mutableListOf("transformed", "uklib_jar_fragment.jar"),
844845
),
845846
),
846847
),
@@ -849,7 +850,7 @@ class UklibConsumptionIT : KGPBaseTest() {
849850
second = mutableListOf(
850851
RelativePath(
851852
mutableListOf(
852-
"transformed", "unzipped_uklib_empty.uklib", "linuxArm64Main",
853+
"unzipped_uklib_empty.uklib", "linuxArm64Main",
853854
),
854855
),
855856
),
@@ -1146,48 +1147,51 @@ class UklibConsumptionIT : KGPBaseTest() {
11461147
}
11471148

11481149
@GradleTest
1149-
fun `uklib consumption - linkage with cinterops`(version: GradleVersion) {
1150+
fun `uklib consumption - MR jar`(version: GradleVersion) {
11501151
val producer = project(
11511152
"empty",
11521153
version,
11531154
) {
11541155
addKgpToBuildScriptCompilationClasspath()
11551156
buildScriptInjection {
11561157
// Commonizer is not supported yet which will be captured by this test
1157-
project.extraProperties.set(PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION, true)
11581158
project.setUklibPublicationStrategy()
11591159
project.applyMultiplatform {
1160-
listOf(
1161-
linuxArm64(),
1162-
linuxX64(),
1163-
).forEach {
1164-
val foo = project.layout.projectDirectory.file("foo.def")
1165-
val bar = project.layout.projectDirectory.file("bar.def")
1166-
1167-
foo.asFile.writeText(
1168-
"""
1169-
language = C
1170-
---
1171-
void foo(void);
1172-
""".trimIndent()
1173-
)
1174-
bar.asFile.writeText(
1175-
"""
1176-
language = C
1177-
---
1178-
void bar(void);
1179-
""".trimIndent()
1180-
)
1181-
1182-
it.compilations.getByName("main").cinterops.create("foo") {
1183-
it.definitionFile.set(foo)
1160+
jvm {
1161+
project.tasks.named(artifactsTaskName, Jar::class.java) {
1162+
it.manifest {
1163+
it.attributes(mapOf("Multi-Release" to true))
1164+
}
1165+
it.rename(".*module-info.class.*", "META-INF/versions/9/module-info.class")
11841166
}
1185-
it.compilations.getByName("main").cinterops.create("bar") {
1186-
it.definitionFile.set(bar)
1167+
compilations.getByName("main").compileJavaTaskProvider?.configure {
1168+
it.sourceCompatibility = "9"
1169+
it.targetCompatibility = "9"
1170+
}
1171+
compilerOptions {
1172+
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_9)
11871173
}
11881174
}
1189-
1190-
sourceSets.commonMain.get().compileSource("class Common")
1175+
val jvmSources = project.layout.projectDirectory.file("src/jvmMain/java").asFile
1176+
jvmSources.mkdirs()
1177+
val producer = jvmSources.resolve("producer/Producer.java")
1178+
producer.parentFile.mkdirs()
1179+
producer.writeText("""
1180+
package producer;
1181+
1182+
public class Producer { }
1183+
""".trimIndent())
1184+
val moduleInfo = jvmSources.resolve("module-info.java")
1185+
moduleInfo.parentFile.mkdirs()
1186+
moduleInfo.writeText(
1187+
"""
1188+
module producer {
1189+
requires transitive kotlin.stdlib;
1190+
1191+
exports producer;
1192+
}
1193+
""".trimIndent()
1194+
)
11911195
}
11921196
}
11931197
}.publish()
@@ -1198,28 +1202,42 @@ class UklibConsumptionIT : KGPBaseTest() {
11981202
buildScriptInjection {
11991203
project.setUklibResolutionStrategy()
12001204
project.applyMultiplatform {
1201-
linuxArm64 {
1202-
binaries.staticLib { }
1205+
jvm {
1206+
compilations.getByName("main").compileJavaTaskProvider?.configure {
1207+
it.sourceCompatibility = "9"
1208+
it.targetCompatibility = "9"
1209+
}
1210+
compilerOptions {
1211+
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_9)
1212+
}
12031213
}
1204-
sourceSets.commonMain.get().compileSource(
1205-
"""
1206-
@file:OptIn(ExperimentalForeignApi::class)
1207-
1208-
import kotlinx.cinterop.ExperimentalForeignApi
1214+
val jvmSources = project.layout.projectDirectory.file("src/jvmMain/kotlin").asFile
1215+
jvmSources.mkdirs()
12091216

1210-
fun consumeCinterops() {
1211-
bar.bar()
1212-
foo.foo()
1213-
}
1217+
val moduleInfo = jvmSources.resolve("module-info.java")
1218+
moduleInfo.parentFile.mkdirs()
1219+
moduleInfo.writeText(
1220+
"""
1221+
module consumer {
1222+
requires transitive kotlin.stdlib;
1223+
requires producer;
1224+
}
12141225
""".trimIndent()
12151226
)
1227+
1228+
sourceSets.jvmMain.get().compileSource("""
1229+
fun consume() {
1230+
producer.Producer()
1231+
}
1232+
""".trimIndent())
1233+
12161234
sourceSets.commonMain.get().dependencies {
1217-
api(producer.rootCoordinate)
1235+
implementation(producer.rootCoordinate)
12181236
}
12191237
}
12201238
}
12211239

1222-
build("linkDebugStaticLinuxArm64")
1240+
build("assemble")
12231241
}
12241242
}
12251243

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/uklibs/UklibFragmentPlatformAttribute.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ internal val KotlinTarget.uklibFragmentPlatformAttribute: UklibFragmentPlatformA
112112
/**
113113
* These attribute names will be recorded in and resolved from the Umanifest
114114
*/
115-
private enum class UklibTargetFragmentAttribute {
115+
internal enum class UklibTargetFragmentAttribute {
116116
js_ir,
117117
wasm_js,
118118
wasm_wasi,

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/uklibs/consumption/UnzippedUklibToPlatformCompilationTransform.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import org.gradle.api.tasks.Input
1313
import org.gradle.api.tasks.PathSensitive
1414
import org.gradle.api.tasks.PathSensitivity
1515
import org.gradle.work.DisableCachingByDefault
16+
import org.jetbrains.kotlin.gradle.plugin.mpp.uklibs.UklibTargetFragmentAttribute
1617
import org.jetbrains.kotlin.gradle.plugin.mpp.uklibs.serialization.deserializeUklibFromDirectory
1718
import java.io.File
1819

@@ -44,7 +45,16 @@ internal abstract class UnzippedUklibToPlatformCompilationTransform :
4445
}
4546

4647
platformFragments.forEach {
47-
outputs.dir(it.files.single())
48+
val output = it.files.single()
49+
if (output.isDirectory) {
50+
outputs.dir(output)
51+
} else if (it.attributes.singleOrNull() == UklibTargetFragmentAttribute.jvm.name) {
52+
val outputJar = outputs.file("uklib_jar_fragment.jar")
53+
output.copyTo(outputJar, overwrite = true)
54+
outputs.file(outputJar)
55+
} else {
56+
outputs.file(output)
57+
}
4858
}
4959
}
50-
}
60+
}

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/uklibs/serialization/uklibSerialization.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ internal data class IncompatibleUklibFragmentFile(val file: File) : IllegalState
6565
*/
6666
private val allowRepackingArchivesWithExtensions = setOf(
6767
"klib",
68+
)
69+
70+
// Always pack jars as is to support MR jars
71+
private val packArchiveAsIs = setOf(
6872
"jar",
6973
)
7074

@@ -94,6 +98,12 @@ private fun zipUklibContents(
9498
identifier = identifier,
9599
zipOutputStream = zipOutputStream,
96100
)
101+
} else if (file.extension in packArchiveAsIs) {
102+
packFile(
103+
file = file,
104+
identifier = identifier,
105+
zipOutputStream = zipOutputStream,
106+
)
97107
} else if (file.extension in allowRepackingArchivesWithExtensions) {
98108
val temp = temporariesDirectory.resolve(identifier)
99109
if (temp.exists()) temp.deleteDirectoryContents()
@@ -132,6 +142,19 @@ private fun packDirectory(
132142
}
133143
}
134144

145+
private fun packFile(
146+
file: File,
147+
identifier: String,
148+
zipOutputStream: ZipOutputStream
149+
) {
150+
val zipEntry = ZipEntry(identifier)
151+
zipOutputStream.putNextEntry(zipEntry)
152+
file.inputStream().use { inputStream ->
153+
inputStream.copyTo(zipOutputStream)
154+
}
155+
zipOutputStream.closeEntry()
156+
}
157+
135158
private fun unzip(zipFilePath: File, outputFolderPath: File) {
136159
ZipInputStream(FileInputStream(zipFilePath)).use { zipInputStream ->
137160
var zipEntry: ZipEntry? = zipInputStream.nextEntry

0 commit comments

Comments
 (0)