Skip to content

Commit ddd869e

Browse files
authored
Declare byte-buddy as 'implementation' dependency instead of shading. (#4266)
Shading byte buddy might have negative effects: - It increases binary size by ~3MB w/o an easy option to opt-out - It causes JPMS issues (because of the re-location itself) The used APIs from the dependency can be considered stable.
1 parent 06395bc commit ddd869e

File tree

6 files changed

+16
-66
lines changed

6 files changed

+16
-66
lines changed

Diff for: benchmarks/build.gradle.kts

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import org.jetbrains.kotlin.gradle.tasks.*
44
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
55

66
plugins {
7-
id("com.github.johnrengelman.shadow")
87
id("me.champeau.jmh")
98
}
109

Diff for: build.gradle.kts

-3
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ buildscript {
2727
classpath("ru.vyarus:gradle-animalsniffer-plugin:${version("animalsniffer")}") // Android API check
2828
classpath("org.jetbrains.kotlin:atomicfu:${version("kotlin")}")
2929
classpath("org.jetbrains.kotlinx:kover-gradle-plugin:${version("kover")}")
30-
31-
// JMH plugins
32-
classpath("gradle.plugin.com.github.johnrengelman:shadow:${version("shadow")}")
3330
}
3431

3532
with(CacheRedirector) { buildscript.configureBuildScript(rootProject) }

Diff for: buildSrc/src/main/kotlin/version-file-conventions.gradle.kts

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ import org.gradle.api.tasks.bundling.*
33
configure(subprojects.filter { !unpublished.contains(it.name) && it.name !in sourceless }) {
44
val project = this
55
val jarTaskName = when {
6-
project.name == "kotlinx-coroutines-debug" -> {
7-
project.apply(plugin = "com.github.johnrengelman.shadow")
8-
"shadowJar"
9-
}
106
isMultiplatform -> "jvmJar"
117
else -> "jar"
128
}

Diff for: gradle.properties

-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ jna_version=5.9.0
2828
# Gradle
2929
jdk_toolchain_version=11
3030
animalsniffer_version=1.7.1
31-
shadow_version=7.1.2
32-
#shadow_version=8.1.1 For Gradle 8, not compatible with Gradle 7
3331

3432
# Android versions
3533
android_version=4.1.1.4

Diff for: kotlinx-coroutines-debug/README.md

+3-6
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,9 @@ dependency of `kotlinx-coroutines-test`) may fail with `DuplicateRelativeFileExc
167167

168168
The problem is that Android merges the resources of all its dependencies into a single directory and complains about
169169
conflicts, but:
170-
* `kotlinx-coroutines-debug` transitively depends on JNA and JNA-platform, both of which include license files in their
171-
META-INF directories. Trying to merge these files leads to conflicts, which means that any Android project that
172-
depends on JNA and JNA-platform will experience build failures.
173-
* Additionally, `kotlinx-coroutines-debug` embeds `byte-buddy-agent` and `byte-buddy`, along with their resource files.
174-
Then, if the project separately depends on `byte-buddy`, merging the resources of `kotlinx-coroutines-debug` with ones
175-
from `byte-buddy` and `byte-buddy-agent` will lead to conflicts as the resource files are duplicated.
170+
`kotlinx-coroutines-debug` transitively depends on JNA and JNA-platform, byte-buddy and byte-buddy-agent, all of them include license files in their
171+
META-INF directories. Trying to merge these files leads to conflicts, which means that any Android project that
172+
depends on JNA and JNA-platform will experience build failures.
176173

177174
One possible workaround for these issues is to add the following to the `android` block in your gradle file for the
178175
application subproject:

Diff for: kotlinx-coroutines-debug/build.gradle.kts

+13-50
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
1-
import com.github.jengelman.gradle.plugins.shadow.tasks.*
2-
import java.net.*
3-
import java.nio.file.*
1+
import org.gradle.api.JavaVersion
2+
import org.gradle.api.file.DuplicatesStrategy
3+
import org.gradle.api.tasks.bundling.Jar
4+
import org.gradle.api.tasks.testing.Test
45

56
plugins {
6-
id("com.github.johnrengelman.shadow")
77
id("org.jetbrains.kotlinx.kover") // apply plugin to use autocomplete for Kover DSL
88
}
99

10-
configurations {
11-
val shadowDeps by creating
12-
compileOnly.configure {
13-
extendsFrom(shadowDeps)
14-
}
15-
runtimeOnly.configure {
16-
extendsFrom(shadowDeps)
17-
}
18-
}
19-
2010
val junit_version by properties
2111
val junit5_version by properties
2212
val byte_buddy_version by properties
@@ -28,8 +18,8 @@ dependencies {
2818
compileOnly("org.junit.jupiter:junit-jupiter-api:$junit5_version")
2919
testImplementation("org.junit.jupiter:junit-jupiter-engine:$junit5_version")
3020
testImplementation("org.junit.platform:junit-platform-testkit:1.7.0")
31-
add("shadowDeps", "net.bytebuddy:byte-buddy:$byte_buddy_version")
32-
add("shadowDeps", "net.bytebuddy:byte-buddy-agent:$byte_buddy_version")
21+
implementation("net.bytebuddy:byte-buddy:$byte_buddy_version")
22+
implementation("net.bytebuddy:byte-buddy-agent:$byte_buddy_version")
3323
compileOnly("io.projectreactor.tools:blockhound:$blockhound_version")
3424
testImplementation("io.projectreactor.tools:blockhound:$blockhound_version")
3525
testImplementation("com.google.code.gson:gson:2.8.6")
@@ -50,21 +40,7 @@ tasks.withType<Test>().configureEach {
5040
}
5141
}
5242

53-
val jar by tasks.existing(Jar::class) {
54-
enabled = false
55-
}
56-
57-
val shadowJar by tasks.existing(ShadowJar::class) {
58-
// Shadow only byte buddy, do not package kotlin stdlib
59-
configurations = listOf(project.configurations["shadowDeps"])
60-
relocate("net.bytebuddy", "kotlinx.coroutines.repackaged.net.bytebuddy")
61-
/* These classifiers are both set to `null` to trick Gradle into thinking that this jar file is both the
62-
artifact from the `jar` task and the one from `shadowJar`. Without this, Gradle complains that the artifact
63-
from the `jar` task is not present when the compilaton finishes, even if the file with this name exists. */
64-
archiveClassifier.convention(null as String?)
65-
archiveClassifier = null
66-
archiveBaseName = jar.flatMap { it.archiveBaseName }
67-
archiveVersion = jar.flatMap { it.archiveVersion }
43+
tasks.named<Jar>("jar") {
6844
manifest {
6945
attributes(
7046
mapOf(
@@ -74,30 +50,17 @@ val shadowJar by tasks.existing(ShadowJar::class) {
7450
)
7551
)
7652
}
53+
7754
// add module-info.class to the META-INF/versions/9/ directory.
7855
dependsOn(tasks.compileModuleInfoJava)
79-
doLast {
80-
// We can't do that directly with the shadowJar task because it doesn't support replacing existing files.
81-
val zipPath = this@existing.outputs.files.singleFile.toPath()
82-
val zipUri = URI.create("jar:${zipPath.toUri()}")
83-
val moduleInfoFilePath = tasks.compileModuleInfoJava.get().outputs.files.asFileTree.matching {
84-
include("module-info.class")
85-
}.singleFile.toPath()
86-
FileSystems.newFileSystem(zipUri, emptyMap<String, String>()).use { fs ->
87-
val moduleInfoFile = fs.getPath("META-INF/versions/9/module-info.class")
88-
Files.copy(moduleInfoFilePath, moduleInfoFile, StandardCopyOption.REPLACE_EXISTING)
89-
}
56+
from(tasks.compileModuleInfoJava.get().outputs.files.asFileTree.matching {
57+
include("module-info.class")
58+
}) {
59+
this.duplicatesStrategy = DuplicatesStrategy.INCLUDE
60+
into("META-INF/versions/9")
9061
}
9162
}
9263

93-
configurations {
94-
// shadowJar is already part of the `shadowRuntimeElements` and `shadowApiElements`, but the other subprojects
95-
// that depend on `kotlinx-coroutines-debug` look at `runtimeElements` and `apiElements`.
96-
artifacts {
97-
add("apiElements", shadowJar)
98-
add("runtimeElements", shadowJar)
99-
}
100-
}
10164

10265
kover {
10366
reports {

0 commit comments

Comments
 (0)