[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