Introduce 2 KLIB resolve strategies: "compiler" & "tooling"
Issue #KT-36213
This commit is contained in:
@@ -238,14 +238,18 @@ class SingleKlibComponentResolver(
|
|||||||
override fun libraryComponentBuilder(file: File, isDefault: Boolean) = createKotlinLibraryComponents(file, isDefault)
|
override fun libraryComponentBuilder(file: File, isDefault: Boolean) = createKotlinLibraryComponents(file, isDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolveSingleFileKlib(
|
/**
|
||||||
libraryFile: File,
|
* Resolves KLIB libraries by:
|
||||||
logger: Logger = object : Logger {
|
* - expanding the given library path to the real path that may or may not contain ".klib" extension
|
||||||
override fun log(message: String) {}
|
* - searching among user-supplied libraries by "unique_name" that matches the given library name
|
||||||
override fun error(message: String) = kotlin.error("e: $message")
|
* - filtering out pre-1.4 libraries (with the old style layout)
|
||||||
override fun warning(message: String) {}
|
* - filtering out library components that have different ABI version than the ABI version of the current compiler
|
||||||
override fun fatal(message: String) = kotlin.error("e: $message")
|
*
|
||||||
}
|
* If no match found, fails with [Logger#fatal].
|
||||||
): KotlinLibrary {
|
*
|
||||||
return SingleKlibComponentResolver(libraryFile.absolutePath, listOf(KotlinAbiVersion.CURRENT), logger).resolve(libraryFile.absolutePath)
|
* Typical usage scenario: compiler.
|
||||||
|
*/
|
||||||
|
object CompilerSingleFileKlibResolveStrategy : SingleFileKlibResolveStrategy {
|
||||||
|
override fun resolve(libraryFile: File, logger: Logger) =
|
||||||
|
SingleKlibComponentResolver(libraryFile.absolutePath, listOf(KotlinAbiVersion.CURRENT), logger).resolve(libraryFile.absolutePath)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.library
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
|
import org.jetbrains.kotlin.util.Logger
|
||||||
|
|
||||||
|
interface SingleFileKlibResolveStrategy {
|
||||||
|
fun resolve(libraryFile: File, logger: Logger): KotlinLibrary
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resolveSingleFileKlib(
|
||||||
|
libraryFile: File,
|
||||||
|
logger: Logger = object : Logger {
|
||||||
|
override fun log(message: String) {}
|
||||||
|
override fun error(message: String) = kotlin.error("e: $message")
|
||||||
|
override fun warning(message: String) {}
|
||||||
|
override fun fatal(message: String) = kotlin.error("e: $message")
|
||||||
|
},
|
||||||
|
strategy: SingleFileKlibResolveStrategy = CompilerSingleFileKlibResolveStrategy
|
||||||
|
): KotlinLibrary = strategy.resolve(libraryFile, logger)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.library
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.konan.file.File
|
||||||
|
import org.jetbrains.kotlin.library.impl.createKotlinLibrary
|
||||||
|
import org.jetbrains.kotlin.util.Logger
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves KLIB library by making sure that the library has 1.4+ layout with exactly one component.
|
||||||
|
* If it is not, then [resolve] does not fail and returns a fake [KotlinLibrary] instance with nonexistent component that can be
|
||||||
|
* treated by the callee but can't be read.
|
||||||
|
*
|
||||||
|
* The given library path is assumed to be absolute and pointing to the real KLIB.
|
||||||
|
* It's the responsibility of the callee to check this condition in the appropriate way.
|
||||||
|
*
|
||||||
|
* [ToolingSingleFileKlibResolveStrategy] does not perform any ABI or metadata version compatibility checks.
|
||||||
|
* It's the responsibility of the callee to check library versions in the appropriate way.
|
||||||
|
*
|
||||||
|
* Typical usage scenario: IDE.
|
||||||
|
*/
|
||||||
|
object ToolingSingleFileKlibResolveStrategy : SingleFileKlibResolveStrategy {
|
||||||
|
override fun resolve(libraryFile: File, logger: Logger): KotlinLibrary {
|
||||||
|
if (checkComponent(libraryFile)) {
|
||||||
|
// old style library
|
||||||
|
return fakeLibrary(libraryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
val componentFiles = libraryFile.listFiles.filter(::checkComponent)
|
||||||
|
componentFiles.singleOrNull()?.let { componentFile ->
|
||||||
|
// single component library
|
||||||
|
return createKotlinLibrary(libraryFile, componentFile.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise mimic as old style library and warn
|
||||||
|
if (componentFiles.isNotEmpty()) {
|
||||||
|
// TODO: choose the best fit among all available candidates
|
||||||
|
|
||||||
|
logger.warning("Library $libraryFile can not be read. Multiple components found: ${componentFiles.map {
|
||||||
|
it.path.substringAfter(libraryFile.path)
|
||||||
|
}}")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fakeLibrary(libraryFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val NONEXISTENT_COMPONENT_NAME = "__nonexistent_component_name__"
|
||||||
|
|
||||||
|
private fun checkComponent(componentFile: File) = componentFile.child(KLIB_MANIFEST_FILE_NAME).isFile
|
||||||
|
private fun fakeLibrary(libraryFile: File) = createKotlinLibrary(libraryFile, NONEXISTENT_COMPONENT_NAME)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user