Demote fatal error to warning on unresolved libraries mentioned in Klib's manifest 'depends' for metadata compilation
^KT-46107
This commit is contained in:
committed by
Space
parent
95a1a4e66a
commit
22ea5c7de4
+8
-7
@@ -25,11 +25,12 @@ import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
|
|||||||
import org.jetbrains.kotlin.library.resolver.LibraryOrder
|
import org.jetbrains.kotlin.library.resolver.LibraryOrder
|
||||||
import org.jetbrains.kotlin.util.WithLogger
|
import org.jetbrains.kotlin.util.WithLogger
|
||||||
|
|
||||||
fun <L: KotlinLibrary> SearchPathResolver<L>.libraryResolver()
|
fun <L: KotlinLibrary> SearchPathResolver<L>.libraryResolver(resolveManifestDependenciesLenient: Boolean = false)
|
||||||
= KotlinLibraryResolverImpl<L>(this)
|
= KotlinLibraryResolverImpl<L>(this, resolveManifestDependenciesLenient)
|
||||||
|
|
||||||
class KotlinLibraryResolverImpl<L: KotlinLibrary>(
|
class KotlinLibraryResolverImpl<L: KotlinLibrary> internal constructor(
|
||||||
override val searchPathResolver: SearchPathResolver<L>
|
override val searchPathResolver: SearchPathResolver<L>,
|
||||||
|
val resolveManifestDependenciesLenient: Boolean
|
||||||
): KotlinLibraryResolver<L>, WithLogger by searchPathResolver {
|
): KotlinLibraryResolver<L>, WithLogger by searchPathResolver {
|
||||||
|
|
||||||
override fun resolveWithDependencies(
|
override fun resolveWithDependencies(
|
||||||
@@ -56,7 +57,7 @@ class KotlinLibraryResolverImpl<L: KotlinLibrary>(
|
|||||||
): List<KotlinLibrary> {
|
): List<KotlinLibrary> {
|
||||||
|
|
||||||
val userProvidedLibraries = unresolvedLibraries.asSequence()
|
val userProvidedLibraries = unresolvedLibraries.asSequence()
|
||||||
.map { searchPathResolver.resolve(it) }
|
.mapNotNull { searchPathResolver.resolve(it) }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val defaultLibraries = searchPathResolver.defaultLinks(noStdLib, noDefaultLibs, noEndorsedLibs)
|
val defaultLibraries = searchPathResolver.defaultLinks(noStdLib, noDefaultLibs, noEndorsedLibs)
|
||||||
@@ -115,10 +116,10 @@ class KotlinLibraryResolverImpl<L: KotlinLibrary>(
|
|||||||
var newDependencies = rootLibraries
|
var newDependencies = rootLibraries
|
||||||
do {
|
do {
|
||||||
newDependencies = newDependencies.map { library: KotlinResolvedLibraryImpl ->
|
newDependencies = newDependencies.map { library: KotlinResolvedLibraryImpl ->
|
||||||
library.library.unresolvedDependencies.asSequence()
|
library.library.unresolvedDependencies(resolveManifestDependenciesLenient).asSequence()
|
||||||
|
|
||||||
.filterNot { searchPathResolver.isProvidedByDefault(it) }
|
.filterNot { searchPathResolver.isProvidedByDefault(it) }
|
||||||
.map { KotlinResolvedLibraryImpl(searchPathResolver.resolve(it)) }
|
.mapNotNull { KotlinResolvedLibraryImpl(searchPathResolver.resolve(it) ?: return@mapNotNull null) }
|
||||||
.map { resolved ->
|
.map { resolved ->
|
||||||
val absoluteFile = resolved.library.libraryFile.absoluteFile
|
val absoluteFile = resolved.library.libraryFile.absoluteFile
|
||||||
if (absoluteFile in cache) {
|
if (absoluteFile in cache) {
|
||||||
|
|||||||
@@ -74,9 +74,12 @@ val BaseKotlinLibrary.uniqueName: String
|
|||||||
val BaseKotlinLibrary.shortName: String?
|
val BaseKotlinLibrary.shortName: String?
|
||||||
get() = manifestProperties.getProperty(KLIB_PROPERTY_SHORT_NAME)
|
get() = manifestProperties.getProperty(KLIB_PROPERTY_SHORT_NAME)
|
||||||
|
|
||||||
val BaseKotlinLibrary.unresolvedDependencies: List<UnresolvedLibrary>
|
val BaseKotlinLibrary.unresolvedDependencies: List<RequiredUnresolvedLibrary>
|
||||||
get() = manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true)
|
get() = unresolvedDependencies(lenient = false).map { it as RequiredUnresolvedLibrary }
|
||||||
.map { UnresolvedLibrary(it, manifestProperties.getProperty("dependency_version_$it")) }
|
|
||||||
|
fun BaseKotlinLibrary.unresolvedDependencies(lenient: Boolean = false): List<UnresolvedLibrary> =
|
||||||
|
manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS, escapeInQuotes = true)
|
||||||
|
.map { UnresolvedLibrary(it, manifestProperties.getProperty("dependency_version_$it"), lenient = lenient) }
|
||||||
|
|
||||||
interface KotlinLibrary : BaseKotlinLibrary, MetadataLibrary, IrLibrary
|
interface KotlinLibrary : BaseKotlinLibrary, MetadataLibrary, IrLibrary
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,19 @@ const val KOTLIN_STDLIB_NAME = "stdlib"
|
|||||||
interface SearchPathResolver<L : KotlinLibrary> : WithLogger {
|
interface SearchPathResolver<L : KotlinLibrary> : WithLogger {
|
||||||
val searchRoots: List<File>
|
val searchRoots: List<File>
|
||||||
fun resolutionSequence(givenPath: String): Sequence<File>
|
fun resolutionSequence(givenPath: String): Sequence<File>
|
||||||
fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean = false): L
|
fun resolve(unresolved: LenientUnresolvedLibrary, isDefaultLink: Boolean = false): L?
|
||||||
|
fun resolve(unresolved: RequiredUnresolvedLibrary, isDefaultLink: Boolean = false): L
|
||||||
fun resolve(givenPath: String): L
|
fun resolve(givenPath: String): L
|
||||||
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean, noEndorsedLibs: Boolean): List<L>
|
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean, noEndorsedLibs: Boolean): List<L>
|
||||||
fun libraryMatch(candidate: L, unresolved: UnresolvedLibrary): Boolean
|
fun libraryMatch(candidate: L, unresolved: UnresolvedLibrary): Boolean
|
||||||
fun isProvidedByDefault(unresolved: UnresolvedLibrary): Boolean = false
|
fun isProvidedByDefault(unresolved: UnresolvedLibrary): Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <L : KotlinLibrary> SearchPathResolver<L>.resolve(unresolved: UnresolvedLibrary): L? = when (unresolved) {
|
||||||
|
is LenientUnresolvedLibrary -> resolve(unresolved)
|
||||||
|
is RequiredUnresolvedLibrary -> resolve(unresolved)
|
||||||
|
}
|
||||||
|
|
||||||
// This is a simple library resolver that only cares for file names.
|
// This is a simple library resolver that only cares for file names.
|
||||||
abstract class KotlinLibrarySearchPathResolver<L : KotlinLibrary>(
|
abstract class KotlinLibrarySearchPathResolver<L : KotlinLibrary>(
|
||||||
repositories: List<String>,
|
repositories: List<String>,
|
||||||
@@ -134,29 +140,42 @@ abstract class KotlinLibrarySearchPathResolver<L : KotlinLibrary>(
|
|||||||
|
|
||||||
// Default libraries could be resolved several times during findLibraries and resolveDependencies.
|
// Default libraries could be resolved several times during findLibraries and resolveDependencies.
|
||||||
// Store already resolved libraries.
|
// Store already resolved libraries.
|
||||||
private val resolvedLibraries = HashMap<UnresolvedLibrary, L>()
|
private inner class ResolvedLibrary(val library: L?)
|
||||||
|
|
||||||
override fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean): L {
|
private val resolvedLibraries = HashMap<UnresolvedLibrary, ResolvedLibrary>()
|
||||||
|
|
||||||
|
private fun resolveOrNull(unresolved: UnresolvedLibrary, isDefaultLink: Boolean): L? {
|
||||||
return resolvedLibraries.getOrPut(unresolved) {
|
return resolvedLibraries.getOrPut(unresolved) {
|
||||||
val givenPath = unresolved.path
|
val givenPath = unresolved.path
|
||||||
try {
|
try {
|
||||||
val fileSequence = resolutionSequence(givenPath)
|
resolutionSequence(givenPath)
|
||||||
val matching = fileSequence
|
.filterOutPre_1_4_libraries()
|
||||||
.filterOutPre_1_4_libraries()
|
.flatMap { libraryComponentBuilder(it, isDefaultLink).asSequence() }
|
||||||
.flatMap { libraryComponentBuilder(it, isDefaultLink).asSequence() }
|
.map { it.takeIf { libraryMatch(it, unresolved) } }
|
||||||
.map { it.takeIf { libraryMatch(it, unresolved) } }
|
.filterNotNull()
|
||||||
.filterNotNull()
|
.firstOrNull()
|
||||||
|
.let(::ResolvedLibrary)
|
||||||
matching.firstOrNull() ?: run {
|
|
||||||
logger.fatal("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}")
|
|
||||||
}
|
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
logger.error("Failed to resolve Kotlin library: $givenPath")
|
logger.error("Failed to resolve Kotlin library: $givenPath")
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
}.library
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolve(unresolved: LenientUnresolvedLibrary, isDefaultLink: Boolean): L? {
|
||||||
|
return resolveOrNull(unresolved, isDefaultLink).also { resolvedLibrary ->
|
||||||
|
if (resolvedLibrary == null) {
|
||||||
|
logger.warning("Could not find \"${unresolved.path}\" in ${searchRoots.map { it.absolutePath }}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun resolve(unresolved: RequiredUnresolvedLibrary, isDefaultLink: Boolean): L {
|
||||||
|
return resolveOrNull(unresolved, isDefaultLink)
|
||||||
|
?: logger.fatal("Could not find \"${unresolved.path}\" in ${searchRoots.map { it.absolutePath }}")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override fun libraryMatch(candidate: L, unresolved: UnresolvedLibrary): Boolean = true
|
override fun libraryMatch(candidate: L, unresolved: UnresolvedLibrary): Boolean = true
|
||||||
|
|
||||||
override fun resolve(givenPath: String) = resolve(UnresolvedLibrary(givenPath, null), false)
|
override fun resolve(givenPath: String) = resolve(UnresolvedLibrary(givenPath, null), false)
|
||||||
|
|||||||
@@ -1,10 +1,33 @@
|
|||||||
|
@file:Suppress("FunctionName")
|
||||||
|
|
||||||
package org.jetbrains.kotlin.library
|
package org.jetbrains.kotlin.library
|
||||||
|
|
||||||
data class UnresolvedLibrary(
|
fun UnresolvedLibrary(path: String, libraryVersion: String?): RequiredUnresolvedLibrary =
|
||||||
val path: String,
|
RequiredUnresolvedLibrary(path, libraryVersion)
|
||||||
val libraryVersion: String?) {
|
|
||||||
|
|
||||||
fun substitutePath(newPath: String): UnresolvedLibrary {
|
fun UnresolvedLibrary(path: String, libraryVersion: String?, lenient: Boolean): UnresolvedLibrary =
|
||||||
return UnresolvedLibrary(newPath, libraryVersion)
|
if (lenient) LenientUnresolvedLibrary(path, libraryVersion) else RequiredUnresolvedLibrary(path, libraryVersion)
|
||||||
|
|
||||||
|
sealed class UnresolvedLibrary {
|
||||||
|
abstract val path: String
|
||||||
|
abstract val libraryVersion: String?
|
||||||
|
abstract fun substitutePath(newPath: String): UnresolvedLibrary
|
||||||
|
}
|
||||||
|
|
||||||
|
data class RequiredUnresolvedLibrary(
|
||||||
|
override val path: String,
|
||||||
|
override val libraryVersion: String?
|
||||||
|
) : UnresolvedLibrary() {
|
||||||
|
override fun substitutePath(newPath: String): RequiredUnresolvedLibrary {
|
||||||
|
return copy(path = newPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class LenientUnresolvedLibrary(
|
||||||
|
override val path: String,
|
||||||
|
override val libraryVersion: String?
|
||||||
|
) : UnresolvedLibrary() {
|
||||||
|
override fun substitutePath(newPath: String): LenientUnresolvedLibrary {
|
||||||
|
return copy(path = newPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+5
-3
@@ -81,7 +81,9 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
internal val purgeUserLibs: Boolean
|
internal val purgeUserLibs: Boolean
|
||||||
get() = configuration.getBoolean(KonanConfigKeys.PURGE_USER_LIBS)
|
get() = configuration.getBoolean(KonanConfigKeys.PURGE_USER_LIBS)
|
||||||
|
|
||||||
internal val resolve = KonanLibrariesResolveSupport(configuration, target, distribution)
|
internal val resolve = KonanLibrariesResolveSupport(
|
||||||
|
configuration, target, distribution, resolveManifestDependenciesLenient = metadataKlib
|
||||||
|
)
|
||||||
|
|
||||||
internal val resolvedLibraries get() = resolve.resolvedLibraries
|
internal val resolvedLibraries get() = resolve.resolvedLibraries
|
||||||
|
|
||||||
@@ -186,7 +188,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
internal val nativeLibraries: List<String> =
|
internal val nativeLibraries: List<String> =
|
||||||
configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES)
|
configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES)
|
||||||
|
|
||||||
internal val includeBinaries: List<String> =
|
internal val includeBinaries: List<String> =
|
||||||
configuration.getList(KonanConfigKeys.INCLUDED_BINARY_FILES)
|
configuration.getList(KonanConfigKeys.INCLUDED_BINARY_FILES)
|
||||||
|
|
||||||
internal val languageVersionSettings =
|
internal val languageVersionSettings =
|
||||||
@@ -202,5 +204,5 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
internal val isInteropStubs: Boolean get() = manifestProperties?.getProperty("interop") == "true"
|
internal val isInteropStubs: Boolean get() = manifestProperties?.getProperty("interop") == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
|
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
|
||||||
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
= this.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(priority, message)
|
||||||
|
|||||||
+4
-5
@@ -8,10 +8,8 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.konan.CompilerVersion
|
|
||||||
import org.jetbrains.kotlin.konan.file.File
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
import org.jetbrains.kotlin.konan.library.defaultResolver
|
import org.jetbrains.kotlin.konan.library.defaultResolver
|
||||||
import org.jetbrains.kotlin.konan.parseCompilerVersion
|
|
||||||
import org.jetbrains.kotlin.konan.target.Distribution
|
import org.jetbrains.kotlin.konan.target.Distribution
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.library.UnresolvedLibrary
|
import org.jetbrains.kotlin.library.UnresolvedLibrary
|
||||||
@@ -22,7 +20,8 @@ import org.jetbrains.kotlin.util.Logger
|
|||||||
class KonanLibrariesResolveSupport(
|
class KonanLibrariesResolveSupport(
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
target: KonanTarget,
|
target: KonanTarget,
|
||||||
distribution: Distribution
|
distribution: Distribution,
|
||||||
|
resolveManifestDependenciesLenient: Boolean
|
||||||
) {
|
) {
|
||||||
private val includedLibraryFiles =
|
private val includedLibraryFiles =
|
||||||
configuration.getList(KonanConfigKeys.INCLUDED_LIBRARIES).map { File(it) }
|
configuration.getList(KonanConfigKeys.INCLUDED_LIBRARIES).map { File(it) }
|
||||||
@@ -56,7 +55,7 @@ class KonanLibrariesResolveSupport(
|
|||||||
target,
|
target,
|
||||||
distribution,
|
distribution,
|
||||||
resolverLogger
|
resolverLogger
|
||||||
).libraryResolver()
|
).libraryResolver(resolveManifestDependenciesLenient)
|
||||||
|
|
||||||
// We pass included libraries by absolute paths to avoid repository-based resolution for them.
|
// We pass included libraries by absolute paths to avoid repository-based resolution for them.
|
||||||
// Strictly speaking such "direct" libraries should be specially handled by the resolver, not by KonanConfig.
|
// Strictly speaking such "direct" libraries should be specially handled by the resolver, not by KonanConfig.
|
||||||
@@ -80,4 +79,4 @@ class KonanLibrariesResolveSupport(
|
|||||||
|
|
||||||
internal val includedLibraries =
|
internal val includedLibraries =
|
||||||
getIncludedLibraries(includedLibraryFiles, configuration, resolvedLibraries)
|
getIncludedLibraries(includedLibraryFiles, configuration, resolvedLibraries)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user