From 267fa4c12d7a7762e274a35ba9ff27ee53036f12 Mon Sep 17 00:00:00 2001 From: Cedric Beust Date: Mon, 21 Dec 2015 04:27:00 +0400 Subject: [PATCH] Incremental compilations. --- .../com/beust/kobalt/IncrementalTaskInfo.kt | 2 +- .../kobalt/internal/JvmCompilerPlugin.kt | 20 ++++++++-- .../com/beust/kobalt/internal/TaskManager.kt | 39 +++++++++++++++++-- .../main/kotlin/com/beust/kobalt/maven/Md5.kt | 19 +++++++++ .../kotlin/com/beust/kobalt/misc/KFiles.kt | 2 +- 5 files changed, 74 insertions(+), 8 deletions(-) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/IncrementalTaskInfo.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/IncrementalTaskInfo.kt index 6e07fa49..3fc06a0c 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/IncrementalTaskInfo.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/IncrementalTaskInfo.kt @@ -10,4 +10,4 @@ import com.beust.kobalt.api.Project * if they differ, the task gets run. * @param task The task to run. */ -class IncrementalTaskInfo(val inputChecksum: String, val outputChecksum: String?, val task: (Project) -> TaskResult) +class IncrementalTaskInfo(val inputChecksum: String?, val outputChecksum: String?, val task: (Project) -> TaskResult) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt index fd07cb5a..15f1c797 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/JvmCompilerPlugin.kt @@ -1,14 +1,17 @@ package com.beust.kobalt.internal import com.beust.kobalt.Features +import com.beust.kobalt.IncrementalTaskInfo import com.beust.kobalt.KobaltException import com.beust.kobalt.TaskResult import com.beust.kobalt.api.* import com.beust.kobalt.api.annotation.ExportedProjectProperty +import com.beust.kobalt.api.annotation.IncrementalTask import com.beust.kobalt.api.annotation.Task import com.beust.kobalt.maven.DepFactory import com.beust.kobalt.maven.DependencyManager import com.beust.kobalt.maven.LocalRepo +import com.beust.kobalt.maven.Md5 import com.beust.kobalt.misc.KFiles import com.beust.kobalt.misc.KobaltExecutors import com.beust.kobalt.misc.log @@ -61,7 +64,7 @@ abstract class JvmCompilerPlugin @Inject constructor( override fun apply(project: Project, context: KobaltContext) { super.apply(project, context) project.projectProperties.put(DEPENDENT_PROJECTS, projects()) - taskContributor.addVariantTasks(this, project, context, "compile", runTask = { taskCompile(project) }) + taskContributor.addVariantTasks(this, project, context, "compile", runTask = { doTaskCompile(project) }) } @Task(name = TASK_TEST, description = "Run the tests", @@ -164,8 +167,19 @@ abstract class JvmCompilerPlugin @Inject constructor( return false } - @Task(name = JvmCompilerPlugin.TASK_COMPILE, description = "Compile the project") - fun taskCompile(project: Project) : TaskResult { + @IncrementalTask(name = JvmCompilerPlugin.TASK_COMPILE, description = "Compile the project") + fun taskCompile(project: Project) : IncrementalTaskInfo { + val inputChecksum = Md5.toMd5Directories(project.sourceDirectories.map { + File(project.directory, it) + }) + return IncrementalTaskInfo( + inputChecksum = inputChecksum, + outputChecksum = "1", + task = { project -> doTaskCompile(project) } + ) + } + + private fun doTaskCompile(project: Project) : TaskResult { // Set up the source files now that we have the variant sourceDirectories.addAll(context.variant.sourceDirectories(project)) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt index a191c1cf..651553bd 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/TaskManager.kt @@ -17,7 +17,7 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -public class TaskManager @Inject constructor(val args: Args) { +public class TaskManager @Inject constructor(val args: Args, val incrementalManager: IncrementalManager) { private val runBefore = TreeMultimap.create() private val alwaysRunAfter = TreeMultimap.create() @@ -248,7 +248,40 @@ public class TaskManager @Inject constructor(val args: Args) { { project -> val iit = method.invoke(plugin, project) as IncrementalTaskInfo // TODO: compare the checksums with the previous run - iit.task(project) + val taskName = project.name + ":" + ta.name + var upToDate = false + incrementalManager.inputChecksumFor(taskName)?.let { inputChecksum -> + if (inputChecksum == iit.inputChecksum) { + incrementalManager.outputChecksumFor(taskName)?.let { outputChecksum -> + if (outputChecksum == iit.outputChecksum) { + upToDate = true + } else { + log(2, " INC- Incremental task ${ta.name} output is out of date, running it") + + } + } + } else { + log(2, " INC- Incremental task ${ta.name} input is out of date, running it") + } + } + if (! upToDate) { + val result = iit.task(project) + if (result.success) { + log(2, " INC- Incremental task ${ta.name} done running, saving checksums") + iit.inputChecksum?.let { + incrementalManager.saveInputChecksum(taskName, it) + log(2, " INC- input $it saved") + } + iit.outputChecksum?.let { + incrementalManager.saveOutputChecksum(taskName, it) + log(2, " INC- output $it saved") + } + } + result + } else { + log(2, " INC- Incremental task ${ta.name} is up to date, not running it") + TaskResult() + } }) class PluginDynamicTask(val plugin: IPlugin, val task: DynamicTask) @@ -334,7 +367,7 @@ class TaskWorker(val tasks: List, val dryRun: Boolean) : IWorker { if (tasks.size > 0) { tasks[0].let { - log(1, AsciiArt.taskColor(AsciiArt.horizontalSingleLine + " ${it.project.name}:${it.name}")) + log(2, AsciiArt.taskColor(AsciiArt.horizontalSingleLine + " ${it.project.name}:${it.name}")) } } var success = true diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Md5.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Md5.kt index c432bbed..c47a5b31 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Md5.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/maven/Md5.kt @@ -1,11 +1,29 @@ package com.beust.kobalt.maven +import com.beust.kobalt.misc.KFiles import java.io.File import java.security.MessageDigest import javax.xml.bind.DatatypeConverter public class Md5 { companion object { + fun toMd5Directories(directories: List) : String { + MessageDigest.getInstance("MD5").let { md5 -> + directories.forEach { file -> + KFiles.findRecursively(file).map { + File(file, it) + }.filter { + it.isFile + }.forEach { + val bytes = it.readBytes() + md5.update(bytes, 0, bytes.size) + } + } + val result = DatatypeConverter.printHexBinary(md5.digest()).toLowerCase() + return result + } + } + fun toMd5(file: File) = MessageDigest.getInstance("MD5").let { md5 -> file.forEachBlock { bytes, size -> md5.update(bytes, 0, size) @@ -14,3 +32,4 @@ public class Md5 { } } } + diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt index 76558e90..a0909add 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt @@ -45,7 +45,7 @@ class KFiles { } companion object { - private const val KOBALT_DOT_DIR : String = ".kobalt" + internal const val KOBALT_DOT_DIR : String = ".kobalt" const val KOBALT_DIR : String = "kobalt" const val KOBALT_BUILD_DIR = "kobaltBuild"