[klib] Add an option to write out header klibs

The header klib is supposed to only contain the public abi of the module
similar to jvm-abi-gen. It is intended to be used as a dependency for other
klib compilations instead of the full klib for compilation avoidance.

^KT-60807
This commit is contained in:
Johan Bay
2023-05-09 14:29:21 +02:00
committed by Space Team
parent 829e0675f4
commit 0a612e4268
90 changed files with 1374 additions and 76 deletions
@@ -314,6 +314,36 @@ fun main() {
}
}
}
// Header klib comparison tests
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
testClass<AbstractNativeHeaderKlibComparisonTest>(
suiteTestClassName = "NativeHeaderKlibComparisonTestGenerated",
) {
model("klib/header-klibs/comparison", extension = null, recursive = false)
}
testClass<AbstractNativeHeaderKlibComparisonTest>(
suiteTestClassName = "FirNativeHeaderKlibComparisonTestGenerated",
annotations = listOf(*frontendFir()),
) {
model("klib/header-klibs/comparison", extension = null, recursive = false)
}
}
// Header klib compilation tests
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
testClass<AbstractNativeHeaderKlibCompilationTest>(
suiteTestClassName = "NativeHeaderKlibCompilationTestGenerated",
) {
model("klib/header-klibs/compilation", extension = null, recursive = false)
}
testClass<AbstractNativeHeaderKlibCompilationTest>(
suiteTestClassName = "FirNativeHeaderKlibCompilationTestGenerated",
annotations = listOf(*frontendFir()),
) {
model("klib/header-klibs/compilation", extension = null, recursive = false)
}
}
}
}
@@ -0,0 +1,103 @@
/*
* Copyright 2010-2022 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.blackboxtest
import com.intellij.testFramework.TestDataFile
import org.jetbrains.kotlin.konan.blackboxtest.support.*
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
import org.jetbrains.kotlin.konan.blackboxtest.support.group.UsePartialLinkage
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.TestRunChecks
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Timeouts
import org.jetbrains.kotlin.konan.blackboxtest.support.util.getAbsoluteFile
import org.junit.jupiter.api.Tag
import java.io.File
import kotlin.test.assertContentEquals
import kotlin.test.assertFailsWith
@Tag("klib")
@UsePartialLinkage(UsePartialLinkage.Mode.ENABLED_WITH_ERROR)
abstract class AbstractNativeHeaderKlibComparisonTest : AbstractNativeSimpleTest() {
protected fun runTest(@TestDataFile testPath: String) {
val testPathFull = getAbsoluteFile(testPath)
val testCaseBase: TestCase = generateTestcaseFromDirectory(testPathFull, "base", listOf())
compileToLibrary(testCaseBase).assertSuccess()
val headerKlibBase = File(getHeaderPath("base"))
assert(headerKlibBase.exists())
val sameAbiDir = testPathFull.resolve("sameAbi")
val differentAbiDir = testPathFull.resolve("differentAbi")
assert(sameAbiDir.exists() || differentAbiDir.exists()) { "Nothing to compare" }
if (sameAbiDir.exists()) {
val testCaseSameAbi: TestCase = generateTestcaseFromDirectory(testPathFull, "sameAbi", listOf())
compileToLibrary(testCaseSameAbi).assertSuccess()
val headerKlibSameAbi = File(getHeaderPath("sameAbi"))
assert(headerKlibSameAbi.exists())
assertContentEquals(headerKlibBase.readBytes(), headerKlibSameAbi.readBytes())
}
if (differentAbiDir.exists()) {
val testCaseDifferentAbi: TestCase = generateTestcaseFromDirectory(testPathFull, "differentAbi", listOf())
compileToLibrary(testCaseDifferentAbi).assertSuccess()
val headerKlibDifferentAbi = File(getHeaderPath("differentAbi"))
assert(headerKlibDifferentAbi.exists())
assertFailsWith<AssertionError>("base and differentAbi header klib are equal") {
assertContentEquals(headerKlibBase.readBytes(), headerKlibDifferentAbi.readBytes())
}
}
}
}
@Tag("klib")
@UsePartialLinkage(UsePartialLinkage.Mode.ENABLED_WITH_ERROR)
abstract class AbstractNativeHeaderKlibCompilationTest : AbstractNativeSimpleTest() {
protected fun runTest(@TestDataFile testPath: String) {
val testPathFull = getAbsoluteFile(testPath)
assert(testPathFull.exists())
val testCaseLib: TestCase = generateTestcaseFromDirectory(testPathFull, "lib", listOf())
val klibLib = compileToLibrary(testCaseLib)
val headerKlibLib = File(getHeaderPath("lib"))
assert(headerKlibLib.exists())
val testPathApp = testPathFull.resolve("main")
val klibAppFromHeader = compileToLibrary(testPathApp, TestCompilationArtifact.KLIB(headerKlibLib))
val klibAppFromFull = compileToLibrary(testPathApp, klibLib.resultingArtifact)
assertContentEquals(
klibAppFromHeader.klibFile.readBytes(),
klibAppFromFull.klibFile.readBytes()
)
}
}
private fun AbstractNativeSimpleTest.getHeaderPath(rev: String) = buildDir.absolutePath + "/header.$rev.klib"
private fun AbstractNativeSimpleTest.generateTestcaseFromDirectory(source: File, rev: String, extraArgs: List<String>): TestCase {
val moduleName: String = source.name
val module = TestModule.Exclusive(moduleName, emptySet(), emptySet(), emptySet())
source.resolve(rev).listFiles()?.forEach {
muteTestIfNecessary(it)
module.files += TestFile.createCommitted(it, module)
}
val headerKlibPath = "-Xheader-klib-path=" + getHeaderPath(rev)
val relativeBasePath = "-Xklib-relative-path-base=$source/$rev"
return TestCase(
id = TestCaseId.Named(moduleName),
kind = TestKind.STANDALONE,
modules = setOf(module),
freeCompilerArgs = TestCompilerArgs(extraArgs + relativeBasePath + headerKlibPath),
nominalPackageName = PackageName.EMPTY,
checks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout),
extras = TestCase.WithTestRunnerExtras(TestRunnerType.DEFAULT)
).apply {
initialize(null, null)
}
}