diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt index 7f4ae14db36..8402cfdecd3 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/AbstractKotlinNativeBinary.kt @@ -70,6 +70,7 @@ abstract class AbstractKotlinNativeBinary( val sourceSet: KotlinNativeSourceSet get() = component.sources + val buildType: KotlinNativeBuildType get() = identity.buildType open val debuggable: Boolean get() = identity.isDebuggable open val optimized: Boolean get() = identity.isOptimized diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeVariantIdentity.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeVariantIdentity.kt index 9ccad52fa0b..926786f4e06 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeVariantIdentity.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/internal/KotlinNativeVariantIdentity.kt @@ -7,26 +7,25 @@ import org.gradle.language.cpp.internal.NativeVariantIdentity import org.jetbrains.kotlin.konan.target.KonanTarget open class KotlinNativeVariantIdentity( - name: String, - baseName: Provider, - group: Provider, - version: Provider, - val konanTarget: KonanTarget, - debuggable: Boolean, - optimized: Boolean, - linkUsage: UsageContext?, - runtimeUsage: UsageContext?, - objects: ObjectFactory + name: String, + baseName: Provider, + group: Provider, + version: Provider, + val konanTarget: KonanTarget, + val buildType: KotlinNativeBuildType, + linkUsage: UsageContext?, + runtimeUsage: UsageContext?, + objects: ObjectFactory ) : NativeVariantIdentity( - name, - baseName, - group, - version, - debuggable, - optimized, - konanTarget.getGradleOSFamily(objects), - linkUsage, - runtimeUsage + name, + baseName, + group, + version, + buildType.debuggable, + buildType.optimized, + konanTarget.getGradleOSFamily(objects), + linkUsage, + runtimeUsage ) { val targetPlatform = DefaultKotlinNativePlatform(konanTarget) } \ No newline at end of file diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt index aba344ff442..c5131dddc9a 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativeBasePlugin.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlin.gradle.plugin.experimental.plugins import org.gradle.api.DefaultTask import org.gradle.api.Plugin +import org.gradle.api.Task import org.gradle.api.component.SoftwareComponentContainer import org.gradle.api.file.DirectoryProperty import org.gradle.api.internal.FeaturePreviews @@ -59,16 +60,28 @@ class KotlinNativeBasePlugin: Plugin { private val KonanTarget.canRunOnHost: Boolean get() = this == HostManager.host + private fun addCompilationTasks( tasks: TaskContainer, components: SoftwareComponentContainer, buildDirectory: DirectoryProperty, providers: ProviderFactory ) { + val assembleTask = tasks.getByName(LifecycleBasePlugin.ASSEMBLE_TASK_NAME) + val typeToAssemble = mutableMapOf() + val targetToAssemble = mutableMapOf() + + fun TaskContainer.createSpecialAssembleTask(name: String, description: String) = create(name) { + it.group = BasePlugin.BUILD_GROUP + it.description = description + assembleTask.dependsOn(it) + } + components.withType(AbstractKotlinNativeBinary::class.java) { binary -> val names = binary.names val target = binary.konanTarget val kind = binary.kind + val buildType = binary.buildType val compileTask = tasks.create( names.getCompileTaskName(LANGUAGE_NAME), @@ -95,6 +108,7 @@ class KotlinNativeBasePlugin: Plugin { } if (binary is KotlinNativeTestExecutableImpl) { + // Generate a task for test execution. val taskName = binary.names.getTaskName("run") val testTask = if (target.canRunOnHost) { tasks.createRunTestTask(taskName, binary, compileTask) @@ -104,6 +118,23 @@ class KotlinNativeBasePlugin: Plugin { tasks.createDummyTestTask(taskName, target) } binary.runTask.set(testTask) + } else { + // Add dependency for assemble tasks. + targetToAssemble.getOrPut(target) { + tasks.createSpecialAssembleTask( + "assembleAll${target.name.capitalize()}", + "Compiles all Kotlin/Native binaries for target '${target.name}'" + ) + }.dependsOn(compileTask) + + typeToAssemble.getOrPut(buildType) { + val buildTypeName = buildType.name + tasks.createSpecialAssembleTask( + "assembleAll${buildTypeName.capitalize()}", + "Compiles all ${buildTypeName} Kotlin/Native binaries for all targets" + ) + }.dependsOn(compileTask) + } } } @@ -146,7 +177,6 @@ class KotlinNativeBasePlugin: Plugin { checkGradleVersion() addCompilerDownloadingTask() - // Create compile tasks addCompilationTasks(tasks, components, layout.buildDirectory, providers) } diff --git a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt index e63306cd011..4197a25c645 100644 --- a/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt +++ b/tools/kotlin-native-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/experimental/plugins/KotlinNativePlugin.kt @@ -105,8 +105,7 @@ class KotlinNativePlugin @Inject constructor(val attributesFactory: ImmutableAtt variantName, component.baseName, group, version, target, - buildType.debuggable, - buildType.optimized, + buildType, linkUsageContext, runtimeUsageContext, objects @@ -153,8 +152,7 @@ class KotlinNativePlugin @Inject constructor(val attributesFactory: ImmutableAtt variantName, component.getBaseName(), group, version, target, - buildType.debuggable, - buildType.optimized, + buildType, null, null, objects @@ -169,6 +167,25 @@ class KotlinNativePlugin @Inject constructor(val attributesFactory: ImmutableAtt } } + private fun Project.setUpMavenPublish() = pluginManager.withPlugin("maven-publish") { + val publishingExtension = project.extensions.getByType(PublishingExtension::class.java) + val components = project.components.withType(KotlinNativeMainComponent::class.java) + publishingExtension.publications.forEach { publication -> + (publication as? MavenPublication)?.apply { + val component = components.find { + it.name == publication.name + || publication.name.startsWith("${it.name}Release") + || publication.name.startsWith("${it.name}Debug") + } + component?.let { + it.poms.forEach { + publication.pom(it) + } + } + } + } + } + override fun apply(project: ProjectInternal): Unit = with(project) { pluginManager.apply(KotlinNativeBasePlugin::class.java) pluginManager.apply(NativeTestingBasePlugin::class.java) @@ -214,24 +231,7 @@ class KotlinNativePlugin @Inject constructor(val attributesFactory: ImmutableAtt addBinariesForMainComponents(group, version) addBinariesForTestComponents(group, version) - pluginManager.withPlugin("maven-publish") { - val publishingExtension = project.extensions.getByType(PublishingExtension::class.java) - val components = project.components.withType(KotlinNativeMainComponent::class.java) - publishingExtension.publications.forEach { publication -> - (publication as? MavenPublication)?.apply { - val component = components.find { - it.name == publication.name - || publication.name.startsWith("${it.name}Release") - || publication.name.startsWith("${it.name}Debug") - } - component?.let { - it.poms.forEach { - publication.pom(it) - } - } - } - } - } + setUpMavenPublish() } } } diff --git a/tools/kotlin-native-gradle-plugin/src/test/kotlin/ExperimentalPluginTests.kt b/tools/kotlin-native-gradle-plugin/src/test/kotlin/ExperimentalPluginTests.kt index 3f4b7187174..95865afdb44 100644 --- a/tools/kotlin-native-gradle-plugin/src/test/kotlin/ExperimentalPluginTests.kt +++ b/tools/kotlin-native-gradle-plugin/src/test/kotlin/ExperimentalPluginTests.kt @@ -4,8 +4,10 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.internal.project.ProjectInternal import org.gradle.testfixtures.ProjectBuilder +import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.TaskOutcome import org.jetbrains.kotlin.gradle.plugin.experimental.internal.KotlinNativeMainComponent +import org.jetbrains.kotlin.gradle.plugin.experimental.internal.OutputKind import org.jetbrains.kotlin.gradle.plugin.experimental.plugins.KotlinNativePlugin import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget @@ -411,4 +413,55 @@ class ExperimentalPluginTests { } } } + + private fun assertCompileOutcome(result: BuildResult, compileTasks: Collection, expectedOutcome: TaskOutcome) { + compileTasks.forEach { taskName -> + val task = result.task(taskName) + assertNotNull(task, "Task '$taskName' was not executed") { + assertEquals( + it.outcome, + expectedOutcome, + "Task '$taskName' has incorrect outcome. Expected: $expectedOutcome, actual: ${it.outcome}" + ) + } + } + } + + @Test + fun `Compilation should be up-to-date if there is no changes`() { + val project = KonanProject.create(projectDirectory).apply { + buildFile.writeText(""" + plugins { id 'kotlin-native' } + + sourceSets.main { + component { + outputKinds = [ EXECUTABLE, KLIBRARY, FRAMEWORK ] + target 'host', 'wasm32' + } + } + + """.trimIndent()) + } + + val outputKinds = arrayOf(OutputKind.EXECUTABLE, OutputKind.KLIBRARY, OutputKind.FRAMEWORK) + val buildTypes = arrayOf("Debug", "Release") + val targets = arrayOf(HostManager.host, KonanTarget.WASM32) + + val compileTasks = targets.flatMap { target -> + outputKinds.filter { it.availableFor(target) }.flatMap { kind -> + buildTypes.map { type -> + ":compile${type}${kind.name.toLowerCase().capitalize()}${target.name.capitalize()}KotlinNative" + } + } + } + + val ttt = project.createRunner().withArguments("tasks").build() + println(ttt.output) + + val result1 = project.createRunner().withArguments("assemble").build() + assertCompileOutcome(result1, compileTasks, TaskOutcome.SUCCESS) + + val result2 = project.createRunner().withArguments("assemble").build() + assertCompileOutcome(result2, compileTasks, TaskOutcome.UP_TO_DATE) + } } \ No newline at end of file