[K/N][KT-39120] Build platform libraries with -fmodules

Merge-request: KT-MR-8175
Merged-by: Vladimir Sukharev <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
Vladimir Sukharev
2023-01-13 07:33:42 +00:00
committed by Space Team
parent d85b23ebb9
commit 45de88abae
35 changed files with 302 additions and 58 deletions
@@ -0,0 +1 @@
error: comparison of incompatible enums 'pod1.ForwardEnumPOD' and 'pod2.ForwardEnumPOD' is always unsuccessful
@@ -0,0 +1,9 @@
import pod1.*
import pod2.*
fun box(): String {
if (pod1.varPOD != pod2.ForwardEnumPOD.Value2POD)
return "OK"
else
return "FAIL"
}
@@ -0,0 +1,6 @@
enum class ForwardEnumPOD private constructor(value: Int) : Enum<ForwardEnumPOD>, CEnum {
var value: ForwardEnumPOD
@Deprecated(level = DeprecationLevel.WARNING, message = "Will be removed.", replaceWith = ReplaceWith(imports = {})) fun byValue(value: Int): ForwardEnumPOD
var varPOD: ForwardEnumPOD
@CCall(id = "knifunptr_pod10_varPOD_getter") get
@CCall(id = "knifunptr_pod11_varPOD_setter") set
@@ -0,0 +1,2 @@
language = Objective-C
modules = forwardEnum1
@@ -0,0 +1,5 @@
enum class ForwardEnumPOD private constructor(value: Int) : Enum<ForwardEnumPOD>, CEnum {
@ConstantValue.Int(value = 0) enum entry Value1POD
@ConstantValue.Int(value = 1) enum entry Value2POD
var value: ForwardEnumPOD
@Deprecated(level = DeprecationLevel.WARNING, message = "Will be removed.", replaceWith = ReplaceWith(imports = {})) fun byValue(value: Int): ForwardEnumPOD
@@ -0,0 +1,2 @@
language = Objective-C
modules = forwardEnum2
@@ -0,0 +1,5 @@
#include <Foundation/NSObjCRuntime.h>
typedef NS_ENUM (int, ForwardEnumPOD); // Actual definition of the enum follows in another module `forwardEnum2`
ForwardEnumPOD varPOD;
@@ -0,0 +1,6 @@
framework module forwardEnum1 {
umbrella header "forwardEnum1.h"
export *
module * { export * }
}
@@ -0,0 +1,6 @@
#include <Foundation/NSObjCRuntime.h>
typedef NS_ENUM (int, ForwardEnumPOD) { // There was forward definition of this enum in another module `forwardEnum1`
Value1POD,
Value2POD
};
@@ -0,0 +1,6 @@
framework module forwardEnum2 {
umbrella header "forwardEnum2.h"
export *
module * { export * }
}
@@ -0,0 +1,15 @@
#ifndef _IOKIT_IOHIDLIB_H
#define _IOKIT_IOHIDLIB_H
typedef struct IOGPoint {
int x;
} IOGPoint;
typedef enum {
NX_OneButton,
} NXMouseButton;
extern int IOHIDPostEvent( IOGPoint location );
extern int IOHIDGetButtonEventNum( NXMouseButton button );
#endif /* ! _IOKIT_IOHIDLIB_H */
@@ -0,0 +1,8 @@
framework module explicitpod1 {
export *
explicit module explicitSubmodule {
header "explicitSubmodule.h"
export *
}
}
@@ -0,0 +1,8 @@
#import <forwardEnum/forwardEnum.h>
typedef NS_ENUM (long long, ForwardEnum) {
A,
B
};
ForwardEnum forwardEnumVar;
@@ -0,0 +1,5 @@
#include <Foundation/NSObjCRuntime.h>
typedef NS_ENUM (long long, ForwardEnum);
typedef NS_ENUM (long long, EnumWithoutConstant);
EnumWithoutConstant enumWithoutConstantVar;
@@ -0,0 +1,6 @@
framework module forwardEnum {
umbrella header "forwardEnum-umbrella.h"
export *
module * { export * }
}
@@ -0,0 +1,32 @@
package pod1 {
@CStruct(spelling = "struct { int x; }") class IOGPoint constructor(rawPtr: NativePtr /* = NativePtr */) : CStructVar {
var x: Int
@CStruct.MemberAt(offset = 0.toLong()) get
@CStruct.MemberAt(offset = 0.toLong()) set
@CStruct.VarType(align = 4, size = 4.toLong()) @Deprecated(level = DeprecationLevel.WARNING, message = "Use sizeOf<T>() or alignOf<T>() instead.", replaceWith = ReplaceWith(imports = {})) companion object : CStructVar.Type
}
enum class NXMouseButton private constructor(value: UInt) : Enum<NXMouseButton>, CEnum {
@ConstantValue.UInt(value = 0.toUInt()) enum entry NX_OneButton
override val value: UInt
class Var constructor(rawPtr: NativePtr /* = NativePtr */) : CEnumVar {
var value: NXMouseButton
@CEnumVarTypeSize(size = 4) @Deprecated(level = DeprecationLevel.WARNING, message = "Use sizeOf<T>() or alignOf<T>() instead.", replaceWith = ReplaceWith(imports = {})) companion object : CPrimitiveVar.Type
}
companion object {
@Deprecated(level = DeprecationLevel.WARNING, message = "Will be removed.", replaceWith = ReplaceWith(imports = {})) fun byValue(value: UInt): NXMouseButton
}
}
}
package pod1 {
@CCall(id = "knifunptr_pod11_IOHIDGetButtonEventNum") external fun IOHIDGetButtonEventNum(button: NXMouseButton): Int
@CCall(id = "knifunptr_pod10_IOHIDPostEvent") external fun IOHIDPostEvent(location: CValue<IOGPoint>): Int
}
@@ -0,0 +1,2 @@
language = Objective-C
modules = explicitpod1
@@ -0,0 +1,44 @@
package pod1 {
enum class EnumWithoutConstant private constructor(value: Long) : Enum<EnumWithoutConstant>, CEnum {
override val value: Long
class Var constructor(rawPtr: NativePtr /* = NativePtr */) : CEnumVar {
var value: EnumWithoutConstant
@CEnumVarTypeSize(size = 8) @Deprecated(level = DeprecationLevel.WARNING, message = "Use sizeOf<T>() or alignOf<T>() instead.", replaceWith = ReplaceWith(imports = {})) companion object : CPrimitiveVar.Type
}
companion object {
@Deprecated(level = DeprecationLevel.WARNING, message = "Will be removed.", replaceWith = ReplaceWith(imports = {})) fun byValue(value: Long): EnumWithoutConstant
}
}
enum class ForwardEnum private constructor(value: Long) : Enum<ForwardEnum>, CEnum {
@ConstantValue.Long(value = 0.toLong()) enum entry A
@ConstantValue.Long(value = 1.toLong()) enum entry B
override val value: Long
class Var constructor(rawPtr: NativePtr /* = NativePtr */) : CEnumVar {
var value: ForwardEnum
@CEnumVarTypeSize(size = 8) @Deprecated(level = DeprecationLevel.WARNING, message = "Use sizeOf<T>() or alignOf<T>() instead.", replaceWith = ReplaceWith(imports = {})) companion object : CPrimitiveVar.Type
}
companion object {
@Deprecated(level = DeprecationLevel.WARNING, message = "Will be removed.", replaceWith = ReplaceWith(imports = {})) fun byValue(value: Long): ForwardEnum
}
}
}
package pod1 {
var enumWithoutConstantVar: EnumWithoutConstant
@CCall(id = "knifunptr_pod10_enumWithoutConstantVar_getter") get
@CCall(id = "knifunptr_pod11_enumWithoutConstantVar_setter") set
var forwardEnumVar: ForwardEnum
@CCall(id = "knifunptr_pod12_forwardEnumVar_getter") get
@CCall(id = "knifunptr_pod13_forwardEnumVar_setter") set
}
@@ -0,0 +1,2 @@
language = Objective-C
modules = forwardEnum
@@ -120,6 +120,12 @@ public class CInteropFModulesTestGenerated extends AbstractNativeCInteropFModule
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/excludePod1Umbrella/");
}
@Test
@TestMetadata("explicitSubmodule")
public void testExplicitSubmodule() throws Exception {
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/explicitSubmodule/");
}
@Test
@TestMetadata("filterPod1")
public void testFilterPod1() throws Exception {
@@ -144,6 +150,12 @@ public class CInteropFModulesTestGenerated extends AbstractNativeCInteropFModule
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/filterPod1UmbrellaPod1A/");
}
@Test
@TestMetadata("forwardEnum")
public void testForwardEnum() throws Exception {
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/forwardEnum/");
}
@Test
@TestMetadata("full")
public void testFull() throws Exception {
@@ -24,6 +24,12 @@ public class CInteropKT39120TestGenerated extends AbstractNativeCInteropKT39120T
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CInterop/KT-39120/defs"), Pattern.compile("^([^_](.+))$"), null, false);
}
@Test
@TestMetadata("ForwardEnum")
public void testForwardEnum() throws Exception {
runTest("native/native.tests/testData/CInterop/KT-39120/defs/ForwardEnum/");
}
@Test
@TestMetadata("interModuleImport")
public void testInterModuleImport() throws Exception {
@@ -120,6 +120,12 @@ public class CInteropNoFModulesTestGenerated extends AbstractNativeCInteropNoFMo
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/excludePod1Umbrella/");
}
@Test
@TestMetadata("explicitSubmodule")
public void testExplicitSubmodule() throws Exception {
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/explicitSubmodule/");
}
@Test
@TestMetadata("filterPod1")
public void testFilterPod1() throws Exception {
@@ -144,6 +150,12 @@ public class CInteropNoFModulesTestGenerated extends AbstractNativeCInteropNoFMo
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/filterPod1UmbrellaPod1A/");
}
@Test
@TestMetadata("forwardEnum")
public void testForwardEnum() throws Exception {
runTest("native/native.tests/testData/CInterop/framework/frameworkDefs/forwardEnum/");
}
@Test
@TestMetadata("full")
public void testFull() throws Exception {
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
import java.io.File
abstract class AbstractNativeCInteropBaseTest : AbstractNativeSimpleTest() {
private val buildDir: File get() = testRunSettings.get<SimpleTestDirectories>().testBuildDir
internal val targets: KotlinNativeTargets get() = testRunSettings.get<KotlinNativeTargets>()
internal val kotlinNativeClassLoader: KotlinNativeClassLoader get() = testRunSettings.get<KotlinNativeClassLoader>()
@@ -17,6 +17,7 @@ import org.junit.jupiter.api.Tag
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.*
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEquals
import org.junit.jupiter.api.Assumptions
import kotlin.test.assertIs
@Tag("cinterop")
abstract class AbstractNativeCInteropKT39120Test : AbstractNativeCInteropBaseTest() {
@@ -51,10 +52,47 @@ abstract class AbstractNativeCInteropKT39120Test : AbstractNativeCInteropBaseTes
val expectedFiltered2Output = golden2File.readText()
val actualFiltered2Output = filterContentsOutput(contents2, " pod.Version|POD|class Pod")
assertEquals(StringUtilRt.convertLineSeparators(expectedFiltered2Output), StringUtilRt.convertLineSeparators(actualFiltered2Output))
val ktFile = testPathFull.resolve(DEFAULT_FILE_NAME)
if (ktFile.exists()) {
// Just compile "main.kt" with klib1 and klib2, without running resulting executable
val module = TestModule.Exclusive(DEFAULT_MODULE_NAME, emptySet(), emptySet()).apply {
files += TestFile.createCommitted(ktFile, this)
}
val compilationResult = compileToExecutable(
createTestCaseNoTestRun(module, TestCompilerArgs(listOf())),
klib1.asLibraryDependency(),
klib2.asLibraryDependency()
)
val expectedFailureTxtFile = testPathFull.resolve("expected.compilation.failure.txt")
if (expectedFailureTxtFile.exists()) {
assertIs<TestCompilationResult.CompilationToolFailure>(compilationResult)
val expectedFailureSubstring = expectedFailureTxtFile.readText()
val actualFailure = compilationResult.loggedData.toString()
assert(actualFailure.contains(expectedFailureSubstring)) {
"Expected failure substring:\n$expectedFailureSubstring\nActual failure logged data:\n$actualFailure"
}
} else {
compilationResult.assertSuccess()
}
}
}
private fun filterContentsOutput(contents: String, pattern: String) =
contents.split("\n").filter {
it.contains(Regex(pattern))
}.joinToString(separator = "\n")
private fun createTestCaseNoTestRun(module: TestModule.Exclusive, compilerArgs: TestCompilerArgs) = TestCase(
id = TestCaseId.Named(module.name),
kind = TestKind.STANDALONE_NO_TR,
modules = setOf(module),
freeCompilerArgs = compilerArgs,
nominalPackageName = PackageName.EMPTY,
checks = TestRunChecks.Default(testRunSettings.get<Timeouts>().executionTimeout),
extras = TestCase.NoTestRunnerExtras(".${module.name}")
).apply {
initialize(null, null)
}
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.konan.blackboxtest.CachesAutoBuildTest.Companion.TES
import org.jetbrains.kotlin.konan.blackboxtest.support.EnforcedHostTarget
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCompilerArgs
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.KLIB
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.CacheMode
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.KotlinNativeTargets
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.OptimizationMode
@@ -59,7 +60,7 @@ class CachesAutoBuildTest : AbstractNativeSimpleTest() {
)
),
*dependencies
)
).assertSuccess().resultingArtifact
private val autoCacheDir: File get() = buildDir.resolve("__auto_cache__")
private val cacheFlavor: String
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.konan.blackboxtest.support.EnforcedHostTarget
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCase
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.Executable
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.KLIB
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Success
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.TestExecutable
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.TestRunners
@@ -49,25 +51,23 @@ class InfrastructureDumpedTestListingTest : AbstractNativeSimpleTest() {
val barTestCase: TestCase = generateTestCaseWithSingleModule(rootDir.resolve("bar"))
val executableTestCase: TestCase
val executableCompilationResult: Success<out Executable>
val (executableTestCase: TestCase, executableCompilationResult: TestCompilationResult<out Executable>) =
if (fromSources) {
barTestCase to compileToExecutable(barTestCase, fooLibrary.asLibraryDependency())
} else {
val barCompilationResult: Success<out KLIB> = compileToLibrary(barTestCase, fooLibrary.asLibraryDependency())
val barLibrary: KLIB = barCompilationResult.resultingArtifact
if (fromSources) {
executableTestCase = barTestCase
executableCompilationResult = compileToExecutable(barTestCase, fooLibrary.asLibraryDependency())
} else {
val barCompilationResult: Success<out KLIB> = compileToLibrary(barTestCase, fooLibrary.asLibraryDependency())
val barLibrary: KLIB = barCompilationResult.resultingArtifact
val executableTestCase = generateTestCaseWithSingleModule(moduleDir = null) // No sources.
executableTestCase to compileToExecutable(
executableTestCase,
fooLibrary.asLibraryDependency(),
barLibrary.asIncludedLibraryDependency()
)
}
executableTestCase = generateTestCaseWithSingleModule(moduleDir = null) // No sources.
executableCompilationResult = compileToExecutable(
executableTestCase,
fooLibrary.asLibraryDependency(),
barLibrary.asIncludedLibraryDependency()
)
}
val executable: Executable = executableCompilationResult.resultingArtifact
val executableCompilationSuccess = executableCompilationResult.assertSuccess()
val executable: Executable = executableCompilationSuccess.resultingArtifact
// check that the test listing dumped during the compilation matches our expectations:
val testDumpFile = executable.testDumpFile
@@ -78,7 +78,7 @@ class InfrastructureDumpedTestListingTest : AbstractNativeSimpleTest() {
assertTrue(dumpedTestListing.isNotEmpty())
// parse test listing obtained from executable file with the help of --ktest_list_tests flag:
val testExecutable = TestExecutable.fromCompilationResult(executableTestCase, executableCompilationResult)
val testExecutable = TestExecutable.fromCompilationResult(executableTestCase, executableCompilationSuccess)
val extractedTestListing = TestRunners.extractTestNames(testExecutable, testRunSettings).toSet()
assertEquals(extractedTestListing, dumpedTestListing)
@@ -58,10 +58,9 @@ internal fun AbstractNativeSimpleTest.compileToExecutable(
sourcesDir: File,
freeCompilerArgs: TestCompilerArgs,
vararg dependencies: TestCompilationArtifact.KLIB
): TestCompilationArtifact.Executable {
): TestCompilationResult<out TestCompilationArtifact.Executable> {
val testCase: TestCase = generateTestCaseWithSingleModule(sourcesDir, freeCompilerArgs)
val compilationResult = compileToExecutable(testCase, dependencies.map { it.asLibraryDependency() })
return compilationResult.resultingArtifact
return compileToExecutable(testCase, dependencies.map { it.asLibraryDependency() })
}
internal fun AbstractNativeSimpleTest.compileToExecutable(testCase: TestCase, vararg dependencies: TestCompilationDependency<*>) =
@@ -109,7 +108,7 @@ private fun AbstractNativeSimpleTest.compileToLibrary(
private fun AbstractNativeSimpleTest.compileToExecutable(
testCase: TestCase,
dependencies: List<TestCompilationDependency<*>>
): TestCompilationResult.Success<out TestCompilationArtifact.Executable> {
): TestCompilationResult<out TestCompilationArtifact.Executable> {
val compilation = ExecutableCompilation(
settings = testRunSettings,
freeCompilerArgs = testCase.freeCompilerArgs,
@@ -118,7 +117,7 @@ private fun AbstractNativeSimpleTest.compileToExecutable(
dependencies = dependencies,
expectedArtifact = getExecutableArtifact()
)
return compilation.result.assertSuccess()
return compilation.result
}
private fun getLibraryArtifact(testCase: TestCase, dir: File) =