[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 warningMode: WarningMode = WarningMode.Fail,
val useFir: Boolean = false,
val customEnvironmentVariables: Map<String, String> = mapOf()
val customEnvironmentVariables: Map<String, String> = mapOf(),
val dryRun: Boolean = false,
)
enum class ConfigurationCacheProblems {
@@ -939,6 +940,10 @@ Finished executing task ':$taskName'|
add("-Pkotlin.useFir=true")
}
if (options.dryRun) {
add("--dry-run")
}
add("-Dorg.gradle.unsafe.configuration-cache=${options.configurationCache}")
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) {
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(", ") }
buildGradle.appendText("""${'\n'}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.gradle.tasks.findToolsJar
import java.io.File
internal class GradleCompilerEnvironment(
val compilerClasspath: List<File>,
val compilerClasspath: Iterable<File>,
messageCollector: GradlePrintingMessageCollector,
outputItemsCollector: OutputItemsCollector,
val outputFiles: FileCollection,
@@ -37,7 +37,7 @@ import java.time.format.DateTimeFormatter
import java.util.zip.ZipFile
import kotlin.concurrent.thread
internal fun loadCompilerVersion(compilerClasspath: List<File>): String {
internal fun loadCompilerVersion(compilerClasspath: Iterable<File>): String {
var result: String? = null
fun checkVersion(bytes: ByteArray) {
@@ -88,13 +88,13 @@ internal fun loadCompilerVersion(compilerClasspath: List<File>): String {
internal fun runToolInSeparateProcess(
argsArray: Array<String>,
compilerClassName: String,
classpath: List<File>,
classpath: Iterable<File>,
logger: KotlinLogger,
buildDir: File,
jvmArgs: List<String> = emptyList()
): ExitCode {
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)
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.cacheOnlyIfEnabledForKotlin
import org.jetbrains.kotlin.gradle.tasks.clearLocalState
import org.jetbrains.kotlin.gradle.utils.getValue
import org.jetbrains.kotlin.gradle.utils.isJavaFile
import java.io.File
import java.util.jar.JarFile
import javax.inject.Inject
@@ -61,9 +60,7 @@ abstract class KaptTask @Inject constructor(
@get:Classpath
@get:InputFiles
val compilerClasspath: List<File> by project.provider {
kotlinCompileTask.computedCompilerClasspath
}
val compilerClasspath: FileCollection = objects.fileCollection().from({ kotlinCompileTask.computedCompilerClasspath })
@get:Internal
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.tasks.TaskWithLocalState
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.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.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.library.impl.isKotlinLibrary
import org.jetbrains.kotlin.utils.JsLibraryUtils
@@ -109,25 +112,29 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments>
@get:Classpath
@get:InputFiles
internal val computedCompilerClasspath: List<File> by lazy {
require(!defaultCompilerClasspath.isEmpty) {
"Default Kotlin compiler classpath is empty! Task: ${this::class.qualifiedName}"
}
internal val computedCompilerClasspath: FileCollection = project.objects.fileCollection().from({
when {
!compilerClasspath.isNullOrEmpty() -> compilerClasspath!!
compilerJarFile != null -> listOf(compilerJarFile!!) +
defaultCompilerClasspath
.filterNot {
it.nameWithoutExtension.startsWith("kotlin-compiler")
}
compilerJarFile != null -> classpathWithCompilerJar
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>
init {
doFirst {
require(!defaultCompilerClasspath.isEmpty) {
"Default Kotlin compiler classpath is empty! Task: ${path} (${this::class.qualifiedName})"
}
}
}
}
public class GradleCompileTaskProvider {