From 1eb951749dff0d0f8642ff6a1f96e5743db56729 Mon Sep 17 00:00:00 2001 From: Vasily Levchenko Date: Fri, 2 Jul 2021 06:36:23 +0200 Subject: [PATCH] [build][kotlin-native] native compiler embeddable --- .../build.gradle.kts | 89 +++++++++++++++++++ .../projects/serialization/serialization.kt | 14 +++ .../testData/projects/smoke/Smoke.kt | 21 +++++ .../CompilerEmbeddableSmokeTests.kt | 79 ++++++++++++++++ .../compilerRunner/nativeToolRunners.kt | 1 + settings.gradle | 2 + 6 files changed, 206 insertions(+) create mode 100644 kotlin-native/prepare/kotlin-native-embeddable-compiler/build.gradle.kts create mode 100644 kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/serialization/serialization.kt create mode 100644 kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/smoke/Smoke.kt create mode 100644 kotlin-native/prepare/kotlin-native-embeddable-compiler/tests/kotlin/org/jetbrains/kotlin/native/compiler/embeddable/CompilerEmbeddableSmokeTests.kt diff --git a/kotlin-native/prepare/kotlin-native-embeddable-compiler/build.gradle.kts b/kotlin-native/prepare/kotlin-native-embeddable-compiler/build.gradle.kts new file mode 100644 index 00000000000..fcec723b995 --- /dev/null +++ b/kotlin-native/prepare/kotlin-native-embeddable-compiler/build.gradle.kts @@ -0,0 +1,89 @@ +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.KonanTarget.MACOS_ARM64 +import org.jetbrains.kotlin.kotlinNativeDist + +plugins { + kotlin("jvm") +} + +val testCompilationClasspath by configurations.creating +val testCompilerClasspath by configurations.creating { + isCanBeConsumed = false + extendsFrom(configurations["runtimeElements"]) + attributes { + attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME)) + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY)) + } +} + +repositories{ + mavenCentral() +} + +val kotlinNativeEmbedded by configurations.creating +val testPlugin by configurations.creating +val testPluginRuntime by configurations.creating + +fun DependencyHandlerScope.testPluginRuntime(any: Any) { + val notation = any as? String ?: return add(testPluginRuntime.name, any){} + val (group, artifact, version) = notation.split(":") + val platformName = HostManager.host.name + val gradlePlatformName = platformName.replace("_", "") + return add(testPluginRuntime.name, "$group:$artifact-$gradlePlatformName:$version") { + isTransitive = false + attributes { + attribute(Attribute.of("artifactType", String::class.java), "org.jetbrains.kotlin.klib") + attribute(Attribute.of("org.gradle.status", String::class.java), "release") + attribute(Attribute.of("org.jetbrains.kotlin.native.target", String::class.java), platformName) + attribute(Attribute.of("org.jetbrains.kotlin.platform.type", String::class.java), "native") + attribute(Usage.USAGE_ATTRIBUTE, objects.named("kotlin-api")) + } + } +} + +dependencies { + kotlinNativeEmbedded(project(":kotlin-native:Interop:Runtime")) + kotlinNativeEmbedded(project(":kotlin-native:Interop:Indexer")) + kotlinNativeEmbedded(project(":kotlin-native:Interop:StubGenerator")) + kotlinNativeEmbedded(project(":kotlin-native:Interop:Skia")) + kotlinNativeEmbedded(project(":kotlin-native:backend.native")) + kotlinNativeEmbedded(project(":kotlin-native:utilities:cli-runner")) + kotlinNativeEmbedded(project(":kotlin-native:utilities:basic-utils")) + kotlinNativeEmbedded(project(":kotlin-native:klib")) + kotlinNativeEmbedded(project(":kotlin-native:endorsedLibraries:kotlinx.cli", "jvmRuntimeElements")) + kotlinNativeEmbedded(project(":kotlin-compiler", configuration = "runtimeJar")) + testImplementation(commonDep("junit:junit")) + testImplementation(project(":kotlin-test:kotlin-test-junit")) +} + +val compiler = embeddableCompiler("kotlin-native-compiler-embeddable") { + from(kotlinNativeEmbedded) + /** + * this jar distributed through kotlin-native distribution, but not with maven. + */ + archiveVersion.set("") + mergeServiceFiles() +} + +val runtimeJar = runtimeJar(compiler) { + exclude("com/sun/jna/**") + mergeServiceFiles() +} + + +kotlin.sourceSets["test"].kotlin.srcDir("tests/kotlin") + + +projectTest { + /** + * It's expected that test should be executed on CI, but currently this project under `kotlin.native.enabled` + */ + dependsOn(runtimeJar) + val runtimeJarPathProvider = project.provider { runtimeJar.get().outputs.files.asPath } + doFirst { + systemProperty("compilerClasspath", runtimeJarPathProvider.get()) + systemProperty("kotlin.native.home", kotlinNativeDist) + } +} + + diff --git a/kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/serialization/serialization.kt b/kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/serialization/serialization.kt new file mode 100644 index 00000000000..3bfe933563b --- /dev/null +++ b/kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/serialization/serialization.kt @@ -0,0 +1,14 @@ +package serialization + +import kotlinx.serialization.* +import kotlinx.serialization.json.* + +@Serializable +data class Data(val number: Int, val english: String, val germany:String) + +fun main() { + Data(42, "forty two", "zweiundvierzig").let { + println(Json.encodeToString(it)) + } +} + diff --git a/kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/smoke/Smoke.kt b/kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/smoke/Smoke.kt new file mode 100644 index 00000000000..62ff5bd7576 --- /dev/null +++ b/kotlin-native/prepare/kotlin-native-embeddable-compiler/testData/projects/smoke/Smoke.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoke + +fun main(args: Array) { + println(args) +} diff --git a/kotlin-native/prepare/kotlin-native-embeddable-compiler/tests/kotlin/org/jetbrains/kotlin/native/compiler/embeddable/CompilerEmbeddableSmokeTests.kt b/kotlin-native/prepare/kotlin-native-embeddable-compiler/tests/kotlin/org/jetbrains/kotlin/native/compiler/embeddable/CompilerEmbeddableSmokeTests.kt new file mode 100644 index 00000000000..fd3d4ecb61a --- /dev/null +++ b/kotlin-native/prepare/kotlin-native-embeddable-compiler/tests/kotlin/org/jetbrains/kotlin/native/compiler/embeddable/CompilerEmbeddableSmokeTests.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2021 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.compiler.embeddable + +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import java.io.File +import java.io.FileNotFoundException +import java.io.InputStream +import kotlin.test.assertEquals + + +private val COMPILER_CLASS_FQN = "org.jetbrains.kotlin.cli.bc.K2Native" + +class CompilerSmokeTest { + + private val _workingDir: TemporaryFolder = TemporaryFolder() + + @Rule + fun getWorkingDir(): TemporaryFolder = _workingDir + + private val javaExecutable = File(File(System.getProperty("java.home"), "bin"), "java") + + private val compilerClasspath: List by lazy { + filesFromProp("compilerClasspath", "kotlin-native-compiler-embeddable.jar") + } + + private fun filesFromProp(propName: String, vararg defaultPaths: String): List = + (System.getProperty(propName)?.split(File.pathSeparator) ?: defaultPaths.asList()).map { + File(it).takeIf(File::exists) + ?: throw FileNotFoundException("cannot find ($it)") + } + + @Test + fun testSmoke() { + val (out, code) = runCompiler("-e", "smoke.main", File("testData/projects/smoke/Smoke.kt").absolutePath) + assertEquals(0, code, "compilation failed: $out\n") + } + + private fun createProcess(vararg cmd: String, projectDir: File): Process { + val builder = ProcessBuilder(*cmd) + builder.directory(projectDir) + builder.redirectErrorStream(true) + return builder.start() + } + + private fun runCompiler(vararg arguments: String): Pair { + val cmd = listOf( + javaExecutable.absolutePath, + "-Djava.awt.headless=true", + "-Dkotlin.native.home=${System.getProperty("kotlin.native.home")}", + "-cp", + compilerClasspath.joinToString(File.pathSeparator), + COMPILER_CLASS_FQN + ) + arguments + val proc = createProcess(*cmd.toTypedArray(), projectDir = _workingDir.root) + return readOutput(proc) + } + + private fun readOutput(process: Process): Pair { + fun InputStream.readFully(): String { + val text = reader().readText() + close() + return text + } + + val stdout = process.inputStream!!.readFully() + System.out.println(stdout) + val stderr = process.errorStream!!.readFully() + System.err.println(stderr) + + val result = process.waitFor() + return stdout to result + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt index 546c35e700d..832822f0526 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.isAtLeast import org.jetbrains.kotlin.gradle.tasks.CacheBuilder import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.properties.resolvablePropertyString import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget diff --git a/settings.gradle b/settings.gradle index 6d9bc5b84a2..fccee42abf1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -641,4 +641,6 @@ if (buildProperties.isKotlinNativeEnabled) { include ':kotlin-native:platformLibs' include ':kotlin-native:libclangext' include ':kotlin-native:backend.native:tests' + include ":kotlin-native-compiler-embeddable" + project(":kotlin-native-compiler-embeddable").projectDir = "$rootDir/kotlin-native/prepare/kotlin-native-embeddable-compiler" as File }