[KLIB Resolver] Native: Respect -nostdlib & -no-default-libs CLI args
The goal of this commit is to fix the behavior inside KLIB resolver
component in the Kotlin/Native compiler to avoid unattended reads
of stdlib and platform libraries from the Kotlin/Native distribution
in cases like the one described in KT-71633.
^KT-71633 Fixed
diff --git a/compiler/util-klib/src/org/jetbrains/kotlin/library/SearchPathResolver.kt b/compiler/util-klib/src/org/jetbrains/kotlin/library/SearchPathResolver.kt
index 9548cea..5ea328d 100644
--- a/compiler/util-klib/src/org/jetbrains/kotlin/library/SearchPathResolver.kt
+++ b/compiler/util-klib/src/org/jetbrains/kotlin/library/SearchPathResolver.kt
@@ -1,8 +1,7 @@
package org.jetbrains.kotlin.library
import org.jetbrains.kotlin.konan.file.File
-import org.jetbrains.kotlin.library.SearchPathResolver.LookupResult
-import org.jetbrains.kotlin.library.SearchPathResolver.SearchRoot
+import org.jetbrains.kotlin.library.SearchPathResolver.*
import org.jetbrains.kotlin.library.impl.createKotlinLibraryComponents
import org.jetbrains.kotlin.util.Logger
import org.jetbrains.kotlin.util.WithLogger
@@ -113,13 +112,31 @@
abstract class KotlinLibrarySearchPathResolver<L : KotlinLibrary>(
directLibs: List<String>,
val distributionKlib: String?,
- private val skipCurrentDir: Boolean,
+ skipCurrentDir: Boolean,
+ skipNativeCommonLibs: Boolean,
override val logger: Logger
) : SearchPathResolver<L> {
+ constructor(
+ directLibs: List<String>,
+ distributionKlib: String?,
+ skipCurrentDir: Boolean,
+ logger: Logger
+ ) : this(
+ directLibs = directLibs,
+ distributionKlib = distributionKlib,
+ skipCurrentDir = skipCurrentDir,
+ skipNativeCommonLibs = false,
+ logger = logger
+ )
- private val distHead: File? get() = distributionKlib?.File()?.child("common")
- open val distPlatformHead: File? = null
- private val currentDirHead: File? get() = if (!skipCurrentDir) File.userDir else null
+ private val nativeDistCommonLibsDir: File? by lazy {
+ distributionKlib?.takeUnless { skipNativeCommonLibs }?.File()?.child("common")
+ }
+
+ protected open val nativeDistPlatformLibsDir: File? get() = null
+
+ @Deprecated("This property is deprecated and will be removed soon. Please, stop using it.")
+ open val distPlatformHead: File? get() = null
abstract fun libraryComponentBuilder(file: File, isDefault: Boolean): List<L>
@@ -137,11 +154,13 @@
val searchRoots = mutableListOf<SearchRoot?>()
// Current working dir:
- searchRoots += currentDirHead?.let { SearchRoot(searchRootPath = it, allowLookupByRelativePath = true) }
+ if (!skipCurrentDir) {
+ searchRoots += SearchRoot(searchRootPath = File.userDir, allowLookupByRelativePath = true)
+ }
// Current Kotlin/Native distribution:
- searchRoots += distHead?.let { SearchRoot(searchRootPath = it) }
- searchRoots += distPlatformHead?.let { SearchRoot(searchRootPath = it) }
+ searchRoots += nativeDistCommonLibsDir?.let { SearchRoot(searchRootPath = it) }
+ searchRoots += nativeDistPlatformLibsDir?.let { SearchRoot(searchRootPath = it) }
searchRoots.filterNotNull()
}
@@ -241,8 +260,9 @@
get() = File(this, "klib")
// The libraries from the default root are linked automatically.
+ @Deprecated("This property is deprecated and will be removed soon. Please, stop using it.")
val defaultRoots: List<File>
- get() = listOfNotNull(distHead, distPlatformHead).filter { it.exists }
+ get() = listOfNotNull(nativeDistCommonLibsDir, nativeDistPlatformLibsDir).filter { it.exists }
private fun getDefaultLibrariesFromDir(directory: File, prefix: String = "org.jetbrains.kotlin") =
if (directory.exists) {
@@ -265,13 +285,13 @@
// Endorsed libraries in distHead.
if (!noEndorsedLibs) {
- distHead?.let {
+ nativeDistCommonLibsDir?.let {
result.addAll(getDefaultLibrariesFromDir(it))
}
}
// Platform libraries resolve.
if (!noDefaultLibs) {
- distPlatformHead?.let {
+ nativeDistPlatformLibsDir?.let {
result.addAll(getDefaultLibrariesFromDir(it))
}
}
@@ -287,9 +307,29 @@
directLibs: List<String>,
distributionKlib: String?,
skipCurrentDir: Boolean,
+ skipNativeCommonLibs: Boolean,
logger: Logger,
private val knownIrProviders: List<String>
-) : KotlinLibrarySearchPathResolver<L>(directLibs, distributionKlib, skipCurrentDir, logger), SearchPathResolver<L> {
+) : KotlinLibrarySearchPathResolver<L>(
+ directLibs = directLibs,
+ distributionKlib = distributionKlib,
+ skipCurrentDir = skipCurrentDir,
+ skipNativeCommonLibs = skipNativeCommonLibs,
+ logger = logger
+), SearchPathResolver<L> {
+ constructor(
+ directLibs: List<String>,
+ distributionKlib: String?,
+ skipCurrentDir: Boolean,
+ logger: Logger,
+ knownIrProviders: List<String>
+ ) : this(
+ directLibs = directLibs,
+ distributionKlib = distributionKlib,
+ skipCurrentDir = skipCurrentDir,
+ skipNativeCommonLibs = false,
+ logger, knownIrProviders
+ )
@Deprecated(
"Please use the KotlinLibraryProperResolverWithAttributes constructor which does not has 'repositories' and 'localKotlinDir' value parameters",
diff --git a/kotlin-native/Interop/StubGenerator/src/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt b/kotlin-native/Interop/StubGenerator/src/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt
index 9db3cac..5c32483 100644
--- a/kotlin-native/Interop/StubGenerator/src/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt
+++ b/kotlin-native/Interop/StubGenerator/src/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt
@@ -476,7 +476,7 @@
private fun getLibraryResolver(
cinteropArguments: CInteropArguments, target: KonanTarget
): KotlinLibraryResolverImpl<KonanLibrary> {
- return defaultResolver(
+ return defaultNativeKlibResolver(
directLibs = cinteropArguments.library,
target,
Distribution(KotlinNativePaths.homePath.absolutePath, konanDataDir = cinteropArguments.konanDataDir)
diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt
index ebe4aac..6229b34 100644
--- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt
+++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLibrariesResolveSupport.kt
@@ -10,7 +10,7 @@
import org.jetbrains.kotlin.config.DuplicatedUniqueNameStrategy
import org.jetbrains.kotlin.config.KlibConfigurationKeys
import org.jetbrains.kotlin.konan.file.File
-import org.jetbrains.kotlin.konan.library.defaultResolver
+import org.jetbrains.kotlin.konan.library.defaultNativeKlibResolver
import org.jetbrains.kotlin.konan.target.Distribution
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.library.RequiredUnresolvedLibrary
@@ -34,11 +34,14 @@
private val unresolvedLibraries = libraryPaths.toUnresolvedLibraries
- private val resolver = defaultResolver(
- libraryPaths + includedLibraryFiles.map { it.absolutePath },
+ private val resolver = defaultNativeKlibResolver(
+ directLibs = libraryPaths + includedLibraryFiles.map { it.absolutePath },
target,
distribution,
- configuration.getLogger()
+ skipCurrentDir = false,
+ skipNativeCommonLibs = configuration.getBoolean(KonanConfigKeys.NOSTDLIB),
+ skipNativePlatformLibs = configuration.getBoolean(KonanConfigKeys.NODEFAULTLIBS),
+ logger = configuration.getLogger()
).libraryResolver(resolveManifestDependenciesLenient)
// We pass included libraries by absolute paths to avoid repository-based resolution for them.
diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/Fir2IrNativeResultsConverter.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/Fir2IrNativeResultsConverter.kt
index 44b08ac..b1b19e9 100644
--- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/Fir2IrNativeResultsConverter.kt
+++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/Fir2IrNativeResultsConverter.kt
@@ -131,6 +131,8 @@
target = nativeTarget,
distributionKlib = nativeDistributionKlibPath,
skipCurrentDir = true,
+ skipNativeCommonLibs = false,
+ skipNativePlatformLibs = false,
logger = logger
).libraryResolver()
diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KlibResolverTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KlibResolverTest.kt
index 04b44c5..b4fda15 100644
--- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KlibResolverTest.kt
+++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KlibResolverTest.kt
@@ -672,8 +672,7 @@
produceUnpackedKlib = true, // does not matter
warningHandler = null,
cliArgs = emptyList()
- )
- customLibraryWithDependencyOnStdlib.assertDependsOnlyOnStdlib()
+ ).apply { assertDependsOnlyOnStdlib() }
fun compileWithoutStdlib(withoutPlatformLibs: Boolean = false, explicitDependency: String? = null): File =
compileSingleModule(
@@ -690,10 +689,10 @@
this += explicitDependency
}
}
- )
+ ).apply { assertDependsOnlyOnStdlib() }
// The following compiler invocations must fail due to unavailability of stdlib:
- run { // TODO(KT-71633): should fail!
+ expectFailingCompilation {
compileWithoutStdlib()
}
expectFailingCompilation {
@@ -701,12 +700,12 @@
}
// The following compiler invocations must fail due to unavailability of stdlib:
- run { // TODO(KT-71633): should fail!
+ expectFailingCompilation {
compileWithoutStdlib(
explicitDependency = customLibraryWithDependencyOnStdlib.absolutePath
)
}
- run { // TODO(KT-71633): should fail!
+ expectFailingCompilation {
compileWithoutStdlib(
withoutPlatformLibs = true,
explicitDependency = customLibraryWithDependencyOnStdlib.absolutePath
@@ -716,14 +715,14 @@
val stdlibPath = testRunSettings.get<KotlinNativeHome>().librariesDir.resolve("common/stdlib").absolutePath
// The following compiler invocations should succeed because stdlib is specified by path as a user-defined library:
- compileWithoutStdlib(explicitDependency = stdlibPath).assertDependsOnlyOnStdlib()
- compileWithoutStdlib(withoutPlatformLibs = true, explicitDependency = stdlibPath).assertDependsOnlyOnStdlib()
+ compileWithoutStdlib(explicitDependency = stdlibPath)
+ compileWithoutStdlib(withoutPlatformLibs = true, explicitDependency = stdlibPath)
// The following compiler invocations must fail due to unavailability of stdlib (stdlib specified by just a name):
- run { // TODO(KT-71633): should fail!
+ expectFailingAsNotFound("stdlib") {
compileWithoutStdlib(explicitDependency = "stdlib")
}
- run { // TODO(KT-71633): should fail!
+ expectFailingAsNotFound("stdlib") {
compileWithoutStdlib(withoutPlatformLibs = true, explicitDependency = "stdlib")
}
}
@@ -733,7 +732,7 @@
fun testNoDefaultLibsArgumentIsRespected(): Unit = with(NonRepeatedModuleNameGenerator()) {
fun File.assertDependsOnlyOnStdlibAndPosix() {
assertEquals(
- setOf("stdlib", "org.jetbrains.kotlin.native.platform.posix"),
+ setOf("stdlib", POSIX),
readDependsFromManifestFile(this)
)
}
@@ -758,11 +757,15 @@
)
customLibraryWithDependencyOnPosix.assertDependsOnlyOnStdlibAndPosix()
- fun compileWithoutPlatformLibs(sourceFile: File? = null, explicitDependencies: List<String> = emptyList()) {
+ fun compileWithoutPlatformLibs(
+ sourceFile: File? = null,
+ explicitDependencies: List<String> = emptyList(),
+ warningHandler: ((String) -> Unit)? = null,
+ ) {
compileSingleModule(
moduleBaseName = "lib",
produceUnpackedKlib = true, // does not matter
- warningHandler = null,
+ warningHandler = warningHandler,
cliArgs = buildList {
this += "-no-default-libs"
for (explicitDependency in explicitDependencies) {
@@ -780,21 +783,24 @@
expectFailingCompilation {
compileWithoutPlatformLibs(sourceFile = generateSourceFileWithPosixUsage())
}
- run { // TODO(KT-71633): should fail!
- compileWithoutPlatformLibs(explicitDependencies = listOf(customLibraryWithDependencyOnPosix.absolutePath))
- }
+ compileWithoutPlatformLibs(
+ explicitDependencies = listOf(customLibraryWithDependencyOnPosix.absolutePath),
+ warningHandler = { warning ->
+ assertTrue(warning.startsWith("warning: KLIB resolver: Could not find \"$POSIX\""))
+ }
+ )
// The following compiler invocations must fail due to unavailability of posix:
- run { // TODO(KT-71633): should fail!
+ expectFailingAsNotFound(POSIX) {
compileWithoutPlatformLibs(
sourceFile = generateSourceFileWithPosixUsage(),
- explicitDependencies = listOf("org.jetbrains.kotlin.native.platform.posix")
+ explicitDependencies = listOf(POSIX)
)
}
- run { // TODO(KT-71633): should fail!
+ expectFailingAsNotFound(POSIX) {
compileWithoutPlatformLibs(
explicitDependencies = listOf(
- "org.jetbrains.kotlin.native.platform.posix",
+ POSIX,
customLibraryWithDependencyOnPosix.absolutePath
)
)
@@ -1075,6 +1081,8 @@
private const val USER_DIR = "user.dir"
private val irProvidersMismatchSrcDir = File("native/native.tests/testData/irProvidersMismatch")
+ private const val POSIX = "org.jetbrains.kotlin.native.platform.posix"
+
private const val DUPLICATED_UNIQUE_NAME = "DUPLICATED_UNIQUE_NAME"
private fun DuplicatedUniqueNameStrategy.asCliArgument(): String {
diff --git a/native/utils/src/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt b/native/utils/src/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt
index 5431512..d357269 100644
--- a/native/utils/src/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt
+++ b/native/utils/src/org/jetbrains/kotlin/konan/library/SearchPathResolver.kt
@@ -12,17 +12,41 @@
val target: KonanTarget
}
+@Deprecated(
+ "Please use defaultNativeKlibResolver() instead, which has 'skipNativeCommonLibs' and 'skipNativePlatformLibs' parameters",
+ ReplaceWith("defaultNativeKlibResolver(directLibs, target, distribution, logger, skipCurrentDir, skipNativeCommonLibs = false, skipNativePlatformLibs = false)")
+)
fun defaultResolver(
directLibs: List<String>,
target: KonanTarget,
distribution: Distribution,
logger: Logger = DummyLogger,
skipCurrentDir: Boolean = false
+): SearchPathResolverWithTarget<KonanLibrary> = defaultNativeKlibResolver(
+ directLibs = directLibs,
+ target = target,
+ distribution = distribution,
+ skipCurrentDir = skipCurrentDir,
+ skipNativeCommonLibs = false,
+ skipNativePlatformLibs = false,
+ logger = logger
+)
+
+fun defaultNativeKlibResolver(
+ directLibs: List<String>,
+ target: KonanTarget,
+ distribution: Distribution,
+ logger: Logger = DummyLogger,
+ skipCurrentDir: Boolean = false,
+ skipNativeCommonLibs: Boolean = false,
+ skipNativePlatformLibs: Boolean = false,
): SearchPathResolverWithTarget<KonanLibrary> = KonanLibraryProperResolver(
directLibs = directLibs,
target = target,
distributionKlib = distribution.klib,
skipCurrentDir = skipCurrentDir,
+ skipNativeCommonLibs = skipNativeCommonLibs,
+ skipNativePlatformLibs = skipNativePlatformLibs,
logger = logger
)
@@ -31,18 +55,42 @@
override val target: KonanTarget,
distributionKlib: String?,
skipCurrentDir: Boolean,
+ skipNativeCommonLibs: Boolean,
+ skipNativePlatformLibs: Boolean,
override val logger: Logger
) : KotlinLibraryProperResolverWithAttributes<KonanLibrary>(
directLibs = directLibs,
distributionKlib = distributionKlib,
skipCurrentDir = skipCurrentDir,
+ skipNativeCommonLibs = skipNativeCommonLibs,
logger = logger,
knownIrProviders = listOf(KLIB_INTEROP_IR_PROVIDER_IDENTIFIER)
), SearchPathResolverWithTarget<KonanLibrary> {
+ @Deprecated(
+ "Please use the primary constructor instead, which has 'skipNativeCommonLibs' and 'skipNativePlatformLibs' parameters",
+ ReplaceWith("KonanLibraryProperResolver>(directLibs, target, distributionKlib, skipCurrentDir, skipNativeCommonLibs = false, skipNativePlatformLibs = false, logger)"),
+ )
+ constructor(
+ directLibs: List<String>,
+ target: KonanTarget,
+ distributionKlib: String?,
+ skipCurrentDir: Boolean,
+ logger: Logger
+ ) : this(
+ directLibs = directLibs,
+ target = target,
+ distributionKlib = distributionKlib,
+ skipCurrentDir = skipCurrentDir,
+ skipNativeCommonLibs = false,
+ skipNativePlatformLibs = false,
+ logger = logger,
+ )
+
override fun libraryComponentBuilder(file: File, isDefault: Boolean) = createKonanLibraryComponents(file, target, isDefault)
- override val distPlatformHead: File?
- get() = distributionKlib?.File()?.child("platform")?.child(target.visibleName)
+ override val nativeDistPlatformLibsDir: File? by lazy {
+ distributionKlib?.takeUnless { skipNativePlatformLibs }?.File()?.child("platform")?.child(target.visibleName)
+ }
override fun libraryMatch(candidate: KonanLibrary, unresolved: UnresolvedLibrary): Boolean {
val resolverTarget = this.target