[K/N][Tests] Migrate framework and objcexport tests
^KT-61259
This commit is contained in:
committed by
Space Team
parent
f00a145dd7
commit
025771460c
+7
-19
@@ -34,7 +34,13 @@ abstract class AbstractNativeObjCExportTest : AbstractNativeSimpleTest() {
|
||||
.map { testPathFull.resolve(it) }
|
||||
ktSources.forEach { muteTestIfNecessary(it) }
|
||||
|
||||
val testCase: TestCase = generateObjCFrameworkTestCase(testPathFull, ktSources)
|
||||
val testCase: TestCase = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE,
|
||||
TestCase.WithTestRunnerExtras(TestRunnerType.DEFAULT),
|
||||
testPathFull.name,
|
||||
ktSources,
|
||||
TestCompilerArgs(listOf("-Xexport-kdoc"))
|
||||
)
|
||||
val objCFramework: ObjCFramework = testCase.toObjCFramework().assertSuccess().resultingArtifact
|
||||
|
||||
val mainHeaderContents = objCFramework.mainHeader.readText()
|
||||
@@ -58,22 +64,4 @@ abstract class AbstractNativeObjCExportTest : AbstractNativeSimpleTest() {
|
||||
private fun TestCase.toObjCFramework(): TestCompilationResult<out ObjCFramework> {
|
||||
return testCompilationFactory.testCaseToObjCFrameworkCompilation(this, testRunSettings).result
|
||||
}
|
||||
|
||||
private fun generateObjCFrameworkTestCase(testPathFull: File, sources: List<File>): TestCase {
|
||||
val moduleName: String = testPathFull.name
|
||||
val module = TestModule.Exclusive(DEFAULT_MODULE_NAME, emptySet(), emptySet(), emptySet())
|
||||
sources.forEach { module.files += TestFile.createCommitted(it, module) }
|
||||
|
||||
return TestCase(
|
||||
id = TestCaseId.Named(moduleName),
|
||||
kind = TestKind.STANDALONE,
|
||||
modules = setOf(module),
|
||||
freeCompilerArgs = TestCompilerArgs(listOf("-Xexport-kdoc")),
|
||||
nominalPackageName = PackageName(moduleName),
|
||||
checks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout),
|
||||
extras = TestCase.WithTestRunnerExtras(TestRunnerType.DEFAULT)
|
||||
).apply {
|
||||
initialize(null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.konan.test.blackbox
|
||||
|
||||
import com.intellij.testFramework.TestDataPath
|
||||
import org.jetbrains.kotlin.konan.target.Family
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.*
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.compilation.*
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.compilation.TestCompilationResult.Companion.assertSuccess
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.group.FirPipeline
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestExecutable
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunChecks
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.*
|
||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Assumptions
|
||||
import org.junit.jupiter.api.Tag
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@TestDataPath("\$PROJECT_ROOT")
|
||||
class ClassicFrameworkTest : FrameworkTestBase()
|
||||
|
||||
@FirPipeline
|
||||
@Tag("frontend-fir")
|
||||
@TestDataPath("\$PROJECT_ROOT")
|
||||
class FirFrameworkTest : FrameworkTestBase()
|
||||
|
||||
abstract class FrameworkTestBase : AbstractNativeSimpleTest() {
|
||||
private val testSuiteDir = File("native/native.tests/testData/framework")
|
||||
private val extras = TestCase.NoTestRunnerExtras("There's no entrypoint in Swift program")
|
||||
private val testCompilationFactory = TestCompilationFactory()
|
||||
|
||||
@Test
|
||||
fun testValuesGenerics() {
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
val testName = "values_generics"
|
||||
|
||||
val testCase = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR, extras, "ValuesGenerics",
|
||||
listOf(
|
||||
testSuiteDir.resolve(testName).resolve("$testName.kt"),
|
||||
testSuiteDir.resolve("objcexport/values.kt"),
|
||||
),
|
||||
freeCompilerArgs = TestCompilerArgs(listOf("-opt-in=kotlinx.cinterop.ExperimentalForeignApi"))
|
||||
)
|
||||
testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase, testRunSettings).result.assertSuccess()
|
||||
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStdlib() {
|
||||
val testName = "stdlib"
|
||||
val testCase = generateObjCFramework(testName)
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultipleFrameworks() {
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
val testName = "multiple"
|
||||
|
||||
val testDir = testSuiteDir.resolve(testName)
|
||||
val framework1Dir = testDir.resolve("framework1")
|
||||
val sharedDir = testDir.resolve("shared")
|
||||
val moduleName1st = "First"
|
||||
val testCase1 = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR, extras, moduleName1st,
|
||||
listOf(
|
||||
framework1Dir.resolve("first.kt"),
|
||||
framework1Dir.resolve("test.kt"),
|
||||
sharedDir.resolve("shared.kt"),
|
||||
),
|
||||
TestCompilerArgs("-Xbinary=bundleId=$moduleName1st")
|
||||
)
|
||||
testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase1, testRunSettings).result.assertSuccess()
|
||||
|
||||
val framework2Dir = testDir.resolve("framework2")
|
||||
val moduleName2nd = "Second"
|
||||
val testCase2 = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR, extras, moduleName2nd,
|
||||
listOf(
|
||||
framework2Dir.resolve("second.kt"),
|
||||
framework2Dir.resolve("test.kt"),
|
||||
sharedDir.resolve("shared.kt"),
|
||||
),
|
||||
TestCompilerArgs("-Xbinary=bundleId=$moduleName2nd")
|
||||
)
|
||||
testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase2, testRunSettings).result.assertSuccess()
|
||||
|
||||
compileAndRunSwift(testName, testCase1) // testCase1 provides testRun parameters. testCase2 should have the same.
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultipleFrameworksStatic() {
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
val testName = "multiple"
|
||||
|
||||
val testDir = testSuiteDir.resolve(testName)
|
||||
val framework1Dir = testDir.resolve("framework1")
|
||||
val sharedDir = testDir.resolve("shared")
|
||||
val freeCompilerArgs = listOf("-Xstatic-framework", "-Xpre-link-caches=enable")
|
||||
val moduleName1st = "First"
|
||||
val defaultChecks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout)
|
||||
val checks = if (testRunSettings.get<CacheMode>() != CacheMode.WithoutCache) {
|
||||
// KT-34262, KT-65289: one assert in testIsolation4() fails with caches:
|
||||
// try assertFalse(obj2 is First.KotlinBase)
|
||||
defaultChecks.copy(exitCodeCheck = TestRunCheck.ExitCode.Expected(134))
|
||||
} else defaultChecks
|
||||
val testCase1 = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR, extras, moduleName1st,
|
||||
listOf(
|
||||
framework1Dir.resolve("first.kt"),
|
||||
framework1Dir.resolve("test.kt"),
|
||||
sharedDir.resolve("shared.kt"),
|
||||
),
|
||||
freeCompilerArgs = TestCompilerArgs(freeCompilerArgs + "-Xbinary=bundleId=$moduleName1st"),
|
||||
checks = checks,
|
||||
)
|
||||
testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase1, testRunSettings).result.assertSuccess()
|
||||
|
||||
val framework2Dir = testDir.resolve("framework2")
|
||||
val moduleName2nd = "Second"
|
||||
val testCase2 = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR, extras, moduleName2nd,
|
||||
listOf(
|
||||
framework2Dir.resolve("second.kt"),
|
||||
framework2Dir.resolve("test.kt"),
|
||||
sharedDir.resolve("shared.kt"),
|
||||
), freeCompilerArgs = TestCompilerArgs(freeCompilerArgs + "-Xbinary=bundleId=$moduleName2nd")
|
||||
)
|
||||
testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase2, testRunSettings).result.assertSuccess()
|
||||
|
||||
compileAndRunSwift(testName, testCase1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGH3343() {
|
||||
val testName = "gh3343"
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
val freeCInteropArgs = TestCompilerArgs(emptyList(), cinteropArgs = listOf("-header", "$testName.h"))
|
||||
val interopLibrary = compileCInterop(testName, freeCInteropArgs)
|
||||
val testCase = generateObjCFramework(testName, emptyList(), setOf(TestModule.Given(interopLibrary.klibFile)))
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKT42397() {
|
||||
val testName = "kt42397"
|
||||
val testCase = generateObjCFramework(testName)
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKT43517() {
|
||||
val testName = "kt43517"
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
val interopLibrary = compileCInterop(testName)
|
||||
|
||||
val testCase = generateObjCFramework(testName, emptyList(), setOf(TestModule.Given(interopLibrary.klibFile)))
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStacktrace() {
|
||||
val testName = "stacktrace"
|
||||
Assumptions.assumeFalse(testRunSettings.get<OptimizationMode>() == OptimizationMode.OPT)
|
||||
|
||||
val testCase = generateObjCFramework(testName, listOf("-g"))
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStacktraceBridges() {
|
||||
val testName = "stacktraceBridges"
|
||||
Assumptions.assumeFalse(testRunSettings.get<OptimizationMode>() == OptimizationMode.OPT)
|
||||
|
||||
val testCase = generateObjCFramework(testName, listOf("-g"))
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStacktraceByLibbacktrace() {
|
||||
Assumptions.assumeFalse(testRunSettings.get<OptimizationMode>() == OptimizationMode.OPT)
|
||||
val testName = "stacktraceByLibbacktrace"
|
||||
val testCase = generateObjCFramework(testName, listOf("-g", "-Xbinary=sourceInfoType=libbacktrace"))
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAbstractInstantiation() {
|
||||
val testName = "abstractInstantiation"
|
||||
val checks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout).copy(
|
||||
exitCodeCheck = TestRunCheck.ExitCode.Expected(134)
|
||||
)
|
||||
val testCase = generateObjCFramework(testName, checks = checks)
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFrameworkBundleId() {
|
||||
Assumptions.assumeTrue(testRunSettings.get<KotlinNativeTargets>().testTarget.family == Family.OSX)
|
||||
val testName = "bundle_id"
|
||||
val testDir = testSuiteDir.resolve(testName)
|
||||
val freeCompilerArgs = TestCompilerArgs(
|
||||
listOf(
|
||||
"-Xbinary=bundleId=$testName",
|
||||
"-Xbinary=bundleVersion=FooBundleVersion",
|
||||
"-Xbinary=bundleShortVersionString=FooBundleShortVersionString"
|
||||
)
|
||||
)
|
||||
val testCase = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR, extras, testName,
|
||||
listOf(
|
||||
testDir.resolve("main.kt"),
|
||||
testDir.resolve("lib.kt"),
|
||||
),
|
||||
freeCompilerArgs
|
||||
)
|
||||
testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase, testRunSettings).result.assertSuccess()
|
||||
|
||||
val buildDir = testRunSettings.get<Binaries>().testBinariesDir
|
||||
val infoPlist = buildDir.resolve("$testName.framework/Resources/Info.plist")
|
||||
val infoPlistContents = infoPlist.readText()
|
||||
listOf(
|
||||
"<key>CFBundleIdentifier</key>\\s*<string>$testName</string>",
|
||||
"<key>CFBundleShortVersionString</key>\\s*<string>FooBundleShortVersionString</string>",
|
||||
"<key>CFBundleVersion</key>\\s*<string>FooBundleVersion</string>",
|
||||
).forEach {
|
||||
assertTrue(infoPlistContents.contains(Regex(it))) {
|
||||
"${infoPlist.absolutePath} does not contain pattern `$it`:\n$infoPlistContents"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testForwardDeclarations() {
|
||||
val testName = "forwardDeclarations"
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
val interopLibrary = compileCInterop(testName)
|
||||
|
||||
val testCase = generateObjCFramework(testName, emptyList(), setOf(TestModule.Given(interopLibrary.klibFile)))
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
private fun compileCInterop(testName: String, freeCInteropArgs: TestCompilerArgs = TestCompilerArgs.EMPTY) =
|
||||
cinteropToLibrary(
|
||||
targets = targets,
|
||||
defFile = testSuiteDir.resolve(testName).resolve("$testName.def"),
|
||||
outputDir = buildDir,
|
||||
freeCompilerArgs = freeCInteropArgs
|
||||
).assertSuccess().resultingArtifact
|
||||
|
||||
@Test
|
||||
fun testUseFoundationModule() {
|
||||
val testName = "use_foundation_module"
|
||||
generateObjCFramework(testName)
|
||||
val modulemap = buildDir.resolve("$testName.framework/Modules/module.modulemap")
|
||||
val modulemapContents = modulemap.readText()
|
||||
val expectedPattern = "use Foundation"
|
||||
assertTrue(modulemapContents.contains(expectedPattern)) {
|
||||
"${modulemap.absolutePath} must contain `$expectedPattern`:\n$modulemapContents"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKT56233() {
|
||||
val testName = "kt56233"
|
||||
// test must make huge amount of repetitions to make sure there's no race conditions, so bigger timeout is needed. Double is not enough
|
||||
val checks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout * 10)
|
||||
val testCase = generateObjCFramework(testName, checks = checks)
|
||||
val swiftExtraOpts = if (testRunSettings.get<GCScheduler>() != GCScheduler.AGGRESSIVE) listOf() else
|
||||
listOf("-D", "AGGRESSIVE_GC")
|
||||
compileAndRunSwift(testName, testCase, swiftExtraOpts)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testKT57791() {
|
||||
val testName = "kt57791"
|
||||
val testCase = generateObjCFramework(testName)
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPermanentObjects() {
|
||||
val testName = "permanentObjects"
|
||||
Assumptions.assumeFalse(testRunSettings.get<GCType>() == GCType.NOOP) { "Test requires GC to actually happen" }
|
||||
|
||||
val testCase = generateObjCFramework(testName, listOf("-opt-in=kotlin.native.internal.InternalForKotlinNative"))
|
||||
compileAndRunSwift(testName, testCase)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun objCExportTest() {
|
||||
objCExportTestImpl("", emptyList(), emptyList(), false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun objCExportTestNoGenerics() {
|
||||
objCExportTestImpl("NoGenerics", listOf("-Xno-objc-generics"),
|
||||
listOf("-D", "NO_GENERICS"), false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun objCExportTestLegacySuspendUnit() {
|
||||
objCExportTestImpl("LegacySuspendUnit", listOf("-Xbinary=unitSuspendFunctionObjCExport=legacy"),
|
||||
listOf("-D", "LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT"), false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun objCExportTestNoSwiftMemberNameMangling() {
|
||||
objCExportTestImpl("NoSwiftMemberNameMangling", listOf("-Xbinary=objcExportDisableSwiftMemberNameMangling=true"),
|
||||
listOf("-D", "DISABLE_MEMBER_NAME_MANGLING"), false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun objCExportTestNoInterfaceMemberNameMangling() {
|
||||
objCExportTestImpl("NoInterfaceMemberNameMangling", listOf("-Xbinary=objcExportIgnoreInterfaceMethodCollisions=true"),
|
||||
listOf("-D", "DISABLE_INTERFACE_METHOD_NAME_MANGLING"), false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun objCExportTestStatic() {
|
||||
objCExportTestImpl("Static", listOf("-Xbinary=objcExportSuspendFunctionLaunchThreadRestriction=none"),
|
||||
listOf("-D", "ALLOW_SUSPEND_ANY_THREAD"), true)
|
||||
}
|
||||
|
||||
private fun objCExportTestImpl(
|
||||
suffix: String,
|
||||
frameworkOpts: List<String>,
|
||||
swiftOpts: List<String>,
|
||||
isStaticFramework: Boolean,
|
||||
) {
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
// Compile a couple of KLIBs
|
||||
val library = compileToLibrary(
|
||||
testSuiteDir.resolve("objcexport/library"),
|
||||
buildDir,
|
||||
TestCompilerArgs("-Xshort-module-name=MyLibrary", "-module-name", "org.jetbrains.kotlin.native.test-library"),
|
||||
emptyList(),
|
||||
)
|
||||
val noEnumEntries = compileToLibrary(
|
||||
testSuiteDir.resolve("objcexport/noEnumEntries"),
|
||||
buildDir,
|
||||
TestCompilerArgs(
|
||||
"-Xshort-module-name=NoEnumEntriesLibrary", "-XXLanguage:-EnumEntries",
|
||||
"-module-name", "org.jetbrains.kotlin.native.test-no-enum-entries-library",
|
||||
),
|
||||
emptyList(),
|
||||
)
|
||||
|
||||
// Convert KT sources into ObjC framework using two KLIbs
|
||||
val objcExportTestSuiteDir = testSuiteDir.resolve("objcexport")
|
||||
val ktFiles = objcExportTestSuiteDir.listFiles { file: File -> file.name.endsWith(".kt") }
|
||||
assertTrue(ktFiles != null && ktFiles.isNotEmpty()) {
|
||||
"Some .kt files must be in test folder $objcExportTestSuiteDir"
|
||||
}
|
||||
val frameworkName = "Kt"
|
||||
val testCase = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR, extras, "Kt",
|
||||
ktFiles!!.toList(),
|
||||
freeCompilerArgs = TestCompilerArgs(
|
||||
frameworkOpts + listOfNotNull(
|
||||
"-Xstatic-framework".takeIf { isStaticFramework },
|
||||
"-opt-in=kotlinx.cinterop.ExperimentalForeignApi",
|
||||
"-Xexport-kdoc",
|
||||
"-Xbinary=bundleId=foo.bar",
|
||||
"-module-name", frameworkName,
|
||||
)
|
||||
),
|
||||
givenDependencies = setOf(TestModule.Given(library.klibFile), TestModule.Given(noEnumEntries.klibFile)),
|
||||
// test must make huge amount of repetitions to make sure there's no race conditions, so bigger timeout is needed.
|
||||
checks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout * 2),
|
||||
)
|
||||
testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase, testRunSettings, listOf(noEnumEntries)).result.assertSuccess()
|
||||
|
||||
// compile Swift sources using generated ObjC framework
|
||||
val swiftFiles = objcExportTestSuiteDir.listFiles { file: File -> file.name.endsWith(".swift") }
|
||||
assertTrue(swiftFiles != null && swiftFiles.isNotEmpty()) {
|
||||
"Some .swift files must be in test folder $objcExportTestSuiteDir"
|
||||
}
|
||||
val swiftExtraOpts = buildList {
|
||||
addAll(swiftOpts)
|
||||
if (testRunSettings.get<GCScheduler>() == GCScheduler.AGGRESSIVE) {
|
||||
add("-D")
|
||||
add("AGGRESSIVE_GC")
|
||||
}
|
||||
if (testRunSettings.get<GCType>() == GCType.NOOP) {
|
||||
add("-D")
|
||||
add("NOOP_GC")
|
||||
}
|
||||
}
|
||||
val successExecutable = compileSwift(swiftFiles!!.toList(), swiftExtraOpts)
|
||||
val testExecutable = TestExecutable(
|
||||
successExecutable.resultingArtifact,
|
||||
successExecutable.loggedData,
|
||||
listOf(TestName("objCExportTest$suffix"))
|
||||
)
|
||||
runExecutableAndVerify(testCase, testExecutable)
|
||||
|
||||
// check Info.plist for expected bundle identifier
|
||||
val plistFName = if (targets.testTarget.family == Family.OSX) "Resources/Info.plist" else "Info.plist"
|
||||
val infoPlist = buildDir.resolve("$frameworkName.framework/$plistFName")
|
||||
val infoPlistContents = infoPlist.readText()
|
||||
assertTrue(infoPlistContents.contains(Regex("<key>CFBundleIdentifier</key>\\s*<string>foo.bar</string>"))) {
|
||||
"${infoPlist.absolutePath} does not contain expected pattern with `foo.bar`:\n$infoPlistContents"
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateObjCFramework(
|
||||
name: String,
|
||||
testCompilerArgs: List<String> = emptyList(),
|
||||
givenDependencies: Set<TestModule.Given> = emptySet(),
|
||||
checks: TestRunChecks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout),
|
||||
): TestCase {
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
|
||||
val testCase = generateObjCFrameworkTestCase(
|
||||
TestKind.STANDALONE_NO_TR,
|
||||
extras,
|
||||
name.replaceFirstChar { it.uppercase() },
|
||||
listOf(testSuiteDir.resolve(name).resolve("$name.kt")),
|
||||
TestCompilerArgs(testCompilerArgs + listOf("-Xbinary=bundleId=$name")),
|
||||
givenDependencies,
|
||||
checks = checks,
|
||||
)
|
||||
val objCFrameworkCompilation = testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase, testRunSettings)
|
||||
val success = objCFrameworkCompilation.result.assertSuccess()
|
||||
codesign(success.resultingArtifact.frameworkDir.absolutePath)
|
||||
|
||||
return testCase
|
||||
}
|
||||
|
||||
private fun compileAndRunSwift(testName: String, testCase: TestCase, swiftExtraOpts: List<String> = emptyList()) {
|
||||
val success = compileSwift(testName, swiftExtraOpts)
|
||||
val testExecutable = TestExecutable(
|
||||
success.resultingArtifact,
|
||||
success.loggedData,
|
||||
listOf(TestName(testName))
|
||||
)
|
||||
runExecutableAndVerify(testCase, testExecutable)
|
||||
}
|
||||
|
||||
private fun compileSwift(
|
||||
name: String,
|
||||
swiftExtraOpts: List<String>,
|
||||
): TestCompilationResult.Success<out TestCompilationArtifact.Executable> =
|
||||
compileSwift(listOf(testSuiteDir.resolve(name).resolve("$name.swift")), swiftExtraOpts)
|
||||
|
||||
private fun compileSwift(
|
||||
testSources: List<File>,
|
||||
swiftExtraOpts: List<String>,
|
||||
): TestCompilationResult.Success<out TestCompilationArtifact.Executable> {
|
||||
// create a test provider and get main entry point
|
||||
val provider = buildDir.resolve("provider.swift")
|
||||
FileWriter(provider).use { writer ->
|
||||
val providers = testSources
|
||||
.map { file ->
|
||||
file.name.toString().removeSuffix(".swift").replaceFirstChar { it.uppercase() }
|
||||
}
|
||||
.map { "${it}Tests" }
|
||||
|
||||
writer.write(
|
||||
"""
|
||||
|// THIS IS AUTOGENERATED FILE
|
||||
|// This method is invoked by the main routine to get a list of tests
|
||||
|func registerProviders() {
|
||||
| ${providers.joinToString("\n ") { "$it()" }}
|
||||
|}
|
||||
""".trimMargin()
|
||||
)
|
||||
}
|
||||
|
||||
return SwiftCompilation(
|
||||
testRunSettings,
|
||||
testSources + listOf(
|
||||
provider,
|
||||
testSuiteDir.resolve("main.swift")
|
||||
),
|
||||
TestCompilationArtifact.Executable(buildDir.resolve("swiftTestExecutable")),
|
||||
swiftExtraOpts,
|
||||
).result.assertSuccess()
|
||||
}
|
||||
}
|
||||
+26
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.konan.test.blackbox.support.settings.Binaries
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.KotlinNativeTargets
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.PipelineType
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.Timeouts
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.util.DEFAULT_MODULE_NAME
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.util.LAUNCHER_MODULE_NAME
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.junit.jupiter.api.Assumptions
|
||||
@@ -270,6 +271,31 @@ internal fun AbstractNativeSimpleTest.generateCInteropTestCaseFromSingleDefFile(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun AbstractNativeSimpleTest.generateObjCFrameworkTestCase(
|
||||
kind: TestKind,
|
||||
extras: TestCase.Extras,
|
||||
moduleName: String,
|
||||
sources: List<File>,
|
||||
freeCompilerArgs: TestCompilerArgs = TestCompilerArgs.EMPTY,
|
||||
givenDependencies: Set<TestModule.Given>? = null,
|
||||
checks: TestRunChecks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout),
|
||||
): TestCase {
|
||||
val module = TestModule.Exclusive(DEFAULT_MODULE_NAME, emptySet(), emptySet(), emptySet())
|
||||
sources.forEach { module.files += TestFile.createCommitted(it, module) }
|
||||
|
||||
return TestCase(
|
||||
id = TestCaseId.Named(moduleName),
|
||||
kind = kind,
|
||||
modules = setOf(module),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
nominalPackageName = PackageName(moduleName),
|
||||
checks = checks,
|
||||
extras = extras,
|
||||
).apply {
|
||||
initialize(givenDependencies, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractNativeSimpleTest.compileToLibrary(
|
||||
testCase: TestCase,
|
||||
outputDir: File,
|
||||
|
||||
+14
-3
@@ -93,17 +93,28 @@ internal abstract class LoggedData {
|
||||
abstract class CompilerCall : LoggedData()
|
||||
|
||||
class CInteropParameters(
|
||||
private val extraArgs: Array<String>,
|
||||
private val args: List<String>,
|
||||
private val defFile: File,
|
||||
private val environment: JVMEnvironment = JVMEnvironment() // Capture environment.
|
||||
) : LoggedData() {
|
||||
override fun computeText() = buildString {
|
||||
appendArguments("CINTEROP INVOCATION EXTRA ARGUMENTS:", extraArgs.toList())
|
||||
appendLine("TEST DEF FILE: ${defFile.canonicalPath}")
|
||||
appendArguments("CINTEROP INVOCATION ARGUMENTS:", args)
|
||||
appendLine()
|
||||
appendLine(environment)
|
||||
}
|
||||
}
|
||||
|
||||
class SwiftCParameters(
|
||||
private val args: List<String>,
|
||||
private val sources: List<File>,
|
||||
private val environment: JVMEnvironment = JVMEnvironment() // Capture environment.
|
||||
) : LoggedData() {
|
||||
override fun computeText() = buildString {
|
||||
appendList("TEST SWIFT SOURCES:", sources.map { it.absolutePath })
|
||||
appendArguments("SWIFTC INVOCATION ARGUMENTS:", args)
|
||||
appendLine()
|
||||
appendLine("TEST DEF FILE: ${defFile.canonicalPath}")
|
||||
appendLine(environment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
-5
@@ -10,10 +10,17 @@ import org.jetbrains.kotlin.cli.common.messages.*
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.compilerRunner.processCompilerOutput
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.konan.target.AppleConfigurables
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.NativeTestSupport
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.KotlinNativeTargets
|
||||
import org.jetbrains.kotlin.native.executors.RunProcessException
|
||||
import org.jetbrains.kotlin.native.executors.runProcess
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.Settings
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.configurables
|
||||
import org.jetbrains.kotlin.native.executors.*
|
||||
import org.jetbrains.kotlin.test.KtAssert.fail
|
||||
import org.junit.jupiter.api.Assumptions
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
@@ -119,12 +126,9 @@ internal fun callCompilerWithoutOutputInterceptor(
|
||||
@OptIn(ExperimentalTime::class)
|
||||
internal fun invokeCInterop(
|
||||
kotlinNativeClassLoader: ClassLoader,
|
||||
targets: KotlinNativeTargets,
|
||||
inputDef: File,
|
||||
outputLib: File,
|
||||
extraArgs: Array<String>
|
||||
args: Array<String>
|
||||
): CompilationToolCallResult {
|
||||
val args = arrayOf("-o", outputLib.canonicalPath, "-def", inputDef.canonicalPath, "-no-default-libs", "-target", targets.testTarget.name)
|
||||
val buildDir = KonanFile("${outputLib.canonicalPath}-build")
|
||||
val generatedDir = KonanFile(buildDir, "kotlin")
|
||||
val nativesDir = KonanFile(buildDir, "natives")
|
||||
@@ -138,7 +142,7 @@ internal fun invokeCInterop(
|
||||
entryPoint.invoke(
|
||||
interopClass.getDeclaredConstructor().newInstance(),
|
||||
"native",
|
||||
args + extraArgs,
|
||||
args,
|
||||
false,
|
||||
generatedDir.absolutePath, nativesDir.absolutePath, manifest.path, cstubsName // args for InternalInteropOptions()
|
||||
)
|
||||
@@ -170,6 +174,36 @@ internal fun invokeCInterop(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun invokeSwiftC(
|
||||
settings: Settings,
|
||||
args: List<String>,
|
||||
): CompilationToolCallResult {
|
||||
val targets = settings.get<KotlinNativeTargets>()
|
||||
Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily)
|
||||
val configs = settings.configurables as AppleConfigurables
|
||||
val swiftCompiler = configs.absoluteTargetToolchain + "/bin/swiftc"
|
||||
val result = try {
|
||||
runProcess(swiftCompiler, *args.toTypedArray()) {
|
||||
timeout = Duration.parse("5m")
|
||||
environment["DYLD_FALLBACK_FRAMEWORK_PATH"] =
|
||||
File(configs.absoluteTargetToolchain).resolveSibling("ExtraFrameworks").absolutePath
|
||||
}
|
||||
} catch (rpe: RunProcessException) {
|
||||
return CompilationToolCallResult(
|
||||
exitCode = ExitCode.COMPILATION_ERROR,
|
||||
toolOutput = "ARGS: $args\nSTDOUT: ${rpe.stdout}\nSTDERR: ${rpe.stderr}",
|
||||
toolOutputHasErrors = true,
|
||||
rpe.executionTime
|
||||
)
|
||||
}
|
||||
return CompilationToolCallResult(
|
||||
exitCode = ExitCode.OK,
|
||||
toolOutput = "ARGS: $args\nSTDOUT: ${result.stdout}\nSTDERR=${result.stderr}}",
|
||||
toolOutputHasErrors = false,
|
||||
result.executionTime
|
||||
)
|
||||
}
|
||||
|
||||
internal fun codesign(path: String) {
|
||||
val executableAbsolutePath = "/usr/bin/codesign"
|
||||
val args = arrayOf("--verbose", "-s", "-", path)
|
||||
|
||||
+91
-8
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.konan.test.blackbox.support.compilation
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.konan.properties.resolvablePropertyList
|
||||
import org.jetbrains.kotlin.konan.target.AppleConfigurables
|
||||
import org.jetbrains.kotlin.konan.target.withOSVersion
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.*
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.TestCase.*
|
||||
import org.jetbrains.kotlin.konan.test.blackbox.support.TestModule.Companion.allDependsOn
|
||||
@@ -76,7 +78,16 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
|
||||
protected abstract fun applyDependencies(argsBuilder: ArgsBuilder)
|
||||
|
||||
private fun ArgsBuilder.applyFreeArgs() {
|
||||
add(freeCompilerArgs.compilerArgs)
|
||||
when (this@BasicCompilation) {
|
||||
is LibraryCompilation, is StaticCacheCompilation ->
|
||||
// In TWO_STAGE_MULTI_MODULE mode, source->framework compilation is split to
|
||||
// - `source -> klib` stage,
|
||||
// - `klib -> static_cache stage(if caches enabled) and
|
||||
// - klib+static_cache -> framework
|
||||
// option `-Xstatic-framework` can be supplied only to `-p framework` stage, so must be filtered out for other stages
|
||||
add(freeCompilerArgs.compilerArgs.filter { it != "-Xstatic-framework" })
|
||||
else -> add(freeCompilerArgs.compilerArgs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ArgsBuilder.applyCompilerPlugins() {
|
||||
@@ -159,6 +170,7 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
|
||||
private val gcScheduler: GCScheduler,
|
||||
private val allocator: Allocator,
|
||||
private val pipelineType: PipelineType,
|
||||
private val cacheMode: CacheMode,
|
||||
freeCompilerArgs: TestCompilerArgs,
|
||||
compilerPlugins: CompilerPlugins,
|
||||
override val sourceModules: Collection<TestModule>,
|
||||
@@ -190,6 +202,9 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
|
||||
add("-friend-modules", friends.joinToString(File.pathSeparator) { friend -> friend.path })
|
||||
}
|
||||
add(dependencies.includedLibraries) { include -> "-Xinclude=${include.path}" }
|
||||
// static caches of distlibs should be used, like in old testinfra. Relates to KT-65289 for ObjC frameworks
|
||||
cacheMode.staticCacheForDistributionLibrariesRootDir
|
||||
?.let { cacheRootDir -> add("-Xcache-directory=$cacheRootDir") }
|
||||
}
|
||||
|
||||
private fun applyK2MPPArgs(argsBuilder: ArgsBuilder): Unit = with(argsBuilder) {
|
||||
@@ -222,6 +237,7 @@ internal class LibraryCompilation(
|
||||
gcScheduler = settings.get(),
|
||||
allocator = settings.get(),
|
||||
pipelineType = settings.get(),
|
||||
cacheMode = settings.get(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
sourceModules = sourceModules,
|
||||
@@ -244,7 +260,8 @@ internal class ObjCFrameworkCompilation(
|
||||
freeCompilerArgs: TestCompilerArgs,
|
||||
sourceModules: Collection<TestModule>,
|
||||
dependencies: Iterable<TestCompilationDependency<*>>,
|
||||
expectedArtifact: ObjCFramework
|
||||
expectedArtifact: ObjCFramework,
|
||||
val exportedLibraries: Iterable<KLIB> = emptyList(),
|
||||
) : SourceBasedCompilation<ObjCFramework>(
|
||||
targets = settings.get(),
|
||||
home = settings.get(),
|
||||
@@ -257,6 +274,7 @@ internal class ObjCFrameworkCompilation(
|
||||
gcScheduler = settings.get(),
|
||||
allocator = settings.get(),
|
||||
pipelineType = settings.getStageDependentPipelineType(),
|
||||
cacheMode = settings.get(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
sourceModules = sourceModules,
|
||||
@@ -272,6 +290,14 @@ internal class ObjCFrameworkCompilation(
|
||||
)
|
||||
super.applySpecificArgs(argsBuilder)
|
||||
}
|
||||
|
||||
override fun applyDependencies(argsBuilder: ArgsBuilder) = with(argsBuilder) {
|
||||
exportedLibraries.forEach {
|
||||
assertTrue(it in dependencies.libraries)
|
||||
add("-Xexport-library=${it.path}")
|
||||
}
|
||||
super.applyDependencies(argsBuilder)
|
||||
}
|
||||
}
|
||||
|
||||
internal class BinaryLibraryCompilation(
|
||||
@@ -292,6 +318,7 @@ internal class BinaryLibraryCompilation(
|
||||
gcScheduler = settings.get(),
|
||||
allocator = settings.get(),
|
||||
pipelineType = settings.getStageDependentPipelineType(),
|
||||
cacheMode = settings.get(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
sourceModules = sourceModules,
|
||||
@@ -328,7 +355,14 @@ internal class CInteropCompilation(
|
||||
) : TestCompilation<KLIB>() {
|
||||
|
||||
override val result: TestCompilationResult<out KLIB> by lazy {
|
||||
val extraArgsArray = buildList {
|
||||
val args = buildList {
|
||||
add("-def")
|
||||
add(defFile.canonicalPath)
|
||||
add("-target")
|
||||
add(targets.testTarget.name)
|
||||
add("-o")
|
||||
add(expectedArtifact.klibFile.canonicalPath)
|
||||
add("-no-default-libs")
|
||||
dependencies.forEach {
|
||||
add("-l")
|
||||
add(it.artifact.path)
|
||||
@@ -344,16 +378,14 @@ internal class CInteropCompilation(
|
||||
add("-DNS_FORMAT_ARGUMENT(A)=")
|
||||
add("-compiler-option")
|
||||
add("-I${defFile.parentFile}")
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
val loggedCInteropParameters = LoggedData.CInteropParameters(extraArgs = extraArgsArray, defFile = defFile)
|
||||
val loggedCInteropParameters = LoggedData.CInteropParameters(args, defFile)
|
||||
val (loggedCall: LoggedData, immediateResult: TestCompilationResult.ImmediateResult<out KLIB>) = try {
|
||||
val (exitCode, cinteropOutput, cinteropOutputHasErrors, duration) = invokeCInterop(
|
||||
classLoader.classLoader,
|
||||
targets,
|
||||
defFile,
|
||||
expectedArtifact.klibFile,
|
||||
extraArgsArray
|
||||
args.toTypedArray()
|
||||
)
|
||||
|
||||
val loggedInteropCall = LoggedData.CompilationToolCall(
|
||||
@@ -383,6 +415,56 @@ internal class CInteropCompilation(
|
||||
}
|
||||
}
|
||||
|
||||
internal class SwiftCompilation(
|
||||
testRunSettings: Settings,
|
||||
sources: List<File>,
|
||||
expectedArtifact: Executable,
|
||||
swiftExtraOpts: List<String>,
|
||||
) : TestCompilation<Executable>() {
|
||||
override val result: TestCompilationResult<out Executable> by lazy {
|
||||
val buildDir = testRunSettings.get<Binaries>().testBinariesDir
|
||||
val configs = testRunSettings.configurables as AppleConfigurables
|
||||
val swiftTarget = configs.targetTriple.withOSVersion(configs.osVersionMin).toString()
|
||||
val args = swiftExtraOpts + sources.map { it.absolutePath } + listOf(
|
||||
"-sdk", configs.absoluteTargetSysRoot, "-target", swiftTarget,
|
||||
"-g", "-o", expectedArtifact.executableFile.absolutePath,
|
||||
"-Xlinker", "-rpath", "-Xlinker", "@executable_path/Frameworks",
|
||||
"-Xlinker", "-rpath", "-Xlinker", buildDir.absolutePath,
|
||||
"-F", buildDir.absolutePath,
|
||||
"-Xcc", "-Werror", // To fail compilation on warnings in framework header.
|
||||
)
|
||||
|
||||
val loggedSwiftCParameters = LoggedData.SwiftCParameters(args, sources)
|
||||
val (loggedCall: LoggedData, immediateResult: TestCompilationResult.ImmediateResult<out Executable>) = try {
|
||||
val (exitCode, swiftcOutput, swiftcOutputHasErrors, duration) =
|
||||
invokeSwiftC(testRunSettings, args)
|
||||
|
||||
val loggedSwiftCCall = LoggedData.CompilationToolCall(
|
||||
toolName = "SWIFTC",
|
||||
input = null,
|
||||
parameters = loggedSwiftCParameters,
|
||||
exitCode = exitCode,
|
||||
toolOutput = swiftcOutput,
|
||||
toolOutputHasErrors = swiftcOutputHasErrors,
|
||||
duration = duration
|
||||
)
|
||||
val res = if (exitCode != ExitCode.OK || swiftcOutputHasErrors)
|
||||
TestCompilationResult.CompilationToolFailure(loggedSwiftCCall)
|
||||
else
|
||||
TestCompilationResult.Success(expectedArtifact, loggedSwiftCCall)
|
||||
|
||||
loggedSwiftCCall to res
|
||||
} catch (unexpectedThrowable: Throwable) {
|
||||
val loggedFailure = LoggedData.CompilationToolCallUnexpectedFailure(loggedSwiftCParameters, unexpectedThrowable)
|
||||
val res = TestCompilationResult.UnexpectedFailure(loggedFailure)
|
||||
|
||||
loggedFailure to res
|
||||
}
|
||||
expectedArtifact.logFile.writeText(loggedCall.toString())
|
||||
immediateResult
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExecutableCompilation(
|
||||
settings: Settings,
|
||||
freeCompilerArgs: TestCompilerArgs,
|
||||
@@ -403,6 +485,7 @@ internal class ExecutableCompilation(
|
||||
gcScheduler = settings.get(),
|
||||
allocator = settings.get(),
|
||||
pipelineType = settings.getStageDependentPipelineType(),
|
||||
cacheMode = settings.get(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
sourceModules = sourceModules,
|
||||
|
||||
+9
-3
@@ -109,7 +109,11 @@ internal class TestCompilationFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun testCaseToObjCFrameworkCompilation(testCase: TestCase, settings: Settings): ObjCFrameworkCompilation {
|
||||
fun testCaseToObjCFrameworkCompilation(
|
||||
testCase: TestCase,
|
||||
settings: Settings,
|
||||
exportedLibraries: Iterable<KLIB> = emptyList(),
|
||||
): ObjCFrameworkCompilation {
|
||||
val cacheKey = ObjCFrameworkCacheKey(testCase.rootModules)
|
||||
cachedObjCFrameworkCompilations[cacheKey]?.let { return it }
|
||||
|
||||
@@ -126,8 +130,9 @@ internal class TestCompilationFactory {
|
||||
freeCompilerArgs = testCase.freeCompilerArgs,
|
||||
sourceModules = sourceModules,
|
||||
dependencies = dependencies,
|
||||
exportedLibraries = exportedLibraries,
|
||||
expectedArtifact = ObjCFramework(
|
||||
settings.artifactDirForPackageName(testCase.nominalPackageName),
|
||||
settings.get<Binaries>().testBinariesDir,
|
||||
testCase.nominalPackageName.compressedPackageName
|
||||
)
|
||||
)
|
||||
@@ -184,7 +189,8 @@ internal class TestCompilationFactory {
|
||||
}
|
||||
TestMode.TWO_STAGE_MULTI_MODULE -> {
|
||||
// Compile root modules to KLIB. Pass this KLIB as included dependency to executable compilation.
|
||||
val klibCompilations = modulesToKlib(rootModules, freeCompilerArgs, produceStaticCache(), settings)
|
||||
val klibCompilations =
|
||||
modulesToKlib(rootModules, freeCompilerArgs, produceStaticCache(), settings)
|
||||
|
||||
Pair(
|
||||
// Include just compiled KLIB as -Xinclude dependency.
|
||||
|
||||
Reference in New Issue
Block a user