1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-26 08:27:12 -07:00

Introduce build listeners and build report contributors.

This commit is contained in:
Cedric Beust 2016-07-30 07:36:03 -07:00
parent f629b76658
commit 007bb31ee3
7 changed files with 86 additions and 19 deletions

View file

@ -0,0 +1,9 @@
package com.beust.kobalt.api
/**
* Plug-ins that listen to build events.
*/
interface IBuildListener : IListener {
fun taskStart(project: Project, context: KobaltContext, taskName: String)
fun taskEnd(project: Project, context: KobaltContext, taskName: String)
}

View file

@ -0,0 +1,8 @@
package com.beust.kobalt.api
/**
* Plug-ins that produce build reports.
*/
interface IBuildReportContributor : IContributor {
fun generateReport(context: KobaltContext)
}

View file

@ -10,3 +10,6 @@ interface IPluginActor {
interface IContributor : IPluginActor
interface IInterceptor : IPluginActor
interface IListener : IPluginActor

View file

@ -0,0 +1,39 @@
package com.beust.kobalt.internal
import com.beust.kobalt.Args
import com.beust.kobalt.AsciiArt
import com.beust.kobalt.api.*
import com.beust.kobalt.misc.log
import java.util.concurrent.ConcurrentHashMap
/**
* Record timings and display them at the end of the build.
*/
class BuildListeners : IBuildListener, IBuildReportContributor {
class ProfilerInfo(val taskName: String, val durationMillis: Long)
private val startTimes = ConcurrentHashMap<String, Long>()
private val timings = arrayListOf<ProfilerInfo>()
override fun taskStart(project: Project, context: KobaltContext, taskName: String) {
startTimes.put(taskName, System.currentTimeMillis())
}
override fun taskEnd(project: Project, context: KobaltContext, taskName: String) {
startTimes[taskName]?.let {
timings.add(ProfilerInfo(taskName, System.currentTimeMillis() - it))
}
}
override fun generateReport(context: KobaltContext) {
val profiling = Kobalt.INJECTOR.getInstance(Args::class.java).profiling
if (profiling) {
log(1, "\n" + AsciiArt.horizontalSingleLine + " Timings (in seconds)")
timings.sortedByDescending { it.durationMillis }.forEach {
log(1, String.format("%1$10.2f", it.durationMillis.toDouble() / 1000)
+ " " + it.taskName)
}
log(1, "\n")
}
}
}

View file

@ -96,6 +96,8 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
val mavenIdInterceptors = arrayListOf<IMavenIdInterceptor>()
val jvmFlagContributors = arrayListOf<IJvmFlagContributor>()
val localMavenRepoPathInterceptors = arrayListOf<ILocalMavenRepoPathInterceptor>()
val buildListeners = arrayListOf<IBuildListener>()
val buildReportContributors = arrayListOf<IBuildReportContributor>()
// Note: intentionally repeating them here even though they are defined by our base class so
// that this class always contains the full list of contributors and interceptors
@ -212,6 +214,8 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
if (this is ITestJvmFlagInterceptor) testJvmFlagInterceptors.add(this)
if (this is IJvmFlagContributor) jvmFlagContributors.add(this)
if (this is ILocalMavenRepoPathInterceptor) localMavenRepoPathInterceptors.add(this)
if (this is IBuildListener) buildListeners.add(this)
if (this is IBuildReportContributor) buildReportContributors.add(this)
}
}
}
@ -225,7 +229,8 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
testSourceDirContributors, buildConfigFieldContributors,
taskContributors, incrementalTaskContributors, assemblyContributors,
incrementalAssemblyContributors, testJvmFlagInterceptors,
jvmFlagContributors, localMavenRepoPathInterceptors
jvmFlagContributors, localMavenRepoPathInterceptors, buildListeners,
buildReportContributors
).forEach {
it.forEach {
it.cleanUpActors()
@ -266,6 +271,8 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?,
testJvmFlagInterceptors.addAll(pluginInfo.testJvmFlagInterceptors)
jvmFlagContributors.addAll(pluginInfo.jvmFlagContributors)
localMavenRepoPathInterceptors.addAll(pluginInfo.localMavenRepoPathInterceptors)
buildListeners.addAll(pluginInfo.buildListeners)
buildReportContributors.addAll(pluginInfo.buildReportContributors)
}
}

View file

@ -17,7 +17,8 @@ import javax.inject.Singleton
@Singleton
class TaskManager @Inject constructor(val args: Args,
val incrementalManagerFactory: IncrementalManager.IFactory) {
val incrementalManagerFactory: IncrementalManager.IFactory,
val pluginInfo: PluginInfo) {
private val dependsOn = TreeMultimap.create<String, String>()
private val reverseDependsOn = TreeMultimap.create<String, String>()
private val runBefore = TreeMultimap.create<String, String>()
@ -168,7 +169,7 @@ class TaskManager @Inject constructor(val args: Args,
val factory = object : IThreadWorkerFactory<ITask> {
override fun createWorkers(nodes: Collection<ITask>)
= nodes.map { TaskWorker(listOf(it), args.dryRun, messages) }
= nodes.map { TaskWorker(listOf(it), args.dryRun, messages, pluginInfo) }
}
val executor = DynamicGraphExecutor(graph, factory)
@ -534,8 +535,13 @@ class TaskManager @Inject constructor(val args: Args,
/////
}
class TaskWorker(val tasks: List<ITask>, val dryRun: Boolean, val timings: MutableList<TaskManager.ProfilerInfo>)
: IWorker<ITask> {
class TaskWorker(val tasks: List<ITask>, val dryRun: Boolean, val pluginInfo: PluginInfo) : IWorker<ITask> {
private fun runBuildListeners(project: Project, context: KobaltContext, taskName: String, start: Boolean) {
context.pluginInfo.buildListeners.forEach {
if (start) it.taskStart(project, context, taskName) else it.taskEnd(project, context, taskName)
}
}
override fun call() : TaskResult2<ITask> {
if (tasks.size > 0) {
@ -545,14 +551,14 @@ class TaskWorker(val tasks: List<ITask>, val dryRun: Boolean, val timings: Mutab
}
var success = true
val errorMessages = arrayListOf<String>()
val context = Kobalt.context!!
tasks.forEach {
val name = it.project.name + ":" + it.name
val time = benchmarkMillis {
val tr = if (dryRun) TaskResult() else it.call()
success = success and tr.success
if (tr.errorMessage != null) errorMessages.add(tr.errorMessage)
}
timings.add(TaskManager.ProfilerInfo(name, time.first))
runBuildListeners(it.project, context, name, start = true)
val tr = if (dryRun) TaskResult() else it.call()
runBuildListeners(it.project, context, name, start = false)
success = success and tr.success
if (tr.errorMessage != null) errorMessages.add(tr.errorMessage)
}
return TaskResult2(success, errorMessages.joinToString("\n"), tasks[0])
}

View file

@ -213,14 +213,9 @@ private class Main @Inject constructor(
// Shutdown all plug-ins
plugins.shutdownPlugins()
// Display timings if requested
if (args.profiling) {
log(1, "\n" + AsciiArt.horizontalSingleLine + " Timings (in seconds)")
runTargetResult.timings.sortedByDescending { it.durationMillis }.forEach {
log(1, String.format("%1$10.2f", it.durationMillis.toDouble() / 1000)
+ " " + it.taskName)
}
log(1, "\n")
// Run the build report contributors
pluginInfo.buildReportContributors.forEach {
it.generateReport(Kobalt.context!!)
}
}
}