From 5c99243c107d8897f627f917b0dc81d7f368a4aa Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Mon, 1 Jul 2019 17:20:21 +0300 Subject: [PATCH] Substitute kotlin-reflect with kotlin-reflect-api in compile classpath Currently Kotlin IC can only track changes in "default" jar files by associating a history of ABI diffs with a source set's jar file. kotlin-reflect is a non-default fat jar, which causes non-inremental builds when it gets changed and included in a compile classpath. To avoid this problem, kotlin-reflect-api project was added. It is assumed that only kotlin-reflect-api should be used for compilation. However, Gradle is known to leak transitive runtime dependencies to a compile classpath, i.e. when `:b` has a runtime dependency on `:a`, and `:c` has a compile dependency on `:b`, `:c` also gets `:a` in its compile classpath. Before this change kotlin-reflect was leaked to compiler tests's classpath through kotlin-scripting-compiler-impl. To work around this issue, and to prevent similar issues from happening, this change introduces a dependency substitution from kotlin-reflect to kotlin-reflect-api in all compile classpath configurations. #KT-32954 Fixed --- build.gradle.kts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 32f768bf898..1cf6ebd3ff0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -743,9 +743,30 @@ fun Project.configureJvmProject(javaHome: String, javaVersion: String) { tasks.withType { executable = File(javaHome, "bin/java").canonicalPath } + + plugins.withId("java-base") { + configureShadowJarSubstitutionInCompileClasspath() + } } -tasks.create("findNonStandardShadowJarsInClasspath").doLast { +fun Project.configureShadowJarSubstitutionInCompileClasspath() { + val substitutionMap = mapOf(":kotlin-reflect" to ":kotlin-reflect-api") + + fun configureSubstitution(substitution: DependencySubstitution) { + val requestedProject = (substitution.requested as? ProjectComponentSelector)?.projectPath ?: return + val replacementProject = substitutionMap[requestedProject] ?: return + substitution.useTarget(project(replacementProject), "Non-default shadow jars should not be used in compile classpath") + } + + sourceSets.all { + val compileClasspathConfig = configurations.getByName(compileClasspathConfigurationName) + compileClasspathConfig.resolutionStrategy.dependencySubstitution { + all(::configureSubstitution) + } + } +} + +tasks.create("findShadowJarsInClasspath").doLast { fun Collection.printSorted(indent: String = " ") { sortedBy { it.path }.forEach { println(indent + it.relativeTo(rootProject.projectDir)) } }