diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileConfig.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileConfig.kt index ea209aa2f8f..030df0c773b 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileConfig.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanCompileConfig.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.gradle.plugin -import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.file.FileCollection import org.gradle.api.internal.project.ProjectInternal @@ -52,13 +51,8 @@ abstract class KonanCompileConfig(name: String, override fun nativeLibraries(vararg libs: Any) = forEach { it.nativeLibraries(*libs) } override fun nativeLibraries(libs: FileCollection) = forEach { it.nativeLibraries(libs) } - override fun expectedBy(parameters: Map) = forEach { it.expectedBy(parameters) } - override fun expectedBy(commonProject: String) = forEach { it.expectedBy(commonProject) } - override fun expectedBy(commonProject: Project) = forEach { it.expectedBy(commonProject) } - override fun expectedBy(commonProject: String, sourceSetName: String) = - forEach { it.expectedBy(commonProject, sourceSetName) } - override fun expectedBy(commonProject: Project, sourceSetName: String) = - forEach { it.expectedBy(commonProject, sourceSetName) } + override fun commonSourceSet(sourceSetName: String) = forEach { it.commonSourceSet(sourceSetName) } + override fun enableMultiplatform(flag: Boolean) = forEach { it.enableMultiplatform(flag) } override fun linkerOpts(values: List) = forEach { it.linkerOpts(values) } override fun linkerOpts(vararg values: String) = forEach { it.linkerOpts(*values) } 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 09371b19c4f..8f66da147cc 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 @@ -309,5 +309,8 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR } } } + + // Enable multiplatform support + project.pluginManager.apply(KotlinNativePlatformPlugin::class.java) } } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanSpecs.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanSpecs.kt index 74b24bd3bf1..ae2ac223f31 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanSpecs.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KonanSpecs.kt @@ -52,12 +52,9 @@ interface KonanCompileSpec: KonanBuildingSpec { fun nativeLibraries(vararg libs: Any) fun nativeLibraries(libs: FileCollection) - // DSL. Mutliplatform projects - fun expectedBy(parameters: Map) - fun expectedBy(commonProject: String, sourceSetName: String) - fun expectedBy(commonProject: String) - fun expectedBy(commonProject: Project) - fun expectedBy(commonProject: Project, sourceSetName: String) + // DSL. Multiplatform projects + fun enableMultiplatform(flag: Boolean) + fun commonSourceSet(sourceSetName: String) // DSL. Other parameters. diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinNativePlatformPlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinNativePlatformPlugin.kt new file mode 100644 index 00000000000..b8843324561 --- /dev/null +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinNativePlatformPlugin.kt @@ -0,0 +1,58 @@ +package org.jetbrains.kotlin.gradle.plugin + +import org.gradle.api.GradleException +import org.gradle.api.Project +import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.tasks.SourceSetContainer +import org.jetbrains.kotlin.gradle.plugin.tasks.KonanCompileTask + +open class KotlinNativePlatformPlugin: KotlinPlatformImplementationPluginBase("native") { + + protected val commonProjects = arrayListOf() + + override fun apply(project: Project) { + val expectedByConfig = project.configurations.create(EXPECTED_BY_CONFIG_NAME) + expectedByConfig.isTransitive = false + expectedByConfig.dependencies.whenObjectAdded { dep -> + if (dep is ProjectDependency) { + addCommonProject(dep.dependencyProject, project) + } else { + throw GradleException("$project '${expectedByConfig.name}' dependency is not a project: $dep") + } + } + } + + protected fun addCommonProject(commonProject: Project, platformProject: Project) { + commonProjects.add(commonProject) + if (commonProjects.size > 1) { + throw GradleException("Platform project $platformProject has more than one " + + "'$EXPECTED_BY_CONFIG_NAME' dependency: ${commonProjects.joinToString()}") + } + + commonProject.whenEvaluated { + if (!commonProject.pluginManager.hasPlugin("kotlin-platform-common")) { + throw GradleException("Platform project $platformProject has an " + + "'$EXPECTED_BY_CONFIG_NAME' dependency to non-common project $commonProject") + } + + platformProject.tasks + .withType(KonanCompileTask::class.java) + .filter { it.enableMultiplatform } + .forEach { task: KonanCompileTask -> + val commonSourceSet = commonProject.sourceSets.findByName(task.commonSourceSet) ?: + throw GradleException("Cannot find a source set with name '${task.commonSourceSet}' " + + "in a common project '${commonProject.path}' " + + "for an artifact '${task.artifactName}' " + + "in a platform project '${platformProject.path}'") + + commonSourceSet.kotlin!!.srcDirs.forEach { + task.commonSrcDir(it) + } + } + } + } + + protected val Project.sourceSets: SourceSetContainer + get() = convention.getPlugin(JavaPluginConvention::class.java).sourceSets +} diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompileTask.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompileTask.kt index 3e45f2e4ba8..adb4a690a61 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompileTask.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/tasks/KonanCompileTask.kt @@ -16,12 +16,7 @@ package org.jetbrains.kotlin.gradle.plugin.tasks -import org.gradle.api.GradleException -import org.gradle.api.Project import org.gradle.api.file.FileCollection -import org.gradle.api.file.SourceDirectorySet -import org.gradle.api.internal.HasConvention -import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.tasks.* import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.konan.target.CompilerOutputKind @@ -54,15 +49,15 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { override val artifactPrefix: String @Internal get() = produce.kind.prefix(konanTarget) - // Mutliplatform support -------------------------------------------------- + // Multiplatform support -------------------------------------------------- - internal var commonProject: Project? = null - internal set - @Internal get + @Input var commonSourceSet = "main" - @InputFiles val commonSrcFiles = mutableSetOf() + @Internal var enableMultiplatform = false - @Internal protected val defaultSourceSetName = "main" + internal val commonSrcFiles_ = mutableSetOf() + val commonSrcFiles: Collection + @InputFiles get() = if (enableMultiplatform) commonSrcFiles_ else emptyList() // Other compilation parameters ------------------------------------------- @@ -125,7 +120,7 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { addKey("-ea", enableAssertions) addKey("--time", measureTime) addKey("-nodefaultlibs", noDefaultLibs) - addKey("-Xmulti-platform", commonProject != null) + addKey("-Xmulti-platform", enableMultiplatform) addAll(extraOpts) @@ -158,49 +153,17 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { // DSL. Multiplatform projects. - override fun expectedBy(parameters: Map) { - val project = parameters[PROJECT_KEY] ?: - throw GradleException("A project should be passed to expectedBy method") - val sourceSetName = parameters[SOURCE_SET_KEY] ?: defaultSourceSetName - - if (sourceSetName !is String) { - throw GradleException("sourceSet parameter of expectedBy should be String") - } - - when (project) { - is Project -> expectedBy(project, sourceSetName) - is String -> expectedBy(project, sourceSetName) - else -> throw GradleException("project parameter of expectedBy should be String") - } + override fun enableMultiplatform(flag: Boolean) { + enableMultiplatform = flag } - override fun expectedBy(commonProject: String, sourceSetName: String) = expectedBy(project.project(commonProject), sourceSetName) - override fun expectedBy(commonProject: String) = expectedBy(commonProject, defaultSourceSetName) - override fun expectedBy(commonProject: Project) = expectedBy(commonProject, defaultSourceSetName) - override fun expectedBy(commonProject: Project, sourceSetName: String) { - if (this.commonProject != null) { - throw GradleException("Artifact ${artifactName} has more then one expectedBy dependency") - } + override fun commonSourceSet(sourceSetName: String) { + commonSourceSet = sourceSetName + enableMultiplatform(true) + } - this.commonProject = commonProject - - commonProject.whenEvaluated { - if (!commonProject.pluginManager.hasPlugin("kotlin-platform-common")) { - throw GradleException("Artifact ${artifactName} of project ${this@KonanCompileTask.project.path} " + - "has an expectedBy dependency to a non-common project ${this.path}") - } - - val commonSourceSet = commonProject.sourceSets.let { - it.findByName(sourceSetName) ?: run { - logger.warn("Cannot find a source set ${sourceSetName} in project ${this.path}. " + - "Use the default one: ${defaultSourceSetName}") - it.getByName(defaultSourceSetName) - } - } - commonSourceSet.kotlin!!.srcDirs.forEach { - commonSrcFiles.add(directoryToKt(it)) - } - } + internal fun commonSrcDir(dir: Any) { + commonSrcFiles_.add(directoryToKt(dir)) } // DSL. Other parameters. @@ -238,37 +201,6 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec { measureTime = flag } // endregion - - // Some functions from Kotlin Gradle plugin. - protected fun Project.whenEvaluated(fn: Project.() -> Unit) { - if (state.executed) { - fn() - } else { - afterEvaluate { it.fn() } - } - } - - protected val Project.sourceSets: SourceSetContainer - get() = convention.getPlugin(JavaPluginConvention::class.java).sourceSets - - protected val SourceSet.kotlin: SourceDirectorySet? - get() { - // Access through reflection, because another project's KotlinSourceSet might be loaded - // by a different class loader: - val convention = (getConvention("kotlin") ?: getConvention("kotlin2js")) ?: return null - val kotlinSourceSetIface = convention.javaClass.interfaces.find { it.name == KotlinSourceSet::class.qualifiedName } - val getKotlin = kotlinSourceSetIface?.methods?.find { it.name == "getKotlin" } ?: return null - return getKotlin(convention) as? SourceDirectorySet - } - - protected fun Any.getConvention(name: String): Any? = - (this as HasConvention).convention.plugins[name] - - companion object { - const val PROJECT_KEY = "project" - const val SOURCE_SET_KEY = "sourceSet" - } - } open class KonanCompileProgramTask: KonanCompileTask() {