diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt index 26c492e71ff..109806b24f6 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt @@ -194,12 +194,6 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xuse-type-table", description = "Use type table in metadata serialization") var useTypeTable: Boolean by FreezableVar(false) - @Argument( - value = "-Xskip-runtime-version-check", - description = "Allow Kotlin runtime libraries of incompatible versions in the classpath" - ) - var skipRuntimeVersionCheck: Boolean by FreezableVar(false) - @Argument( value = "-Xuse-old-class-files-reading", description = "Use old class files reading implementation. This may slow down the build and cause problems with Groovy interop.\n" + diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/JvmRuntimeVersionsConsistencyChecker.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/JvmRuntimeVersionsConsistencyChecker.kt deleted file mode 100644 index 01977a80dd7..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/JvmRuntimeVersionsConsistencyChecker.kt +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.cli.jvm - -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.vfs.VfsUtilCore -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.config.* -import java.io.IOException -import java.util.* -import java.util.jar.Attributes -import java.util.jar.Manifest - -object JvmRuntimeVersionsConsistencyChecker { - private val LOG = Logger.getInstance(JvmRuntimeVersionsConsistencyChecker::class.java) - - private fun T?.assertNotNull(lazyMessage: () -> String): T = - this ?: lazyMessage().let { message -> - LOG.error(message) - throw AssertionError(message) - } - - private const val META_INF = "META-INF" - private const val MANIFEST_MF = "$META_INF/MANIFEST.MF" - - private const val MANIFEST_KOTLIN_VERSION_ATTRIBUTE = "manifest.impl.attribute.kotlin.version" - private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT = "manifest.impl.attribute.kotlin.runtime.component" - private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE = "manifest.impl.value.kotlin.runtime.component.core" - private const val MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN = "manifest.impl.value.kotlin.runtime.component.main" - - private const val KOTLIN_STDLIB_MODULE = "$META_INF/kotlin-stdlib.kotlin_module" - private const val KOTLIN_STDLIB_JRE_7_MODULE = "$META_INF/kotlin-stdlib-jre7.kotlin_module" - private const val KOTLIN_STDLIB_JRE_8_MODULE = "$META_INF/kotlin-stdlib-jre8.kotlin_module" - private const val KOTLIN_REFLECT_MODULE = "$META_INF/kotlin-reflection.kotlin_module" - - private val RUNTIME_IMPLEMENTATION_TITLES = setOf( - "kotlin-runtime", "kotlin-stdlib", "kotlin-reflect", "Kotlin Runtime", "Kotlin Standard Library", "Kotlin Reflect" - ) - - private val KOTLIN_VERSION_ATTRIBUTE: String - private val KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE: String - private val KOTLIN_RUNTIME_COMPONENT_CORE: String - private val KOTLIN_RUNTIME_COMPONENT_MAIN: String - - init { - val manifestProperties: Properties = try { - JvmRuntimeVersionsConsistencyChecker::class.java - .getResourceAsStream("/kotlinManifest.properties") - .let { input -> Properties().apply { load(input) } } - } catch (e: Exception) { - LOG.error(e) - throw e - } - - KOTLIN_VERSION_ATTRIBUTE = manifestProperties.getProperty(MANIFEST_KOTLIN_VERSION_ATTRIBUTE) - .assertNotNull { "$MANIFEST_KOTLIN_VERSION_ATTRIBUTE not found in kotlinManifest.properties" } - KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT) - .assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT not found in kotlinManifest.properties" } - KOTLIN_RUNTIME_COMPONENT_CORE = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE) - .assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT_CORE not found in kotlinManifest.properties" } - KOTLIN_RUNTIME_COMPONENT_MAIN = manifestProperties.getProperty(MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN) - .assertNotNull { "$MANIFEST_KOTLIN_RUNTIME_COMPONENT_MAIN not found in kotlinManifest.properties" } - } - - private class KotlinLibraryFile(val file: VirtualFile, val version: MavenComparableVersion) { - override fun toString(): String = - "${file.name}:$version" - } - - private class RuntimeJarsInfo( - // Runtime jars with components "Main" and "Core" - val jars: List, - // Runtime jars with components "Core" only (a subset of [jars]) - val coreJars: List, - // Library jars which have some Kotlin Runtime library bundled into them - val otherLibrariesWithBundledRuntime: List, - val stdlibJre7: List, - val stdlibJre8: List - ) - - fun checkCompilerClasspathConsistency( - messageCollector: MessageCollector, - configuration: CompilerConfiguration, - classpathJarRoots: List - ) { - val runtimeJarsInfo = collectRuntimeJarsInfo(classpathJarRoots) - if (runtimeJarsInfo.jars.isEmpty()) return - - val languageVersionSettings = configuration.languageVersionSettings - val currentApi = languageVersionSettings.apiVersion - - val consistency = checkCompilerClasspathConsistency(messageCollector, currentApi.version, runtimeJarsInfo) - if (consistency is ClasspathConsistency.InconsistentWithApiVersion) { - val actualRuntimeVersion = consistency.actualRuntimeVersion - if (currentApi.isStable) { - messageCollector.issue( - null, - "Runtime JAR files in the classpath have the version $actualRuntimeVersion, " + - "which is older than the API version ${currentApi.version}. " + - "Consider using the runtime of version ${currentApi.version}, or pass '-api-version $actualRuntimeVersion' " + - "explicitly to restrict the available APIs to the runtime of version $actualRuntimeVersion. " + - "You can also pass '-language-version $actualRuntimeVersion' instead, which will restrict " + - "not only the APIs to the specified version, but also the language features" - ) - - for (jar in consistency.incompatibleJars) { - messageCollector.issue( - jar.file, - "Runtime JAR file has version ${jar.version} which is older than required for API version ${currentApi.version}" - ) - } - } - - val actualApi = ApiVersion.parse(actualRuntimeVersion.toString()) - if (actualApi == null) { - messageCollector.issue(null, "Could not parse runtime JAR version: $actualRuntimeVersion") - } else if (!languageVersionSettings.getFlag(AnalysisFlags.explicitApiVersion) && actualApi < currentApi) { - // If there's no explicit "-api-version" AND there's an old stdlib in the classpath (older than the default value of API), - // we infer API = the version of that stdlib. - // Note that "no explicit -api-version" requirement is necessary because for example, in - // "kotlinc-1.2 -language-version 1.0 -cp kotlin-runtime-1.1.jar" we should still infer API = 1.0 - configuration.languageVersionSettings = object : LanguageVersionSettings by languageVersionSettings { - override val apiVersion: ApiVersion get() = actualApi - } - - messageCollector.issue( - null, "Old runtime has been found in the classpath. " + - "Initial language version settings: $languageVersionSettings. " + - "Updated API version: $actualApi", CompilerMessageSeverity.LOGGING - ) - } - } else if (consistency != ClasspathConsistency.Consistent) { - messageCollector.issue( - null, - "Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath" - ) - } - - if (configuration.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_2) { - for (stdlibJre7 in runtimeJarsInfo.stdlibJre7) { - messageCollector.issue(stdlibJre7.file, "kotlin-stdlib-jre7 is deprecated. Please use kotlin-stdlib-jdk7 instead") - } - for (stdlibJre8 in runtimeJarsInfo.stdlibJre8) { - messageCollector.issue(stdlibJre8.file, "kotlin-stdlib-jre8 is deprecated. Please use kotlin-stdlib-jdk8 instead") - } - } - - val librariesWithBundled = runtimeJarsInfo.otherLibrariesWithBundledRuntime - if (librariesWithBundled.isNotEmpty()) { - messageCollector.issue( - null, - "Some JAR files in the classpath have the Kotlin Runtime library bundled into them. " + - "This may cause difficult to debug problems if there's a different version of the Kotlin Runtime library in the classpath. " + - "Consider removing these libraries from the classpath" - ) - - for (library in librariesWithBundled) { - messageCollector.issue(library, "Library has Kotlin runtime bundled into it") - } - } - } - - private sealed class ClasspathConsistency { - object Consistent : ClasspathConsistency() - class InconsistentWithApiVersion( - val actualRuntimeVersion: MavenComparableVersion, - val incompatibleJars: List - ) : ClasspathConsistency() - - object InconsistentWithCompilerVersion : ClasspathConsistency() - object InconsistentBecauseOfRuntimesWithDifferentVersions : ClasspathConsistency() - } - - private fun checkCompilerClasspathConsistency( - messageCollector: MessageCollector, - apiVersion: MavenComparableVersion, - runtimeJarsInfo: RuntimeJarsInfo - ): ClasspathConsistency { - // The "Core" jar files should not be newer than the compiler. This behavior is reserved for the future if we realise that we're - // going to break language/library compatibility in such a way that it's easier to make the old compiler just report an error - // in the case the new runtime library is specified in the classpath, rather than employing any other compatibility breakage tools - // we have at our disposal (Deprecated, SinceKotlin, VersionRequirement in metadata, etc.) - if (runtimeJarsInfo.coreJars.map { - checkNotNewerThanCompiler(messageCollector, it) - }.any { it }) return ClasspathConsistency.InconsistentWithCompilerVersion - - val jars = runtimeJarsInfo.jars - if (jars.isEmpty()) return ClasspathConsistency.Consistent - - val runtimeVersion = checkMatchingVersionsAndGetRuntimeVersion(messageCollector, jars) - ?: return ClasspathConsistency.InconsistentBecauseOfRuntimesWithDifferentVersions - - val jarsIncompatibleWithApiVersion = jars.filter { it.version < apiVersion } - if (jarsIncompatibleWithApiVersion.isNotEmpty()) { - return ClasspathConsistency.InconsistentWithApiVersion(runtimeVersion, jarsIncompatibleWithApiVersion) - } - - return ClasspathConsistency.Consistent - } - - private fun checkNotNewerThanCompiler(messageCollector: MessageCollector, jar: KotlinLibraryFile): Boolean { - if (jar.version > ApiVersion.LATEST_STABLE.version) { - messageCollector.issue( - jar.file, - "Runtime JAR file has version ${jar.version} which is newer than compiler version ${ApiVersion.LATEST_STABLE.version}", - CompilerMessageSeverity.ERROR - ) - return true - } - return false - } - - // Returns the version if it's the same across all jars, or null if versions of some jars differ. - private fun checkMatchingVersionsAndGetRuntimeVersion( - messageCollector: MessageCollector, - jars: List - ): MavenComparableVersion? { - assert(jars.isNotEmpty()) { "'jars' must not be empty" } - val oldestVersion = jars.minOf { it.version } - val newestVersion = jars.maxOf { it.version } - - // If the oldest version is the same as the newest version, then all jars have the same version - if (oldestVersion == newestVersion) return oldestVersion - - messageCollector.issue(null, buildString { - append("Runtime JAR files in the classpath should have the same version. These files were found in the classpath:\n") - for (jar in jars) { - append(" ${jar.file.path} (version ${jar.version})\n") - } - }.trimEnd()) - - // If there's kotlin-stdlib of version X in the classpath and kotlin-reflect of version Y < X, - // we suggest to provide an explicit dependency on version X. - // TODO: report this depending on the content of the jars instead - val minReflectJar = - jars.filter { it.file.name.startsWith("kotlin-reflect") }.minByOrNull { it.version } - val maxStdlibJar = - jars.filter { it.file.name.startsWith("kotlin-runtime") || it.file.name.startsWith("kotlin-stdlib") }.maxByOrNull { it.version } - if (minReflectJar != null && maxStdlibJar != null && minReflectJar.version < maxStdlibJar.version) { - messageCollector.issue( - null, - "Consider providing an explicit dependency on kotlin-reflect ${maxStdlibJar.version} to prevent strange errors" - ) - } - - return null - } - - private fun MessageCollector.issue( - file: VirtualFile?, - message: String, - severity: CompilerMessageSeverity = CompilerMessageSeverity.STRONG_WARNING - ) { - report(severity, message, CompilerMessageLocation.create(file?.let(VfsUtilCore::virtualToIoFile)?.path)) - } - - private fun collectRuntimeJarsInfo(classpathJarRoots: List): RuntimeJarsInfo { - val jars = ArrayList(2) - val coreJars = ArrayList(2) - val otherLibrariesWithBundledRuntime = ArrayList(0) - val stdlibJre7 = ArrayList(0) - val stdlibJre8 = ArrayList(0) - - val visitedPaths = hashSetOf() - - for (jarRoot in classpathJarRoots) { - val fileKind = determineFileKind(jarRoot) - if (fileKind is FileKind.Irrelevant) continue - - val jarFile = VfsUtilCore.getVirtualFileForJar(jarRoot) ?: continue - if (!visitedPaths.add(jarFile.path)) continue - - when (fileKind) { - is FileKind.Runtime -> { - val file = KotlinLibraryFile(jarFile, fileKind.version) - jars.add(file) - if (fileKind.isCoreComponent) { - coreJars.add(file) - } - if (fileKind.isStdlibJre7) { - stdlibJre7.add(file) - } - if (fileKind.isStdlibJre8) { - stdlibJre8.add(file) - } - } - FileKind.OldRuntime -> jars.add(KotlinLibraryFile(jarFile, ApiVersion.KOTLIN_1_0.version)) - FileKind.LibraryWithBundledRuntime -> otherLibrariesWithBundledRuntime.add(jarFile) - FileKind.Irrelevant -> {} - } - } - - return RuntimeJarsInfo(jars, coreJars, otherLibrariesWithBundledRuntime, stdlibJre7, stdlibJre8) - } - - private sealed class FileKind { - class Runtime( - val version: MavenComparableVersion, - val isStdlibJre7: Boolean, - val isStdlibJre8: Boolean, - val isCoreComponent: Boolean - ) : FileKind() - - // Runtime library of Kotlin 1.0 - object OldRuntime : FileKind() - - object LibraryWithBundledRuntime : FileKind() - - object Irrelevant : FileKind() - } - - private fun determineFileKind(jarRoot: VirtualFile): FileKind { - val manifestFile = jarRoot.findFileByRelativePath(MANIFEST_MF) - val manifest = try { - manifestFile?.let { Manifest(it.inputStream) } - } catch (e: IOException) { - return FileKind.Irrelevant - } - - val runtimeComponent = manifest?.mainAttributes?.getValue(KOTLIN_RUNTIME_COMPONENT_ATTRIBUTE) - val isStdlibJre7 = jarRoot.findFileByRelativePath(KOTLIN_STDLIB_JRE_7_MODULE) != null - val isStdlibJre8 = jarRoot.findFileByRelativePath(KOTLIN_STDLIB_JRE_8_MODULE) != null - return when (runtimeComponent) { - KOTLIN_RUNTIME_COMPONENT_MAIN -> - FileKind.Runtime(manifest.getKotlinLanguageVersion(), isStdlibJre7, isStdlibJre8, isCoreComponent = false) - KOTLIN_RUNTIME_COMPONENT_CORE -> - FileKind.Runtime(manifest.getKotlinLanguageVersion(), isStdlibJre7, isStdlibJre8, isCoreComponent = true) - null -> when { - jarRoot.findFileByRelativePath(KOTLIN_STDLIB_MODULE) == null && - jarRoot.findFileByRelativePath(KOTLIN_REFLECT_MODULE) == null -> FileKind.Irrelevant - isGenuineKotlinRuntime(manifest) -> FileKind.OldRuntime - else -> FileKind.LibraryWithBundledRuntime - } - else -> FileKind.Irrelevant - } - } - - // Returns true if the manifest is from the original Kotlin Runtime jar, false if it's from a library with a bundled runtime - private fun isGenuineKotlinRuntime(manifest: Manifest?): Boolean { - return manifest != null && - manifest.mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE) in RUNTIME_IMPLEMENTATION_TITLES - } - - private fun Manifest.getKotlinLanguageVersion(): MavenComparableVersion = - (mainAttributes.getValue(KOTLIN_VERSION_ATTRIBUTE)?.let(ApiVersion.Companion::parse) ?: ApiVersion.KOTLIN_1_0).version -} diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 09b3d429051..0954b77f9ca 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -67,7 +67,6 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.toBooleanLenient -import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.index.* @@ -267,17 +266,6 @@ class KotlinCoreEnvironment private constructor( classpathRootsResolver.convertClasspathRoots(configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) this.initialRoots.addAll(initialRoots) - if (!configuration.getBoolean(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK) && messageCollector != null) { - /* - // Temporarily disable until compiler is bootstrapped to 1.6. - JvmRuntimeVersionsConsistencyChecker.checkCompilerClasspathConsistency( - messageCollector, - configuration, - initialRoots.mapNotNull { (file, type) -> if (type == JavaRoot.RootType.BINARY) file else null } - ) - */ - } - val (roots, singleJavaFileRoots) = initialRoots.partition { (file) -> file.isDirectory || file.extension != JavaFileType.DEFAULT_EXTENSION } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt index a1309b96348..b61405ea3bb 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -271,7 +271,6 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.ASSERTIONS_MODE, assertionsMode ?: JVMAssertionsMode.DEFAULT) put(JVMConfigurationKeys.USE_TYPE_TABLE, arguments.useTypeTable) - put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck) put(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING, arguments.useOldClassFilesReading) put(JVMConfigurationKeys.USE_FAST_JAR_FILE_SYSTEM, arguments.useFastJarFileSystem) diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java index 8289873ff0d..8c7d82e1528 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -61,9 +61,6 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey USE_SINGLE_MODULE = CompilerConfigurationKey.create("combine modules for source files and binary dependencies into a single module"); - public static final CompilerConfigurationKey SKIP_RUNTIME_VERSION_CHECK = - CompilerConfigurationKey.create("do not perform checks on runtime versions consistency"); - public static final CompilerConfigurationKey JVM_TARGET = CompilerConfigurationKey.create("JVM bytecode target version"); diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index a679eaaa202..74941cbc54b 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -119,7 +119,6 @@ where advanced options include: -Xserialize-ir={none|inline|all} Save IR to metadata (EXPERIMENTAL) -Xsingle-module Combine modules for source files and binary dependencies into a single module - -Xskip-runtime-version-check Allow Kotlin runtime libraries of incompatible versions in the classpath -Xgenerate-strict-metadata-version Generate metadata with strict version semantics (see kdoc on Metadata.extraInt) -Xstring-concat={indy-with-constants|indy|inline}