diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanCompilerTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanCompilerTask.kt deleted file mode 100644 index 8aa3716f7cb..00000000000 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanCompilerTask.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2010-2017 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 org.jetbrains.kotlin.gradle.plugin - -import org.gradle.api.DefaultTask -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.* -import java.io.File - -// TODO: form groups for tasks -// TODO: Make the task class nested for config with properties accessible for outer users. -open class KonanCompileTask: DefaultTask() { - - companion object { - const val COMPILER_MAIN = "org.jetbrains.kotlin.cli.bc.K2NativeKt" - } - - val COMPILER_JVM_ARGS: List - get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib") - val COMPILER_CLASSPATH: String - get() = "${project.konanHome}/konan/lib/" - - // Output artifact -------------------------------------------------------- - - lateinit var artifactName: String - - @OutputDirectory - lateinit var outputDir: File - internal set - - internal fun initialize(artifactName: String) { - dependsOn(project.konanCompilerDownloadTask) - this.artifactName = artifactName - outputDir = project.file("${project.konanCompilerOutputDir}/$artifactName") - } - - private val artifactSuffix = mapOf("program" to "kexe", "library" to "klib", "bitcode" to "bc") - - val artifactPath: String - get() = "${outputDir.absolutePath}/$artifactName.${artifactSuffix[produce]}" - - // Other compilation parameters ------------------------------------------- - - @InputFiles val inputFiles = mutableSetOf() - - @InputFiles val libraries = mutableSetOf() - @InputFiles val nativeLibraries = mutableSetOf() - - @Input var produce = "program" - internal set - - @Input var linkerOpts = mutableListOf() - internal set - - @Input var noStdLib = false - internal set - @Input var noMain = false - internal set - @Input var enableOptimization = false - internal set - @Input var enableAssertions = false - internal set - - @Optional @Input var target : String? = null - internal set - @Optional @Input var languageVersion : String? = null - internal set - @Optional @Input var apiVersion : String? = null - internal set - - // TODO: Is there a better way to rerun tasks when the compiler version changes? - @Input val konanVersion = project.konanVersion - - // Task action ------------------------------------------------------------ - - protected fun buildArgs() = mutableListOf().apply { - addArg("-output", artifactPath) - - addFileArgs("-library", libraries) - addFileArgs("-nativelibrary", nativeLibraries) - addArg("-produce", produce) - - addListArg("-linkerOpts", linkerOpts) - - addArgIfNotNull("-target", target) - addArgIfNotNull("-language-version", languageVersion) - addArgIfNotNull("-api-version", apiVersion) - - addKey("-nostdlib", noStdLib) - addKey("-nomain", noMain) - addKey("-opt", enableOptimization) - addKey("-ea", enableAssertions) - - inputFiles.forEach { - it.files.filter { it.name.endsWith(".kt") }.mapTo(this) { it.canonicalPath } - } - } - - @TaskAction - fun compile() { - project.file(outputDir).mkdirs() - - // TODO: Use compiler service. - project.javaexec { - with(it) { - main = COMPILER_MAIN - classpath = project.fileTree(COMPILER_CLASSPATH).apply { include("*.jar") } - jvmArgs(COMPILER_JVM_ARGS) - args(buildArgs().apply { logger.info("Compiler args: ${this.joinToString(separator = " ")}") }) - } - } - } - -} diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanInteropConfig.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanInteropConfig.kt deleted file mode 100644 index 2fdfa65698b..00000000000 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanInteropConfig.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2010-2017 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 org.jetbrains.kotlin.gradle.plugin - -import org.gradle.api.Named -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.file.FileCollection -import org.gradle.api.internal.project.ProjectInternal - -/** - * What we can: - * - * konanInterop { - * foo { - * defFile - * pkg - * target - * compilerOpts - * linkerOpts - * headers - * includeDirs - * linkFiles - * } - * - * // TODO: add configuration for konan compiler - * } - */ - -open class KonanInteropConfig( - val configName: String, - val project: ProjectInternal -): Named { - - override fun getName() = configName - - // Child tasks ------------------------------------------------------------ - - // Task to process the library and generate stubs - val generateStubsTask: KonanInteropTask = project.tasks.create( - "gen${name.capitalize()}InteropStubs", - KonanInteropTask::class.java - ) - - // Config and task to compile *.kt stubs in a *.bc library - internal val compileStubsConfig = KonanCompilerConfig("${name}InteropStubs", project, "compile").apply { - compilationTask.dependsOn(generateStubsTask) - outputDir("${project.konanInteropCompiledStubsDir}/$name") - produce("library") - inputFiles(project.fileTree(generateStubsTask.stubsDir).apply { builtBy(generateStubsTask) }) - } - val compileStubsTask = compileStubsConfig.compilationTask - - // DSL methods ------------------------------------------------------------ - - fun defFile(file: Any) = with(generateStubsTask) { - defFile = project.file(file) - } - - fun pkg(value: String) = with(generateStubsTask) { - pkg = value - } - - fun target(value: String) = with(generateStubsTask) { - generateStubsTask.target = value - compileStubsTask.target = value - } - - fun compilerOpts(vararg values: String) = with(generateStubsTask) { - compilerOpts.addAll(values) - } - - fun header(file: Any) = headers(file) - fun headers(vararg files: Any) = with(generateStubsTask) { - headers.add(project.files(files)) - } - fun headers(files: FileCollection) = with(generateStubsTask) { - headers.add(files) - } - - - fun includeDirs(vararg values: String) = with(generateStubsTask) { - compilerOpts.addAll(values.map { "-I$it" }) - } - - fun linker(value: String) = with(generateStubsTask) { - linker = value - } - - fun linkerOpts(vararg values: String) = linkerOpts(values.toList()) - fun linkerOpts(values: List) = with(generateStubsTask) { - linkerOpts.addAll(values) - } - - fun link(vararg files: Any) = with(generateStubsTask) { - linkFiles.add(project.files(files)) - } - fun link(files: FileCollection) = with(generateStubsTask) { - linkFiles.add(files) - } - -} diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanInteropTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanInteropTask.kt deleted file mode 100644 index b40fb9427c4..00000000000 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanInteropTask.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2010-2017 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 org.jetbrains.kotlin.gradle.plugin - -import org.gradle.api.DefaultTask -import org.gradle.api.Task -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.* -import java.io.File - - -open class KonanInteropTask: DefaultTask() { - - internal companion object { - const val INTEROP_MAIN = "org.jetbrains.kotlin.native.interop.gen.jvm.MainKt" - } - - init { - dependsOn(project.konanCompilerDownloadTask) - } - - internal val INTEROP_JVM_ARGS: List - get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib") - internal val INTEROP_CLASSPATH: String - get() = "${project.konanHome}/konan/lib/" - - - // Output directories ----------------------------------------------------- - - /** Directory with autogenerated interop stubs (*.kt) */ - @OutputDirectory - val stubsDir = project.file("${project.konanInteropStubsOutputDir}/$name") - - /** Directory with library bitcodes (*.bc) */ - @OutputDirectory - val libsDir = project.file("${project.konanInteropLibsOutputDir}/$name") - - // Interop stub generator parameters ------------------------------------- - - @Optional @InputFile var defFile: File? = null - internal set - @Optional @Input var target: String? = null - internal set - @Optional @Input var pkg: String? = null - internal set - @Optional @Input var linker: String? = null - internal set - - @Input val compilerOpts = mutableListOf() - @Input val linkerOpts = mutableListOf() - - // TODO: Check if we can use only one FileCollection instead of set. - @InputFiles val headers = mutableSetOf() - @InputFiles val linkFiles = mutableSetOf() - - @Input val konanVersion = project.konanVersion - - @TaskAction - fun exec() { - project.javaexec { - with(it) { - main = INTEROP_MAIN - classpath = project.fileTree(INTEROP_CLASSPATH).apply { include("*.jar") } - jvmArgs(INTEROP_JVM_ARGS) - environment("LIBCLANG_DISABLE_CRASH_RECOVERY", "1") - - args(buildArgs().apply { logger.info("Interop args: ${this.joinToString(separator = " ")}") }) - } - } - } - - protected fun buildArgs() = mutableListOf().apply { - addArg("-properties", "${project.konanHome}/konan/konan.properties") - addArg("-flavor", "native") - - addArg("-generated", stubsDir.canonicalPath) - addArg("-natives", libsDir.canonicalPath) - - addArgIfNotNull("-target", target) - addArgIfNotNull("-def", defFile?.canonicalPath) - addArgIfNotNull("-pkg", pkg) - addArgIfNotNull("-linker", linker) - - addFileArgs("-h", headers) - - compilerOpts.forEach { - addArg("-copt", it) - } - - val linkerOpts = mutableListOf().apply { addAll(linkerOpts) } - linkFiles.forEach { - linkerOpts.addAll(it.files.map { it.canonicalPath }) - } - linkerOpts.forEach { - addArg("-lopt", it) - } - } - -} diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanCompilerConfig.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileTask.kt similarity index 53% rename from tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanCompilerConfig.kt rename to tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileTask.kt index 822fef59224..cd9b1b471d1 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/KonanCompilerConfig.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileTask.kt @@ -16,9 +16,11 @@ package org.jetbrains.kotlin.gradle.plugin +import org.gradle.api.DefaultTask import org.gradle.api.Named import org.gradle.api.file.FileCollection import org.gradle.api.internal.project.ProjectInternal +import org.gradle.api.tasks.* import java.io.File /** @@ -62,9 +64,121 @@ import java.io.File */ + +// TODO: form groups for tasks +// TODO: Make the task class nested for config with properties accessible for outer users. +open class KonanCompileTask: DefaultTask() { + + companion object { + const val COMPILER_MAIN = "org.jetbrains.kotlin.cli.bc.K2NativeKt" + } + + val COMPILER_JVM_ARGS: List + get() = listOf("-Dkonan.home=${project.konanHome}", "-Djava.library.path=${project.konanHome}/konan/nativelib") + val COMPILER_CLASSPATH: String + get() = "${project.konanHome}/konan/lib/" + + // Output artifact -------------------------------------------------------- + + internal lateinit var artifactName: String + + @OutputDirectory + lateinit var outputDir: File + internal set + + internal fun init(artifactName: String) { + dependsOn(project.konanCompilerDownloadTask) + this.artifactName = artifactName + outputDir = project.file("${project.konanCompilerOutputDir}/$artifactName") + } + + private val artifactSuffix = mapOf("program" to "kexe", "library" to "klib", "bitcode" to "bc") + + val artifactPath: String + get() = "${outputDir.absolutePath}/$artifactName.${artifactSuffix[produce]}" + + // Other compilation parameters ------------------------------------------- + + @InputFiles val inputFiles = mutableSetOf() + + @InputFiles val libraries = mutableSetOf() + @InputFiles val nativeLibraries = mutableSetOf() + + @Input var produce = "program" + internal set + + @Input var linkerOpts = mutableListOf() + internal set + + @Input var noStdLib = false + internal set + @Input var noMain = false + internal set + @Input var enableOptimization = false + internal set + @Input var enableAssertions = false + internal set + + @Optional @Input var target : String? = null + internal set + @Optional @Input var languageVersion : String? = null + internal set + @Optional @Input var apiVersion : String? = null + internal set + + @Input var dumpParameters: Boolean = false + // TODO: Is there a better way to rerun tasks when the compiler version changes? + @Input val konanVersion = project.konanVersion + + // Task action ------------------------------------------------------------ + + protected fun buildArgs() = mutableListOf().apply { + addArg("-output", artifactPath) + + addFileArgs("-library", libraries) + addFileArgs("-nativelibrary", nativeLibraries) + addArg("-produce", produce) + + addListArg("-linkerOpts", linkerOpts) + + addArgIfNotNull("-target", target) + addArgIfNotNull("-language-version", languageVersion) + addArgIfNotNull("-api-version", apiVersion) + + addKey("-nostdlib", noStdLib) + addKey("-nomain", noMain) + addKey("-opt", enableOptimization) + addKey("-ea", enableAssertions) + + (if (inputFiles.isEmpty()) { + project.fileTree("${project.projectDir.canonicalPath}/src/main/kotlin") + } else { + inputFiles.flatMap { it.files } + }).filter { it.name.endsWith(".kt") }.mapTo(this) { it.canonicalPath } + } + + @TaskAction + fun compile() { + project.file(outputDir).mkdirs() + + if (dumpParameters) dumpProperties(this@KonanCompileTask) + + // TODO: Use compiler service. + project.javaexec { + with(it) { + main = COMPILER_MAIN + classpath = project.fileTree(COMPILER_CLASSPATH).apply { include("*.jar") } + jvmArgs(COMPILER_JVM_ARGS) + args(buildArgs().apply { logger.info("Compiler args: ${this.joinToString(separator = " ")}") }) + } + } + } + +} + // TODO: check debug outputs // TODO: Use +=/-= syntax for libraries and inputFiles -open class KonanCompilerConfig( +open class KonanCompileConfig( val configName: String, val project: ProjectInternal, taskNamePrefix: String = "compileKonan"): Named { @@ -74,12 +188,12 @@ open class KonanCompilerConfig( val compilationTask: KonanCompileTask = project.tasks.create( "$taskNamePrefix${configName.capitalize()}", KonanCompileTask::class.java - ) { it.initialize(this@KonanCompilerConfig.name) } + ) { it.init(this@KonanCompileConfig.name) } // DSL methods -------------------------------------------------- // TODO: Check if we copied all data or not - fun extendsFrom(anotherConfig: KonanCompilerConfig) = with(compilationTask) { + fun extendsFrom(anotherConfig: KonanCompileConfig) = with(compilationTask) { val anotherTask = anotherConfig.compilationTask outputDir(anotherTask.outputDir.absolutePath) @@ -97,7 +211,7 @@ open class KonanCompilerConfig( if (anotherTask.enableAssertions) enableAssertions() } - fun useInterop(interopConfig: KonanInteropConfig) { + private fun useInteropFromConfig(interopConfig: KonanInteropConfig) { val generateStubsTask = interopConfig.generateStubsTask val compileStubsTask = interopConfig.compileStubsTask @@ -111,7 +225,14 @@ open class KonanCompilerConfig( include("**/*.bc") }) } - fun useInterop(interop: String) = useInterop(project.konanInteropContainer.getByName(interop)) + + fun useInterops(interops: ArrayList) { + interops.forEach { useInteropFromConfig(project.konanInteropContainer.getByName(it)) } + } + + fun useInterop(interop: String) { + useInteropFromConfig(project.konanInteropContainer.getByName(interop)) + } // DSL. Input/output files @@ -185,4 +306,8 @@ open class KonanCompilerConfig( fun enableAssertions() = with(compilationTask) { enableAssertions = true } + + fun dumpParameters(value: Boolean) = with(compilationTask) { + dumpParameters = value + } } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/CompilerDownloadTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompilerDownloadTask.kt similarity index 81% rename from tools/kotlin-native-gradle-plugin/src/main/kotlin/CompilerDownloadTask.kt rename to tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompilerDownloadTask.kt index e76989dbb20..d5af67e012c 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/CompilerDownloadTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompilerDownloadTask.kt @@ -22,18 +22,19 @@ import org.gradle.api.tasks.TaskAction import org.jetbrains.kotlin.konan.DependencyDownloader import java.io.File -open class CompilerDownloadTask: DefaultTask() { +open class KonanCompilerDownloadTask : DefaultTask() { internal companion object { internal const val DOWNLOAD_URL = "http://download.jetbrains.com/kotlin/native" - private val KONAN_PARENT_DIR = "${System.getProperty("user.home")}/.konan" + internal val KONAN_PARENT_DIR = "${System.getProperty("user.home")}/.konan" internal fun simpleOsName(): String { val osName = System.getProperty("os.name") - return when (osName) { - "Mac OS X" -> "macos" - "Linux" -> "linux" + return when { + osName == "Mac OS X" -> "macos" + osName == "Linux" -> "linux" + osName.startsWith("Windows") -> "windows" else -> throw IllegalStateException("Unsupported platform: $osName") } } @@ -47,10 +48,9 @@ open class CompilerDownloadTask: DefaultTask() { return } try { - val konanCompiler = "kotlin-native-${simpleOsName()}-${project.konanVersion}" + val konanCompiler = project.konanCompilerName() logger.info("Downloading Kotlin Native compiler from $DOWNLOAD_URL/$konanCompiler into $KONAN_PARENT_DIR") DependencyDownloader(File(KONAN_PARENT_DIR), DOWNLOAD_URL, listOf(konanCompiler)).run() - project.extensions.extraProperties.set(KonanPlugin.KONAN_HOME_PROPERTY_NAME, "$KONAN_PARENT_DIR/$konanCompiler") } catch (e: RuntimeException) { throw GradleScriptException("Cannot download Kotlin Native compiler", e) } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanInteropTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanInteropTask.kt new file mode 100644 index 00000000000..08181ddec65 --- /dev/null +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanInteropTask.kt @@ -0,0 +1,222 @@ +/* + * Copyright 2010-2017 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 org.jetbrains.kotlin.gradle.plugin + +import org.gradle.api.DefaultTask +import org.gradle.api.Named +import org.gradle.api.file.FileCollection +import org.gradle.api.internal.project.ProjectInternal +import org.gradle.api.tasks.* +import java.io.File + +/** + * What we can: + * + * konanInterop { + * pkgName { + * defFile + * pkg + * target + * compilerOpts + * linkerOpts + * headers + * includeDirs + * linkFiles + * dumpParameters