fine tune compilation output logging and some other cherries
diff --git a/kotlin/builder/integrationtests/KotlinBuilderActionTests.java b/kotlin/builder/integrationtests/KotlinBuilderActionTests.java
index a8516bf..2c6a829 100644
--- a/kotlin/builder/integrationtests/KotlinBuilderActionTests.java
+++ b/kotlin/builder/integrationtests/KotlinBuilderActionTests.java
@@ -6,7 +6,7 @@
   @Test
   public void testCompileSimple() {
     addSource("AClass.kt", "package something;" + "class AClass{}");
-    component().jvmTaskExecutor().compileKotlin(builderCommand(), context());
+    component().jvmTaskExecutor().compileKotlin(builderCommand(), context(), true);
     assertFileExists(DirectoryType.CLASSES, "something/AClass.class");
     assertFileDoesNotExist(outputs().getJar());
   }
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt b/kotlin/builder/src/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt
index 4a56c44..bad7f60 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/tasks/jvm/KotlinJvmTaskExecutor.kt
@@ -85,15 +85,16 @@
         }
     }
 
-    private fun JvmCompilationTask.runAnnotationProcessor(context: CompilationTaskContext): List<String> {
-        check(info.plugins.annotationProcessorsList.isNotEmpty()) {
-            "method called without annotation processors"
-        }
+    private fun JvmCompilationTask.runAnnotationProcessor(
+        context: CompilationTaskContext,
+        printOnSuccess: Boolean = true
+    ): List<String> {
+        check(info.plugins.annotationProcessorsList.isNotEmpty()) { "method called without annotation processors" }
         return getCommonArgs().let { args ->
             args.addAll(pluginArgsEncoder.encode(context, this))
             args.addAll(inputs.kotlinSourcesList)
             args.addAll(inputs.javaSourcesList)
-            context.executeCompilerTask(args, false, compiler::compile)
+            context.executeCompilerTask(args, compiler::compile, printOnSuccess = printOnSuccess)
         }
     }
 
@@ -124,17 +125,17 @@
     private fun JvmCompilationTask.runAnnotationProcessors(
         context: CompilationTaskContext
     ): JvmCompilationTask =
-        try {
-            if (info.plugins.annotationProcessorsList.isEmpty()) {
-                this
-            } else {
-                val kaptOutput = runAnnotationProcessor(context)
-                context.whenTracing { printLines("kapt output", kaptOutput) }
+        if (info.plugins.annotationProcessorsList.isEmpty()) {
+            this
+        } else {
+            runAnnotationProcessor(context, printOnSuccess = !context.isTracing).let { outputLines ->
+                // if tracing is enabled the output should be formated in a special way, if we aren't tracing then any
+                // compiler output would make it's way to the console as is.
+                if (context.isTracing) {
+                    context.printLines("kapt output", outputLines)
+                }
                 expandWithGeneratedSources()
             }
-        } catch (ex: CompilationStatusException) {
-            ex.lines.also(context::printCompilerOutput)
-            throw ex
         }
 
     /**
@@ -160,16 +161,14 @@
         var result: List<String>? = null
         context.execute("kotlinc") {
             result = try {
-                compileKotlin(context)
+                compileKotlin(context, printOnFail = false)
             } catch (ex: CompilationStatusException) {
                 kotlinError = ex
                 ex.lines
             }
         }
         try {
-            context.execute("javac") {
-                javaCompiler.compile(this)
-            }
+            context.execute("javac") { javaCompiler.compile(this) }
         } finally {
             checkNotNull(result).also(context::printCompilerOutput)
             kotlinError?.also { throw it }
@@ -179,11 +178,11 @@
     /**
      * Compiles Kotlin sources to classes. Does not compile Java sources.
      */
-    fun JvmCompilationTask.compileKotlin(context: CompilationTaskContext): List<String> =
+    fun JvmCompilationTask.compileKotlin(context: CompilationTaskContext, printOnFail: Boolean = true) =
         getCommonArgs().let { args ->
             args.addAll(inputs.javaSourcesList)
             args.addAll(inputs.kotlinSourcesList)
-            context.executeCompilerTask(args, false, compiler::compile)
+            context.executeCompilerTask(args, compiler::compile, printOnFail = printOnFail)
         }
 
     /**
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt b/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
index 8712d88..d65d447 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/utils/CompilationTaskContext.kt
@@ -93,21 +93,27 @@
      *
      * @throws CompilationStatusException if the compiler returns a status of anything but zero.
      * @param args the compiler command line switches
-     * @param deliverOutput if this is true the output will be printed to out directly.
+     * @param printOnFail if this is true the output will be printed if the task fails else the caller is responsible
+     *  for logging it by catching the [CompilationStatusException] excepotion.
      * @param compile the compilation method.
      */
     inline fun executeCompilerTask(
         args: List<String>,
-        deliverOutput: Boolean,
-        compile: (Array<String>, PrintStream) -> Int
+        compile: (Array<String>, PrintStream) -> Int,
+        printOnFail: Boolean = true,
+        printOnSuccess: Boolean = true
     ): List<String> {
         val outputStream = ByteArrayOutputStream()
         val ps = PrintStream(outputStream)
         val result = compile(args.toTypedArray(), ps)
         val output = ByteArrayInputStream(outputStream.toByteArray()).bufferedReader().readLines()
         if (result != 0) {
-            throw CompilationStatusException("compile phase failed", result, output)
-        } else if(deliverOutput) {
+            if (printOnFail) {
+                printCompilerOutput(output)
+            } else {
+                throw CompilationStatusException("compile phase failed", result, output)
+            }
+        } else if(printOnSuccess) {
             printCompilerOutput(output)
         }
         return output
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt b/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt
index 9e9c70b..f3b9de6 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt
@@ -65,6 +65,12 @@
     lines().forEach(pw::println); close()
 }
 
+fun Path.resolveTwinVerified(extension: String): Path =
+    parent.resolve(
+        "${toFile().nameWithoutExtension}${if (extension.startsWith(".")) "" else "."}$extension"
+    ).verified().toPath()
+
+
 fun Path.resolveVerified(vararg parts: String): File =
     resolve(Paths.get(parts[0], *Arrays.copyOfRange(parts, 1, parts.size))).verified()
 
@@ -73,6 +79,8 @@
 
 fun Path.verified(): File = this.toFile().also { check(it.exists()) { "file did not exist: $this" } }
 
+fun Path.verifiedPath(): Path = this.toFile().also { check(it.exists()) { "file did not exist: $this" } }.toPath()
+
 fun ensureDirectories(vararg directories: String) {
     for (directory in directories) {
         Files.createDirectories(Paths.get(directory))