From 98c3147d19153a3becd9489a9c26381013b9200b Mon Sep 17 00:00:00 2001 From: Vladimir Sukharev Date: Wed, 21 Feb 2024 19:15:08 +0100 Subject: [PATCH] [K/N][Tests] Fix ComplexCInteropTest.kt to respect 2-stage compilation ^KT-66014 --- .../AbstractNativeCInteropKT39120Test.kt | 2 + .../test/blackbox/CinteropPackagesTest.kt | 2 + .../test/blackbox/ComplexCInteropTest.kt | 165 +++++++++--------- .../blackbox/IncrementalCompilationTest.kt | 2 + .../InfrastructureDumpedTestListingTest.kt | 2 + .../test/blackbox/KT59030WorkaroundTest.kt | 2 + .../konan/test/blackbox/KlibResolverTest.kt | 2 + .../test/blackbox/NativeSimpleTestUtils.kt | 6 + .../support/compilation/TestCompilation.kt | 26 ++- 9 files changed, 122 insertions(+), 87 deletions(-) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/AbstractNativeCInteropKT39120Test.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/AbstractNativeCInteropKT39120Test.kt index 269bb43a385..12de270a08c 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/AbstractNativeCInteropKT39120Test.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/AbstractNativeCInteropKT39120Test.kt @@ -54,6 +54,8 @@ abstract class AbstractNativeCInteropKT39120Test : AbstractNativeCInteropBaseTes val module = TestModule.Exclusive(DEFAULT_MODULE_NAME, emptySet(), emptySet(), emptySet()).apply { files += TestFile.createCommitted(ktFile, this) } + // KT-66014: TODO convert compileToExecutable() to TestCompilationFactory.testCasesToExecutable(), + // to respect possible `mode=TWO_STAGE_MULTI_MODULE`: factory would then add intermediate LibraryCompilation(kt->klib). val compilationResult = compileToExecutable( createTestCaseNoTestRun(module, TestCompilerArgs.EMPTY), klib1.asLibraryDependency(), diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/CinteropPackagesTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/CinteropPackagesTest.kt index 9cd14c4f18e..6d8f7574379 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/CinteropPackagesTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/CinteropPackagesTest.kt @@ -78,6 +78,8 @@ class CInteropPackagesTest : AbstractNativeSimpleTest() { freeCompilerArgs = TestCompilerArgs.EMPTY ).assertSuccess().resultingArtifact + // KT-66014: TODO convert compileToExecutable() to TestCompilationFactory.testCasesToExecutable(), + // to respect possible `mde=TWO_STAGE_MULTI_MODULE`: factory would then add intermediate LibraryCompilation(kt->klib). compileToExecutable( generateTestCaseWithSingleFile( sourceFile = ktFile, diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/ComplexCInteropTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/ComplexCInteropTest.kt index 8cbc63175a5..294524732db 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/ComplexCInteropTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/ComplexCInteropTest.kt @@ -44,6 +44,7 @@ class FirComplexCInteropTest : ComplexCInteropTestBase() abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { private val interopDir = File("native/native.tests/testData/interop") private val interopObjCDir = interopDir.resolve("objc") + private val testCompilationFactory = TestCompilationFactory() @Test @TestMetadata("embedStaticLibraries.kt") @@ -79,26 +80,20 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { ) } } - val cinteropKlib = cinteropToLibrary( - targets = targets, + val (testCase, compilationResult) = compileDefAndKtToExecutable( + testName = "embedStaticLibraries", defFile = defFile, - outputDir = buildDir, + ktFiles = listOf(embedStaticLibrariesDir.resolve("embedStaticLibraries.kt")), freeCompilerArgs = TestCompilerArgs( - emptyList(), cinteropArgs = listOf( + compilerArgs = listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi"), + cinteropArgs = listOf( "-header", embedStaticLibrariesDir.resolve("embedStaticLibraries.h").absolutePath, "-staticLibrary", "1.a", "-staticLibrary", "2.a", ) - ) - ).assertSuccess().resultingArtifact - - val testCase = generateTestCaseWithSingleFile( - sourceFile = embedStaticLibrariesDir.resolve("embedStaticLibraries.kt"), - testKind = TestKind.STANDALONE_NO_TR, + ), extras = TestCase.NoTestRunnerExtras("main"), - freeCompilerArgs = TestCompilerArgs("-opt-in=kotlinx.cinterop.ExperimentalForeignApi"), ) - val compilationResult = compileToExecutable(testCase, cinteropKlib.asLibraryDependency()).assertSuccess() val testExecutable = TestExecutable( compilationResult.resultingArtifact, compilationResult.loggedData, @@ -132,30 +127,21 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { if (testRunSettings.configurables.targetTriple.isSimulator) codesign(dylib.resultingArtifact.path) val stringsdict = interopObjCDir.resolve("Localizable.stringsdict") - stringsdict.copyTo(buildDir.resolve("en.lproj/Localizable.stringsdict"), overwrite = true) + stringsdict.copyTo(buildDir.resolve("$ktFilePrefix/en.lproj/Localizable.stringsdict"), overwrite = true) - val cinteropKlib = cinteropToLibrary( - targets = targets, + val (testCase, success) = compileDefAndKtToExecutable( + testName = ktFilePrefix, defFile = interopObjCDir.resolve("objcSmoke.def"), - outputDir = buildDir, - freeCompilerArgs = TestCompilerArgs(emptyList(), cinteropArgs = listOf("-header", "smoke.h")) - ).assertSuccess().resultingArtifact - - val testCase = generateTestCaseWithSingleFile( - sourceFile = interopObjCDir.resolve("$ktFilePrefix.kt"), - moduleName = "smoke", + ktFiles = listOf(interopObjCDir.resolve("$ktFilePrefix.kt")), freeCompilerArgs = TestCompilerArgs( - "-opt-in=kotlinx.cinterop.ExperimentalForeignApi", - "-linker-option", - "-L${buildDir.absolutePath}" + compilerArgs = listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi", "-linker-option", "-L${buildDir.absolutePath}"), + cinteropArgs = listOf("-header", "smoke.h") ), - testKind = TestKind.STANDALONE_NO_TR, extras = TestCase.NoTestRunnerExtras("main"), checks = TestRunChecks.Default(testRunSettings.get().executionTimeout).copy( outputDataFile = TestRunCheck.OutputDataFile(file = interopObjCDir.resolve("$ktFilePrefix.out")) - ) + ), ) - val success = compileToExecutable(testCase, cinteropKlib.asLibraryDependency()).assertSuccess() val testExecutable = TestExecutable( success.resultingArtifact, success.loggedData, @@ -167,20 +153,17 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { @Test @TestMetadata("tests") fun testInteropObjCTests() { + fun fileList(subFolder: String, extension: String) = + interopObjCDir.resolve(subFolder).walk().filter { it.isFile && it.extension == extension }.toList() + Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily) - val mSources = interopObjCDir.resolve("tests").listFiles { file: File -> file.name.endsWith(".m") }!!.toList() - val dylib = compileDylib("objctests", mSources) + val ktFiles = fileList("tests", "kt") + val hFiles = fileList("tests", "h") + val mFiles = fileList("tests", "m") + val dylib = compileDylib("objctests", mFiles) if (testRunSettings.configurables.targetTriple.isSimulator) codesign(dylib.resultingArtifact.path) - val hFiles = interopObjCDir.resolve("tests").listFiles { file: File -> file.name.endsWith(".h") }!!.toList() - val cinteropKlib = cinteropToLibrary( - targets = targets, - defFile = interopObjCDir.resolve("objcTests.def"), - outputDir = buildDir, - freeCompilerArgs = TestCompilerArgs(emptyList(), cinteropArgs = hFiles.flatMap { listOf("-header", "tests/${it.name}") }) - ).assertSuccess().resultingArtifact - val ignoredTestGTestPatterns = if (testRunSettings.get() != GCType.NOOP) emptySet() else setOf( "Kt41811Kt.*", "CustomStringKt.testCustomString", @@ -188,17 +171,21 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { "ObjcWeakRefsKt.testObjCWeakRef", "WeakRefsKt.testWeakRefs", ) - val testCase = generateTestCaseWithSingleModule( - moduleDir = interopObjCDir.resolve("tests"), + val (testCase, success) = compileDefAndKtToExecutable( + testName = "embedStaticLibraries", + defFile = interopObjCDir.resolve("objcTests.def"), + ktFiles = ktFiles, freeCompilerArgs = TestCompilerArgs( - "-opt-in=kotlinx.cinterop.ExperimentalForeignApi", - "-opt-in=kotlin.native.internal.InternalForKotlinNative", - "-XXLanguage:+ImplicitSignedToUnsignedIntegerConversion", - "-tr", "-e", "main", "-linker-option", "-L${buildDir.absolutePath}" + compilerArgs = listOf( + "-opt-in=kotlinx.cinterop.ExperimentalForeignApi", + "-opt-in=kotlin.native.internal.InternalForKotlinNative", + "-XXLanguage:+ImplicitSignedToUnsignedIntegerConversion", + "-tr", "-e", "main", "-linker-option", "-L${buildDir.absolutePath}" + ), + cinteropArgs = hFiles.flatMap { listOf("-header", "tests/${it.name}") } ), extras = TestCase.WithTestRunnerExtras(TestRunnerType.DEFAULT, ignoredTestGTestPatterns), ) - val success = compileToExecutable(testCase, cinteropKlib.asLibraryDependency()).assertSuccess() val testExecutable = TestExecutable( success.resultingArtifact, success.loggedData, @@ -257,7 +244,7 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { extraClangOpts = listOf("-framework", "AppKit", "-fobjc-arc"), extraCompilerOpts = listOf("-tr"), ) - assertTrue(execResult.stdout.contains("[ PASSED ] 8 tests")) + assertTrue(execResult.stdout.contains("[ PASSED ] 8 tests"), execResult.stdout) } @Test @@ -362,34 +349,21 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { if (testRunSettings.configurables.targetTriple.isSimulator) codesign(dylib.resultingArtifact.path) - val cinteropKlib = cinteropToLibrary( - targets = targets, + val (_, success) = compileDefAndKtToExecutable( + testName = testName, defFile = srcDir.resolve(defFile), - outputDir = buildDir, + ktFiles = listOf(srcDir.resolve(ktFile)), freeCompilerArgs = TestCompilerArgs( - compilerArgs = emptyList(), + compilerArgs = listOf( + "-opt-in=kotlinx.cinterop.ExperimentalForeignApi", + "-opt-in=kotlin.native.internal.InternalForKotlinNative", + "-linker-option", "-L${buildDir.absolutePath}", + *extraCompilerOpts.toTypedArray() + ), cinteropArgs = extraCinteropArgs + listOf("-header", srcDir.resolve(hFile).absolutePath) - ) - ).assertSuccess().resultingArtifact - - val testKind = when (extras) { - is TestCase.NoTestRunnerExtras -> TestKind.STANDALONE_NO_TR - is TestCase.WithTestRunnerExtras -> TestKind.STANDALONE - } - val testCase = generateTestCaseWithSingleFile( - sourceFile = srcDir.resolve(ktFile), - moduleName = testName, - testKind = testKind, + ), extras = extras, - freeCompilerArgs = TestCompilerArgs( - "-opt-in=kotlinx.cinterop.ExperimentalForeignApi", - "-opt-in=kotlin.native.internal.InternalForKotlinNative", - "-linker-option", "-L${buildDir.absolutePath}", - *extraCompilerOpts.toTypedArray() - ) ) - - val success = compileToExecutable(testCase, cinteropKlib.asLibraryDependency()).assertSuccess() return testRunSettings.executor.runProcess(success.resultingArtifact.executableFile.absolutePath) } @@ -418,22 +392,15 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { ) } } - val cinteropKlib = cinteropToLibrary( - targets = targets, - defFile = withSpacesDef, - outputDir = buildDir, - freeCompilerArgs = TestCompilerArgs.EMPTY - ).assertSuccess().resultingArtifact - val testCase = generateTestCaseWithSingleFile( - sourceFile = srcDir.resolve("withSpaces.kt"), - freeCompilerArgs = TestCompilerArgs( - "-opt-in=kotlinx.cinterop.ExperimentalForeignApi", - ), - testKind = TestKind.STANDALONE_NO_TR, + val (testCase, success) = compileDefAndKtToExecutable( + testName = "withSpaces", + defFile = withSpacesDef, + ktFiles = listOf(srcDir.resolve("withSpaces.kt")), + freeCompilerArgs = TestCompilerArgs("-opt-in=kotlinx.cinterop.ExperimentalForeignApi"), extras = TestCase.NoTestRunnerExtras("main"), ) - val success = compileToExecutable(testCase, cinteropKlib.asLibraryDependency()).assertSuccess() + val testExecutable = TestExecutable( success.resultingArtifact, success.loggedData, @@ -443,6 +410,40 @@ abstract class ComplexCInteropTestBase : AbstractNativeSimpleTest() { assertTrue(mapfile.exists()) } + private fun compileDefAndKtToExecutable( + testName: String, + defFile: File, + ktFiles: Collection, + freeCompilerArgs: TestCompilerArgs, + extras: TestCase.Extras, + checks: TestRunChecks = TestRunChecks.Default(testRunSettings.get().executionTimeout), + ): Pair> { + val cinteropModule = TestModule.Exclusive("cinterop", emptySet(), emptySet(), emptySet()) + cinteropModule.files += TestFile.createCommitted(defFile, cinteropModule) + + val ktModule = TestModule.Exclusive("main", setOf("cinterop"), emptySet(), emptySet()) + ktFiles.forEach { ktModule.files += TestFile.createCommitted(it, ktModule) } + + val testKind = when (extras) { + is TestCase.NoTestRunnerExtras -> TestKind.STANDALONE_NO_TR + is TestCase.WithTestRunnerExtras -> TestKind.STANDALONE + } + val testCase = TestCase( + id = TestCaseId.Named(testName), + kind = testKind, + modules = setOf(cinteropModule, ktModule), + freeCompilerArgs = freeCompilerArgs, + nominalPackageName = PackageName(testName), + checks = checks, + extras = extras + ).apply { + initialize(null, null) + } + // Compile test, respecting possible `mode=TWO_STAGE_MULTI_MODULE`: add intermediate LibraryCompilation(kt->klib), if needed. + val success = testCompilationFactory.testCasesToExecutable(listOf(testCase), testRunSettings).result.assertSuccess() + return Pair(testCase, success) + } + private fun compileDylib(name: String, mSources: List, extraClangOpts: List = listOf("-fobjc-arc")): TestCompilationResult.Success { val clangResult = compileWithClang( clangDistribution = ClangDistribution.Llvm, diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/IncrementalCompilationTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/IncrementalCompilationTest.kt index 5a84593d93b..efb1ffcdde0 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/IncrementalCompilationTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/IncrementalCompilationTest.kt @@ -498,6 +498,8 @@ class IncrementalCompilationTest : AbstractNativeSimpleTest() { build() } + // Compile test, NOT respecting possible `mode=TWO_STAGE_MULTI_MODULE`: don't add intermediate LibraryCompilation(kt->klib). + // KT-66014: Extract this test from usual Native test run, and run it in scope of new test module inline fun compileToExecutable( targetSrc: String, vararg dependencies: TestCompilationArtifact.KLIB, diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/InfrastructureDumpedTestListingTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/InfrastructureDumpedTestListingTest.kt index 64d6b3ce1ec..51f8101a9fe 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/InfrastructureDumpedTestListingTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/InfrastructureDumpedTestListingTest.kt @@ -54,6 +54,8 @@ class InfrastructureDumpedTestListingTest : AbstractNativeSimpleTest() { val (executableTestCase: TestCase, executableCompilationResult: TestCompilationResult) = if (fromSources) { + // Compile test, NOT respecting possible `mode=TWO_STAGE_MULTI_MODULE`: don't add intermediate LibraryCompilation(kt->klib). + // KT-66014: Extract this test from usual Native test run, and run it in scope of new test module barTestCase to compileToExecutable(barTestCase, fooLibrary.asLibraryDependency()) } else { val barCompilationResult: Success = compileToLibrary(barTestCase, fooLibrary.asLibraryDependency()) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KT59030WorkaroundTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KT59030WorkaroundTest.kt index 4529d7c5916..f23959f0749 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KT59030WorkaroundTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/KT59030WorkaroundTest.kt @@ -58,6 +58,8 @@ class KT59030WorkaroundTest : AbstractNativeSimpleTest() { ).assertSuccess().resultingArtifact spoilDeprecatedAnnotationsInLibrary(library) + // Compile test, NOT respecting possible `mode=TWO_STAGE_MULTI_MODULE`: don't add intermediate LibraryCompilation(kt->klib). + // KT-66014: Extract this test from usual Native test run, and run it in scope of new test module compileToExecutable( generateTestCaseWithSingleFile( sourceFile = File(MAIN_FILE_PATH), 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 54726c0bb8e..ac6607ab022 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 @@ -102,6 +102,8 @@ class KlibResolverTest : AbstractNativeSimpleTest() { testKind = TestKind.STANDALONE_NO_TR, extras = TestCase.NoTestRunnerExtras("main"), ) + // Compile test, NOT respecting possible `mode=TWO_STAGE_MULTI_MODULE`: don't add intermediate LibraryCompilation(kt->klib). + // KT-66014: Extract this test from usual Native test run, and run it in scope of new test module val executableResult = compileToExecutable(testCase, klibResult.resultingArtifact.asLibraryDependency()).assertSuccess() val testExecutable = TestExecutable( diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/NativeSimpleTestUtils.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/NativeSimpleTestUtils.kt index c876640eea7..d41e7f2f88a 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/NativeSimpleTestUtils.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/NativeSimpleTestUtils.kt @@ -78,6 +78,7 @@ internal class LibraryBuilder( ) } +// WARNING: compiles in one-stage mode (sources->executable) even when `mode=TWO_STAGE_MULTI_MODULE` internal class ExecutableBuilder( test: AbstractNativeSimpleTest, rootDir: File, @@ -91,6 +92,7 @@ internal class ExecutableBuilder( freeCompilerArgs.add(this) } + // WARNING: compiles in one-stage mode (sources->executable) even when `mode=TWO_STAGE_MULTI_MODULE` override fun build(sourcesDir: File, outputDir: File, dependencies: List) = test.compileToExecutable( sourcesDir, @@ -161,6 +163,7 @@ internal class CompiledExecutable( val testExecutable by lazy { TestExecutable.fromCompilationResult(testCase, compilationResult) } } +// WARNING: compiles in one-stage mode (sources->executable) even when `mode=TWO_STAGE_MULTI_MODULE` internal fun AbstractNativeSimpleTest.compileToExecutable( sourcesDir: File, tryPassSystemCacheDirectory: Boolean, @@ -168,6 +171,7 @@ internal fun AbstractNativeSimpleTest.compileToExecutable( vararg dependencies: TestCompilationArtifact.KLIB ) = compileToExecutable(sourcesDir, tryPassSystemCacheDirectory, freeCompilerArgs, dependencies.asList()) +// WARNING: compiles in one-stage mode (sources->executable) even when `mode=TWO_STAGE_MULTI_MODULE` internal fun AbstractNativeSimpleTest.compileToExecutable( sourcesDir: File, tryPassSystemCacheDirectory: Boolean, @@ -179,9 +183,11 @@ internal fun AbstractNativeSimpleTest.compileToExecutable( return CompiledExecutable(testCase, compilationResult.assertSuccess()) } +// WARNING: compiles in one-stage mode (sources->executable) even when `mode=TWO_STAGE_MULTI_MODULE` internal fun AbstractNativeSimpleTest.compileToExecutable(testCase: TestCase, vararg dependencies: TestCompilationDependency<*>) = compileToExecutable(testCase, true, dependencies.asList()) +// WARNING: compiles in one-stage mode (sources->static cache) even when `mode=TWO_STAGE_MULTI_MODULE` internal fun AbstractNativeSimpleTest.compileToStaticCache( klib: TestCompilationArtifact.KLIB, cacheDir: File, diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/TestCompilation.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/TestCompilation.kt index 0ade61a74ea..bb35ed1e359 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/TestCompilation.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/compilation/TestCompilation.kt @@ -296,7 +296,7 @@ internal class ObjCFrameworkCompilation( gcType = settings.get(), gcScheduler = settings.get(), allocator = settings.get(), - pipelineType = settings.getStageDependentPipelineType(), + pipelineType = settings.getStageDependentPipelineType(sourceModules), cacheMode = settings.get(), freeCompilerArgs = freeCompilerArgs, compilerPlugins = settings.get(), @@ -341,7 +341,7 @@ internal class BinaryLibraryCompilation( gcType = settings.get(), gcScheduler = settings.get(), allocator = settings.get(), - pipelineType = settings.getStageDependentPipelineType(), + pipelineType = settings.getStageDependentPipelineType(sourceModules), cacheMode = settings.get(), freeCompilerArgs = freeCompilerArgs, compilerPlugins = settings.get(), @@ -508,7 +508,7 @@ internal class ExecutableCompilation( gcType = settings.get(), gcScheduler = settings.get(), allocator = settings.get(), - pipelineType = settings.getStageDependentPipelineType(), + pipelineType = settings.getStageDependentPipelineType(sourceModules), cacheMode = settings.get(), freeCompilerArgs = freeCompilerArgs, compilerPlugins = settings.get(), @@ -712,8 +712,24 @@ private object BinaryOptions { } } -internal fun Settings.getStageDependentPipelineType(): PipelineType = +// Calculates PipelineType to be used for compilations involving native backend or C/ObjC export. +// Second stage of TWO_STAGE_MULTI_MODULE must receive PipelineType.DEFAULT to be unaware of the language version used before, during first stage. +internal fun Settings.getStageDependentPipelineType(sourceModules: Collection): PipelineType = when (get()) { TestMode.ONE_STAGE_MULTI_MODULE -> get() - TestMode.TWO_STAGE_MULTI_MODULE -> PipelineType.DEFAULT // Don't pass "-language_version" option to the second stage + TestMode.TWO_STAGE_MULTI_MODULE -> { + if (sourceModules.isEmpty()) + PipelineType.DEFAULT // KT-56182: Don't pass "-language_version" option to pure second compilation stage. + else { + println( // KT-66014: TODO change println() to fail{} if all testsuites in KT-66014 would be changed + "WARNING: Wrong testing approach for `mode=TWO_STAGE_MULTI_MODULE`: test explicitly uses one-stage compilation for sources:\n" + + "${sourceModules.map { it.files.map { it.location.name } }}\n" + + "Please re-implement test to split compilation to two stages, when `mode=TWO_STAGE_MULTI_MODULE` is specified.\n" + + "TestCompilationFactory provides some tooling for this." + ) + // Provided source modules must be compiled with proper frontend version, + // even if this version would be then wrongly passed to backend or C/ObjC generator + get() + } + } }