[Gradle] Prevent early resolve of compiler classpath

#KT-45834 Fixed
This commit is contained in:
Alexander Likhachev
2021-04-08 17:37:54 +03:00
parent 660208740e
commit f2f2df90aa
7 changed files with 77 additions and 27 deletions
@@ -248,7 +248,8 @@ abstract class BaseGradleIT {
val configurationCacheProblems: ConfigurationCacheProblems = ConfigurationCacheProblems.FAIL, val configurationCacheProblems: ConfigurationCacheProblems = ConfigurationCacheProblems.FAIL,
val warningMode: WarningMode = WarningMode.Fail, val warningMode: WarningMode = WarningMode.Fail,
val useFir: Boolean = false, val useFir: Boolean = false,
val customEnvironmentVariables: Map<String, String> = mapOf() val customEnvironmentVariables: Map<String, String> = mapOf(),
val dryRun: Boolean = false,
) )
enum class ConfigurationCacheProblems { enum class ConfigurationCacheProblems {
@@ -939,6 +940,10 @@ Finished executing task ':$taskName'|
add("-Pkotlin.useFir=true") add("-Pkotlin.useFir=true")
} }
if (options.dryRun) {
add("--dry-run")
}
add("-Dorg.gradle.unsafe.configuration-cache=${options.configurationCache}") add("-Dorg.gradle.unsafe.configuration-cache=${options.configurationCache}")
add("-Dorg.gradle.unsafe.configuration-cache-problems=${options.configurationCacheProblems.name.toLowerCase()}") add("-Dorg.gradle.unsafe.configuration-cache-problems=${options.configurationCacheProblems.name.toLowerCase()}")
@@ -1240,4 +1240,45 @@ class KotlinGradleIT : BaseGradleIT() {
} }
} }
} }
@Test
fun testEarlyConfigurationsResolutionKotlin() = testEarlyConfigurationsResolution("kotlinProject", kts = false)
@Test
fun testEarlyConfigurationsResolutionKotlinJs() = testEarlyConfigurationsResolution("kotlin-js-browser-project", kts = true)
private fun testEarlyConfigurationsResolution(projectName: String, kts: Boolean) = with(Project(projectName = projectName)) {
setupWorkingDir()
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
//language=Gradle
gradleBuildScript().appendText(
"""${'\n'}
// KT-45834 start
${if (kts) "var" else "def"} ready = false
gradle.taskGraph.whenReady {
println("Task Graph Ready")
ready = true
}
allprojects {
configurations.forEach { configuration ->
configuration.incoming.beforeResolve {
println("Resolving ${'$'}configuration")
if (!ready) {
throw ${if (kts) "" else "new"} GradleException("${'$'}configuration is being resolved at configuration time")
}
}
}
}
// KT-45834 end
""".trimIndent()
)
build(
"assemble",
options = defaultBuildOptions().copy(dryRun = true)
) {
assertSuccessful()
}
}
} }
@@ -79,7 +79,7 @@ class UpToDateIT : BaseGradleIT() {
override fun initProject(project: Project) = with(project) { override fun initProject(project: Project) = with(project) {
buildGradle.appendText( buildGradle.appendText(
"\nafterEvaluate { println 'compiler_cp=' + compileKotlin.getComputedCompilerClasspath\$kotlin_gradle_plugin() }" "\nafterEvaluate { println 'compiler_cp=' + compileKotlin.getComputedCompilerClasspath\$kotlin_gradle_plugin().toList() }"
) )
build("clean") { originalCompilerCp = "compiler_cp=\\[(.*)]".toRegex().find(output)!!.groupValues[1].split(", ") } build("clean") { originalCompilerCp = "compiler_cp=\\[(.*)]".toRegex().find(output)!!.groupValues[1].split(", ") }
buildGradle.appendText("""${'\n'} buildGradle.appendText("""${'\n'}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.gradle.tasks.findToolsJar
import java.io.File import java.io.File
internal class GradleCompilerEnvironment( internal class GradleCompilerEnvironment(
val compilerClasspath: List<File>, val compilerClasspath: Iterable<File>,
messageCollector: GradlePrintingMessageCollector, messageCollector: GradlePrintingMessageCollector,
outputItemsCollector: OutputItemsCollector, outputItemsCollector: OutputItemsCollector,
val outputFiles: FileCollection, val outputFiles: FileCollection,
@@ -37,7 +37,7 @@ import java.time.format.DateTimeFormatter
import java.util.zip.ZipFile import java.util.zip.ZipFile
import kotlin.concurrent.thread import kotlin.concurrent.thread
internal fun loadCompilerVersion(compilerClasspath: List<File>): String { internal fun loadCompilerVersion(compilerClasspath: Iterable<File>): String {
var result: String? = null var result: String? = null
fun checkVersion(bytes: ByteArray) { fun checkVersion(bytes: ByteArray) {
@@ -88,13 +88,13 @@ internal fun loadCompilerVersion(compilerClasspath: List<File>): String {
internal fun runToolInSeparateProcess( internal fun runToolInSeparateProcess(
argsArray: Array<String>, argsArray: Array<String>,
compilerClassName: String, compilerClassName: String,
classpath: List<File>, classpath: Iterable<File>,
logger: KotlinLogger, logger: KotlinLogger,
buildDir: File, buildDir: File,
jvmArgs: List<String> = emptyList() jvmArgs: List<String> = emptyList()
): ExitCode { ): ExitCode {
val javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java" val javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"
val classpathString = classpath.map { it.absolutePath }.joinToString(separator = File.pathSeparator) val classpathString = classpath.joinToString(separator = File.pathSeparator) { it.absolutePath }
val compilerOptions = writeArgumentsToFile(buildDir, argsArray) val compilerOptions = writeArgumentsToFile(buildDir, argsArray)
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.cacheOnlyIfEnabledForKotlin import org.jetbrains.kotlin.gradle.tasks.cacheOnlyIfEnabledForKotlin
import org.jetbrains.kotlin.gradle.tasks.clearLocalState import org.jetbrains.kotlin.gradle.tasks.clearLocalState
import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.gradle.utils.getValue
import org.jetbrains.kotlin.gradle.utils.isJavaFile
import java.io.File import java.io.File
import java.util.jar.JarFile import java.util.jar.JarFile
import javax.inject.Inject import javax.inject.Inject
@@ -61,9 +60,7 @@ abstract class KaptTask @Inject constructor(
@get:Classpath @get:Classpath
@get:InputFiles @get:InputFiles
val compilerClasspath: List<File> by project.provider { val compilerClasspath: FileCollection = objects.fileCollection().from({ kotlinCompileTask.computedCompilerClasspath })
kotlinCompileTask.computedCompilerClasspath
}
@get:Internal @get:Internal
internal abstract val kaptClasspathConfigurationNames: ListProperty<String> internal abstract val kaptClasspathConfigurationNames: ListProperty<String>
@@ -37,14 +37,17 @@ import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoProvider
import org.jetbrains.kotlin.gradle.internal.* import org.jetbrains.kotlin.gradle.internal.*
import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
import org.jetbrains.kotlin.gradle.logging.* import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
import org.jetbrains.kotlin.gradle.logging.kotlinWarn
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.COMPILER_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.report.ReportingSettings
import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib
import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.getValue
import org.jetbrains.kotlin.gradle.utils.isParentOf
import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.library.impl.isKotlinLibrary import org.jetbrains.kotlin.library.impl.isKotlinLibrary
import org.jetbrains.kotlin.utils.JsLibraryUtils import org.jetbrains.kotlin.utils.JsLibraryUtils
@@ -109,25 +112,29 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments>
@get:Classpath @get:Classpath
@get:InputFiles @get:InputFiles
internal val computedCompilerClasspath: List<File> by lazy { internal val computedCompilerClasspath: FileCollection = project.objects.fileCollection().from({
require(!defaultCompilerClasspath.isEmpty) {
"Default Kotlin compiler classpath is empty! Task: ${this::class.qualifiedName}"
}
when { when {
!compilerClasspath.isNullOrEmpty() -> compilerClasspath!! !compilerClasspath.isNullOrEmpty() -> compilerClasspath!!
compilerJarFile != null -> listOf(compilerJarFile!!) + compilerJarFile != null -> classpathWithCompilerJar
defaultCompilerClasspath
.filterNot {
it.nameWithoutExtension.startsWith("kotlin-compiler")
}
useFallbackCompilerSearch -> findKotlinCompilerClasspath(project) useFallbackCompilerSearch -> findKotlinCompilerClasspath(project)
else -> defaultCompilerClasspath.toList() else -> defaultCompilerClasspath
} }
} })
// a hack to remove compiler jar from the cp, will be dropped when compilerJarFile will be removed
private val classpathWithCompilerJar
get() = project.objects.fileCollection()
.from(compilerJarFile, defaultCompilerClasspath.filter { !it.nameWithoutExtension.startsWith("kotlin-compiler") })
protected abstract fun findKotlinCompilerClasspath(project: Project): List<File> protected abstract fun findKotlinCompilerClasspath(project: Project): List<File>
init {
doFirst {
require(!defaultCompilerClasspath.isEmpty) {
"Default Kotlin compiler classpath is empty! Task: ${path} (${this::class.qualifiedName})"
}
}
}
} }
public class GradleCompileTaskProvider { public class GradleCompileTaskProvider {