diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileTask.kt index b67bed83046..c9cdc7208d1 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileTask.kt @@ -16,10 +16,9 @@ package org.jetbrains.kotlin.gradle.plugin -import org.gradle.api.DefaultTask import org.gradle.api.Named +import org.gradle.api.Project import org.gradle.api.file.FileCollection -import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.tasks.* import java.io.File @@ -187,7 +186,7 @@ open class KonanCompileTask: KonanTargetableTask() { // TODO: Use +=/-= syntax for libraries and inputFiles open class KonanCompileConfig( val configName: String, - val project: ProjectInternal, + val project: Project, taskNamePrefix: String = "compileKonan"): Named { override fun getName() = configName diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompilerDownloadTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompilerDownloadTask.kt index f6a9708845f..3525fb23a6f 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompilerDownloadTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompilerDownloadTask.kt @@ -20,7 +20,6 @@ import org.gradle.api.DefaultTask import org.gradle.api.GradleScriptException import org.gradle.api.tasks.TaskAction import org.jetbrains.kotlin.konan.DependencyDownloader -import org.jetbrains.kotlin.konan.target.* import java.io.File open class KonanCompilerDownloadTask : DefaultTask() { @@ -33,8 +32,8 @@ open class KonanCompilerDownloadTask : DefaultTask() { @TaskAction fun downloadAndExtract() { - if (!project.hasProperty(KonanPlugin.DOWNLOAD_COMPILER_PROPERTY_NAME)) { - val konanHome = project.property(KonanPlugin.KONAN_HOME_PROPERTY_NAME) + if (!project.hasProperty(KonanPlugin.PropertyNames.DOWNLOAD_COMPILER)) { + val konanHome = project.property(KonanPlugin.PropertyNames.KONAN_HOME) logger.info("Use a user-defined compiler path: $konanHome") return } 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 index c5c4a4cf77a..791ebc99da8 100644 --- 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 @@ -16,10 +16,9 @@ package org.jetbrains.kotlin.gradle.plugin -import org.gradle.api.DefaultTask import org.gradle.api.Named +import org.gradle.api.Project import org.gradle.api.file.FileCollection -import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.tasks.* import java.io.File @@ -145,7 +144,7 @@ open class KonanInteropTask: KonanTargetableTask() { open class KonanInteropConfig( val configName: String, - val project: ProjectInternal + val project: Project ): Named { override fun getName() = configName diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt index 628b523c7e0..3a40262f151 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanPlugin.kt @@ -16,15 +16,9 @@ package org.jetbrains.kotlin.gradle.plugin -import org.gradle.api.DefaultTask -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.Task +import org.gradle.api.* import org.gradle.api.file.FileCollection -import org.gradle.api.internal.AbstractNamedDomainObjectContainer -import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.tasks.TaskCollection -import org.gradle.internal.reflect.Instantiator import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import java.util.* import javax.inject.Inject @@ -38,8 +32,8 @@ import javax.inject.Inject // konanHome extension is set by downloadKonanCompiler task. internal val Project.konanHome: String get() { - assert(extensions.extraProperties.has(KonanPlugin.KONAN_HOME_PROPERTY_NAME)) - return extensions.extraProperties.get(KonanPlugin.KONAN_HOME_PROPERTY_NAME).toString() + assert(extensions.extraProperties.has(KonanPlugin.PropertyNames.KONAN_HOME)) + return extensions.extraProperties.get(KonanPlugin.PropertyNames.KONAN_HOME).toString() } internal val Project.konanBuildRoot get() = "${buildDir.canonicalPath}/konan" @@ -52,18 +46,21 @@ internal val Project.konanDefaultSrcDir get() = file("${projectDir.can internal fun Project.konanDefaultDefFile(interopName: String) = file("${projectDir.canonicalPath}/src/main/c_interop/$interopName.def") -internal val Project.konanArtifactsContainer: KonanArtifactsContainer - get() = extensions.getByName(KonanPlugin.COMPILER_EXTENSION_NAME) as KonanArtifactsContainer -internal val Project.konanInteropContainer: KonanInteropContainer - get() = extensions.getByName(KonanPlugin.INTEROP_EXTENSION_NAME) as KonanInteropContainer +@Suppress("UNCHECKED_CAST") +internal val Project.konanArtifactsContainer: NamedDomainObjectContainer + get() = extensions.getByName(KonanPlugin.ARTIFACTS_CONTAINER_NAME) as NamedDomainObjectContainer + +@Suppress("UNCHECKED_CAST") +internal val Project.konanInteropContainer: NamedDomainObjectContainer + get() = extensions.getByName(KonanPlugin.INTEROP_CONTAINER_NAME) as NamedDomainObjectContainer internal val Project.konanCompilerDownloadTask get() = tasks.getByName(KonanPlugin.KONAN_DOWNLOAD_TASK_NAME) internal val Project.konanVersion - get() = findProperty(KonanPlugin.KONAN_VERSION_PROPERTY_NAME) as String? ?: KonanPlugin.DEFAULT_KONAN_VERSION + get() = findProperty(KonanPlugin.PropertyNames.KONAN_VERSION) as String? ?: KonanPlugin.DEFAULT_KONAN_VERSION internal fun Project.targetIsRequested(target: String?): Boolean { - val targets = extensions.extraProperties.get(KonanPlugin.KONAN_BUILD_TARGETS).toString().trim().split(' ') + val targets = extensions.extraProperties.get(KonanPlugin.PropertyNames.KONAN_BUILD_TARGETS).toString().trim().split(' ') return (targets.contains(target) || targets.contains("all") || @@ -89,18 +86,12 @@ internal fun Project.konanCompilerName(): String = internal fun Project.konanCompilerDownloadDir(): String = KonanCompilerDownloadTask.KONAN_PARENT_DIR + "/" + project.konanCompilerName() -class KonanArtifactsContainer(val project: ProjectInternal): AbstractNamedDomainObjectContainer( - KonanCompileConfig::class.java, - project.gradle.services.get(Instantiator::class.java)) { - - override fun doCreate(name: String): KonanCompileConfig = KonanCompileConfig(name, project) +class KonanCompileConfigFactory(val project: Project): NamedDomainObjectFactory { + override fun create(name: String): KonanCompileConfig = KonanCompileConfig(name, project) } -class KonanInteropContainer(val project: ProjectInternal): AbstractNamedDomainObjectContainer( - KonanInteropConfig::class.java, - project.gradle.services.get(Instantiator::class.java)) { - - override fun doCreate(name: String): KonanInteropConfig = KonanInteropConfig(name, project) +class KonanInteropConfigFactory(val project: Project): NamedDomainObjectFactory { + override fun create(name: String): KonanInteropConfig = KonanInteropConfig(name, project) } // Useful extensions and functions --------------------------------------- @@ -182,52 +173,54 @@ internal fun dumpProperties(task: Task) { } } -private fun setDefaultInputs(project: Project) { - project.tasks.withType(KonanCompileTask::class.java).forEach { task -> - if (task.inputFiles.isEmpty()) { - project.konanDefaultSrcDir?.takeIf { it.exists() }?.let { srcDir -> - task.inputFiles.add(project.fileTree(srcDir)) +fun setDefaultInputs(project: Project) { + project.konanArtifactsContainer.asSequence() + .filter { it.compilationTask.inputFiles.isEmpty() } + .forEach { config -> + project.konanDefaultSrcDir?.takeIf { it.exists() }?.let { + config.inputDir(it.canonicalPath) + } } - } - } - project.tasks.withType(KonanInteropTask::class.java).forEach { task -> - if (task.defFile == null) { - project.konanDefaultDefFile(task.libName).takeIf { it.exists() }?.let { - task.defFile = it + project.konanInteropContainer.asSequence() + .filter { it.generateStubsTask.defFile == null } + .forEach { config -> + project.konanDefaultDefFile(config.name).takeIf { it.exists() }?.let { + config.defFile(it) + } } - } - } } class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderRegistry) - : Plugin { + : Plugin { + + object PropertyNames { + internal const val KONAN_HOME = "konan.home" + internal const val KONAN_VERSION = "konan.version" + internal const val KONAN_BUILD_TARGETS = "konan.build.targets" + + internal const val DOWNLOAD_COMPILER = "download.compiler" + } companion object { - internal const val COMPILER_EXTENSION_NAME = "konanArtifacts" - internal const val INTEROP_EXTENSION_NAME = "konanInterop" + internal const val ARTIFACTS_CONTAINER_NAME = "konanArtifacts" + internal const val INTEROP_CONTAINER_NAME = "konanInterop" internal const val KONAN_DOWNLOAD_TASK_NAME = "downloadKonanCompiler" - internal const val KONAN_HOME_PROPERTY_NAME = "konan.home" - internal const val KONAN_VERSION_PROPERTY_NAME = "konan.version" - internal const val KONAN_BUILD_TARGETS = "konan.build.targets" - internal val DEFAULT_KONAN_VERSION = Properties().apply { load(KonanPlugin::class.java.getResourceAsStream("/META-INF/gradle-plugins/konan.properties") ?: throw RuntimeException("Cannot find a properties file")) }.getProperty("default-konan-version") ?: throw RuntimeException("Cannot read the default compiler version") - - internal const val DOWNLOAD_COMPILER_PROPERTY_NAME = "DownloadCompiler" } /** * Looks for task with given name in the given project. * If such task isn't found, will create it. Returns created/found task. */ - private fun ProjectInternal.getTask(name: String): Task = getTasksByName(name, false).single() + private fun Project.getTask(name: String): Task = getTasksByName(name, false).single() - private fun ProjectInternal.getOrCreateTask(name: String): Task { - var tasks = getTasksByName(name, false) + private fun Project.getOrCreateTask(name: String): Task { + val tasks = getTasksByName(name, false) assert(tasks.size <= 1) return if (tasks.isEmpty()) { this.tasks.create(name, DefaultTask::class.java) @@ -237,28 +230,38 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR } // TODO: Create default config? what about test sources? - override fun apply(project: ProjectInternal?) { + override fun apply(project: Project?) { if (project == null) { return } registry.register(KonanToolingModelBuilder) project.plugins.apply("base") + // Create necessary tasks and extensions. project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, KonanCompilerDownloadTask::class.java) - project.extensions.add(COMPILER_EXTENSION_NAME, KonanArtifactsContainer(project)) - project.extensions.add(INTEROP_EXTENSION_NAME, KonanInteropContainer(project)) - if (!project.extensions.extraProperties.has(KonanPlugin.KONAN_HOME_PROPERTY_NAME)) { - project.extensions.extraProperties.set(KonanPlugin.KONAN_HOME_PROPERTY_NAME, project.konanCompilerDownloadDir()) - project.extensions.extraProperties.set(DOWNLOAD_COMPILER_PROPERTY_NAME, true) + project.extensions.add(ARTIFACTS_CONTAINER_NAME, + project.container(KonanCompileConfig::class.java, KonanCompileConfigFactory(project))) + project.extensions.add(INTEROP_CONTAINER_NAME, + project.container(KonanInteropConfig::class.java, KonanInteropConfigFactory(project))) + + // Set additional project properties like konan.home, konan.build.targets etc. + if (!project.extensions.extraProperties.has(PropertyNames.KONAN_HOME)) { + project.extensions.extraProperties.set(PropertyNames.KONAN_HOME, project.konanCompilerDownloadDir()) + project.extensions.extraProperties.set(PropertyNames.DOWNLOAD_COMPILER, true) } - if (!project.extensions.extraProperties.has(KonanPlugin.KONAN_BUILD_TARGETS)) { - project.extensions.extraProperties.set(KonanPlugin.KONAN_BUILD_TARGETS, project.host) + if (!project.extensions.extraProperties.has(PropertyNames.KONAN_BUILD_TARGETS)) { + project.extensions.extraProperties.set(PropertyNames.KONAN_BUILD_TARGETS, project.host) } + + // Create and set up aggregate building tasks. val compileKonanTask = project.getOrCreateTask("compileKonan").apply { dependsOn(project.supportedCompileTasks) } project.getTask("build").apply { dependsOn(compileKonanTask) } + + // Add default source paths after project evaluation. project.afterEvaluate(::setDefaultInputs) + // Create task to run supported executables. project.getOrCreateTask("run").apply { dependsOn(project.getTask("build")) doLast { diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanTargetableTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanTargetableTask.kt index 1b5ee26b3b7..4efb3051dfe 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanTargetableTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanTargetableTask.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.gradle.plugin import org.gradle.api.DefaultTask import org.gradle.api.Project -import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.tasks.* import org.jetbrains.kotlin.konan.target.* import org.jetbrains.kotlin.konan.target.KonanTarget.*