diff --git a/kotlin-native/Interop/StubGenerator/build.gradle.kts b/kotlin-native/Interop/StubGenerator/build.gradle.kts index c901c4976bf..128b1857143 100644 --- a/kotlin-native/Interop/StubGenerator/build.gradle.kts +++ b/kotlin-native/Interop/StubGenerator/build.gradle.kts @@ -53,6 +53,31 @@ tasks { allWarningsAsErrors = true } } + + // Copy-pasted from Indexer build.gradle.kts. + withType().configureEach { + val projectsWithNativeLibs = listOf( + project(":kotlin-native:Interop:Indexer"), + project(":kotlin-native:Interop:Runtime") + ) + dependsOn(projectsWithNativeLibs.map { "${it.path}:nativelibs" }) + systemProperty("java.library.path", projectsWithNativeLibs.joinToString(File.pathSeparator) { + File(it.buildDir, "nativelibs").absolutePath + }) + val llvmDir = project.findProperty("llvmDir") + val libclangPath = "$llvmDir/" + if (org.jetbrains.kotlin.konan.target.HostManager.hostIsMingw) { + "bin/libclang.dll" + } else { + "lib/${System.mapLibraryName("clang")}" + } + systemProperty("kotlin.native.llvm.libclang", libclangPath) + systemProperty("kotlin.native.interop.stubgenerator.temp", File(buildDir, "stubGeneratorTestTemp")) + + // Set the konan.home property because we run the cinterop tool not from a distribution jar + // so it will not be able to determine this path by itself. + systemProperty("konan.home", project.project(":kotlin-native").projectDir) + environment["LIBCLANG_DISABLE_CRASH_RECOVERY"] = "1" + } } sourceSets { diff --git a/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/ExcludeFilterTests.kt b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/ExcludeFilterTests.kt new file mode 100644 index 00000000000..4afe74c5263 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/ExcludeFilterTests.kt @@ -0,0 +1,75 @@ +/* + * 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.native.interop.gen + +import org.jetbrains.kotlin.native.interop.indexer.getHeaderPaths +import kotlin.test.* + +class ExcludeFilterTests : InteropTestsBase() { + @Test + fun `excludeFilter smoke 0`() { + val files = TempFiles("excludeFilterSmoke0") + val header1 = files.file("header1.h", "") + val header2 = files.file("header2.h", "") + val header3 = files.file("header3.h", "") + val defFile = files.file("excludeSmoke.def", """ + headers = header1.h header2.h header3.h + headerFilter = ** + excludeFilter = header3.h + """.trimIndent()) + val library = buildNativeLibraryFrom(defFile, files.directory) + val headers = library.getHeaderPaths().ownHeaders + assertContains(headers, header1.absolutePath) + assertContains(headers, header2.absolutePath) + assertFalse(header3.absolutePath in headers) + } + + @Test + fun `excludeFilter smoke 1`() { + val files = TempFiles("excludeFilterSmoke1") + val header1 = files.file("header1.h", "") + val header2 = files.file("header2.h", "") + val header3 = files.file("header3.h", "") + val defFile = files.file("excludeSmoke.def", """ + headers = header1.h header2.h header3.h + headerFilter = ** + excludeFilter = header[2-3].h + """.trimIndent()) + val library = buildNativeLibraryFrom(defFile, files.directory) + val headers = library.getHeaderPaths().ownHeaders + assertContains(headers, header1.absolutePath) + assertFalse(header2.absolutePath in headers) + assertFalse(header3.absolutePath in headers) + } + + @Test + fun `excludeFilter empty`() { + val files = TempFiles("excludeFilterEmpty") + val header1 = files.file("header1.h", "") + val defFile = files.file("excludeSmoke.def", """ + headers = header1.h + headerFilter = ** + excludeFilter = + """.trimIndent()) + val library = buildNativeLibraryFrom(defFile, files.directory) + val headers = library.getHeaderPaths().ownHeaders + assertContains(headers, header1.absolutePath) + } + + @Test + fun `excludeFilter has higher priority than headerFilter`() { + val files = TempFiles("excludeFilterHasHigherPriority") + val header1 = files.file("header1.h", "") + val defFile = files.file("excludeSmoke.def", """ + headers = header1.h + headerFilter = header1.h + excludeFilter = header1.h + """.trimIndent()) + val library = buildNativeLibraryFrom(defFile, files.directory) + val headers = library.getHeaderPaths().ownHeaders + assertFalse(header1.absolutePath in headers) + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropTestsBase.kt b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropTestsBase.kt new file mode 100644 index 00000000000..4f5392c7ed3 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropTestsBase.kt @@ -0,0 +1,64 @@ +/* + * 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.native.interop.gen + +import kotlinx.cinterop.JvmCInteropCallbacks +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.util.DefFile +import org.jetbrains.kotlin.konan.util.NativeMemoryAllocator +import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform +import org.jetbrains.kotlin.native.interop.gen.jvm.buildNativeLibrary +import org.jetbrains.kotlin.native.interop.gen.jvm.prepareTool +import org.jetbrains.kotlin.native.interop.indexer.NativeLibrary +import org.jetbrains.kotlin.native.interop.indexer.getHeaderPaths +import org.jetbrains.kotlin.native.interop.tool.CInteropArguments +import kotlin.test.* +import java.io.File + +abstract class InteropTestsBase { + init { + System.load(System.getProperty("kotlin.native.llvm.libclang")) + } + + @BeforeTest + fun init() { + NativeMemoryAllocator.init() + JvmCInteropCallbacks.init() + } + + @AfterTest + fun dispose() { + JvmCInteropCallbacks.dispose() + NativeMemoryAllocator.dispose() + } + + class TempFiles(name: String) { + private val tempRootDir = System.getProperty("kotlin.native.interop.stubgenerator.temp") ?: System.getProperty("java.io.tmpdir") ?: "." + + val directory: File = File(tempRootDir, name).canonicalFile.also { + it.mkdirs() + } + + fun file(relativePath: String, contents: String): File = File(directory, relativePath).canonicalFile.apply { + parentFile.mkdirs() + writeText(contents) + } + } + + protected fun buildNativeLibraryFrom(defFile: File, headersDirectory: File): NativeLibrary { + val tool = prepareTool(HostManager.hostName, KotlinPlatform.NATIVE, runFromDaemon = true) + val cinteropArguments = CInteropArguments() + cinteropArguments.argParser.parse(arrayOf( + "-compiler-option", "-I${headersDirectory.absolutePath}" + )) + return buildNativeLibrary( + tool, + DefFile(defFile, tool.substitutions), + cinteropArguments, + ImportsImpl(emptyMap()) + ) + } +} \ No newline at end of file