rework the bootstrap macros to support multiple bootstrap libs and add (#71)

compiler delegate.
diff --git a/kotlin/builder/BUILD b/kotlin/builder/BUILD
index a8f2e6d..a268bbf 100644
--- a/kotlin/builder/BUILD
+++ b/kotlin/builder/BUILD
@@ -12,72 +12,113 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 load("//kotlin/builder:bootstrap.bzl", "kotlin_worker_lib")
+load("//kotlin:kotlin.bzl", "kt_jvm_library")
 
+# Should not be linked against to allow the compiler workspace to be switched out when toolchains support this.
+_COMPILER_DEPS = [
+    "@com_github_jetbrains_kotlin//:compiler",
+    "@com_github_jetbrains_kotlin//:kotlin-annotation-processing",
+    "@com_github_jetbrains_kotlin//:kotlin-script-runtime",
+]
+
+# Common depset for the builder.
+_COMMON_DEPS = [
+    "//kotlin/builder/proto",
+    "@com_github_jetbrains_kotlin//:preloader",
+    "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java//jar",
+    "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java_util//jar",
+    "@io_bazel_rules_kotlin_com_google_inject_guice//jar",
+    "@io_bazel_rules_kotlin_aopalliance_aopalliance//jar",
+    "@io_bazel_rules_kotlin_javax_inject_javax_inject//jar",
+    "@io_bazel_rules_kotlin_com_google_guava_guava//jar",
+    "@io_bazel_rules_kotlin_com_google_code_gson_gson//jar",
+    "@com_github_jetbrains_kotlin//:kotlin-reflect",
+    "@com_github_jetbrains_kotlin//:kotlin-stdlib",
+    "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7",
+    "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8",
+]
+
+# The compiler library, this is co-located in the kotlin compiler classloader.
 kotlin_worker_lib(
-    srcs = glob(["src/**/*.kt"]),
-    args = ["-jvm-target", "1.8"],
-    deps = [
-        "//kotlin/builder/proto",
-        "@com_github_jetbrains_kotlin//:preloader",
-        "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java//jar",
-        "@io_bazel_rules_kotlin_com_google_protobuf_protobuf_java_util//jar",
-        "@io_bazel_rules_kotlin_com_google_inject_guice//jar",
-        "@io_bazel_rules_kotlin_aopalliance_aopalliance//jar",
-        "@io_bazel_rules_kotlin_javax_inject_javax_inject//jar",
-        "@io_bazel_rules_kotlin_com_google_guava_guava//jar",
-        "@io_bazel_rules_kotlin_com_google_code_gson_gson//jar",
+    name = "compiler_lib",
+    srcs = glob(["src/io/bazel/kotlin/compiler/**/*.kt"]),
+    args = [
+        "-jvm-target","1.8",
     ],
-    exports = ["//kotlin/builder/proto"],
-    runtime_deps = [
-        "@com_github_jetbrains_kotlin//:kotlin-stdlib",
-        "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk7",
-        "@com_github_jetbrains_kotlin//:kotlin-stdlib-jdk8",
-        "@com_github_jetbrains_kotlin//:kotlin-reflect"
-    ]
+    neverlink_deps = _COMPILER_DEPS,
 )
 
+# The builder library.
+kotlin_worker_lib(
+    name = "builder_lib",
+    srcs = glob(["src/io/bazel/kotlin/builder/**/*.kt"]),
+    args = [
+        "-jvm-target","1.8",
+    ],
+    deps = _COMMON_DEPS
+)
+
+# This is a hack so that the builder and compiler sources can be picked up by intellij.
+kt_jvm_library(
+    name = "for_ide",
+    srcs = glob(["src/**/*.kt"]),
+    visibility = ["//visibility:private"],
+    deps = _COMMON_DEPS + _COMPILER_DEPS,
+)
+
+# The builder artifact.
 java_binary(
     name = "builder",
     main_class = "io.bazel.kotlin.builder.KotlinBuilder",
     visibility = ["//visibility:public"],
-    runtime_deps = [":worker_lib"]
-)
-
-filegroup(
-    name = "builder_runfiles",
-    srcs = [
-        "@com_github_jetbrains_kotlin//:kotlin-annotation-processing",
-        "@com_github_jetbrains_kotlin//:kotlin-script-runtime",
-        "@com_github_jetbrains_kotlin//:compiler",
-    ],
-    visibility = ["//visibility:private"]
-)
-
-java_test(
-    name = "integrationtests",
-    test_class = "io.bazel.kotlin.builder.KotlinBuilderTestSuite",
-    srcs = glob(["integrationtests/*.java"]),
-    deps = [
-        "//kotlin/builder:worker_lib",
-        "//kotlin/builder/proto:proto",
-        "//third_party/jvm/junit",
-        "//third_party/jvm/com/google/protobuf:protobuf_java",
-        "//third_party/jvm/com/google/guava",
-        "//third_party/jvm/com/google/inject:guice",
-        "//third_party/jvm/com/google/truth"
+    runtime_deps = [
+        ":builder_lib",
     ],
     data = [
-        ":builder_runfiles"
+        ":compiler_lib.jar"
+    ]
+)
+
+# This is defined so that tests can wire up a builder.
+filegroup(
+    name = "builder_runfiles_for_tests",
+    srcs = [
+        ":compiler_lib.jar",
+        "@com_github_jetbrains_kotlin//:compiler",
+        "@com_github_jetbrains_kotlin//:kotlin-annotation-processing",
+        "@com_github_jetbrains_kotlin//:kotlin-script-runtime",
+    ],
+    testonly = 1,
+    visibility = ["//visibility:private"],
+)
+
+java_library(
+    name = "builder_for_tests",
+    testonly = 1,
+    exports = _COMMON_DEPS + [
+        ":builder_lib",
+        ":compiler_lib",
+    ],
+    data = [
+        "builder_runfiles_for_tests"
     ]
 )
 
 java_test(
-    name = "unittests",
-    test_class = "io.bazel.kotlin.builder.mode.jvm.utils.JdepsParserTest",
-    srcs = glob(["unittests/**/*.java"]),
+    name = "integrationtests",
+    srcs = glob(["integrationtests/*.java"]),
+    test_class = "io.bazel.kotlin.builder.KotlinBuilderTestSuite",
     deps = [
-        ":worker_lib",
-        "//third_party/jvm/com/google/protobuf:protobuf_java",
+        "//kotlin/builder:builder_for_tests",
+        "//third_party/jvm/com/google/truth",
+        "//third_party/jvm/junit",
     ],
-    size = "small"
-)
\ No newline at end of file
+)
+
+java_test(
+    name = "unittests",
+    size = "small",
+    srcs = glob(["unittests/**/*.java"]),
+    test_class = "io.bazel.kotlin.builder.mode.jvm.utils.JdepsParserTest",
+    deps = [":builder_for_tests"],
+)
diff --git a/kotlin/builder/bootstrap.bzl b/kotlin/builder/bootstrap.bzl
index 28cdfe4..9772b81 100644
--- a/kotlin/builder/bootstrap.bzl
+++ b/kotlin/builder/bootstrap.bzl
@@ -40,25 +40,16 @@
 JAVA_HOME=external/local_jdk ./$(location @com_github_jetbrains_kotlin//:kotlinc) -cp $${CP} -d $(OUTS) $${ARGS} $(SRCS)
 """) % (name,args)
 
-def kotlin_worker_lib(srcs =[], args = [], deps=[], runtime_deps=[], exports=[]):
-    name = "worker"
+def kotlin_worker_lib(name, srcs, args = [], deps=[], runtime_deps=[], neverlink_deps=[]):
     dep_label = name + "_deps"
     jar_file_label =  name + "_file"
     jar_name = name+".jar"
-    libary_label =  name + "_lib"
+    jar_sources_file_label = jar_file_label + "_sources"
+    jar_sources_name = name + "-sources.jar"
 
-    # Dummy target loaded by `kotlin_library` so intellij can understand the sources.
-    _for_ide(
-        name = "for_ide",
-        srcs = srcs,
-        deps = deps,
-        runtime_deps = runtime_deps,
-        exports = exports,
-        visibility=["//visibility:private"],
-    )
     native.filegroup(
         name = dep_label,
-        srcs = deps,
+        srcs = deps + neverlink_deps,
         visibility = ["//visibility:private"]
     )
     native.genrule(
@@ -74,21 +65,26 @@
         cmd = _gen_cmd(dep_label, " ".join(args)),
         visibility = ["//visibility:private"]
     )
+    native.genrule(
+        name = jar_sources_file_label,
+        tools = [
+            "@local_jdk//:jdk",
+        ],
+        srcs = srcs,
+        outs = [jar_sources_name],
+        cmd = "jar cf $(OUTS) $(SRCS)",
+        visibility = ["//visibility:private"]
+    )
 
     # Use kt_jvm_import so that ijarification doesn't ruin the worker lib.
     kt_jvm_import(
-        name = libary_label + "_kt",
+        name = name,
         jars = [jar_name],
-        tags = ["no-ide"]
-    )
-
-    native.java_library(
-        name = libary_label,
-        exports = exports + [libary_label + "_kt"],
-        runtime_deps = (depset(runtime_deps) + exports + deps).to_list(),
+        srcjar = jar_sources_name,
+        tags = ["no-ide"],
+        runtime_deps = (depset(runtime_deps) + deps).to_list(),
         visibility = [
             "//tests:__subpackages__",
             "//kotlin:__subpackages__"
-        ],
-        tags = ["no-ide"]
+        ]
     )
\ No newline at end of file
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/KotlinToolchain.kt b/kotlin/builder/src/io/bazel/kotlin/builder/KotlinToolchain.kt
index 197810e..7219f43 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/KotlinToolchain.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/KotlinToolchain.kt
@@ -48,11 +48,14 @@
             Guice.createInjector(
                 object : AbstractModule() {
                     override fun configure() {
+                        val builderRunfiles=Paths.get(System.getenv("JAVA_RUNFILES"))
                         bind(PrintStream::class.java).toProvider(outputProvider)
                         install(
                             KotlinToolchain.TCModule(
                                 javaHome = Paths.get("external", "local_jdk"),
-                                kotlinHome = Paths.get("external", "com_github_jetbrains_kotlin")
+                                kotlinHome = Paths.get("external", "com_github_jetbrains_kotlin"),
+                                bazelKotlinCompilersJar = builderRunfiles.resolveVerified(
+                                    "io_bazel_rules_kotlin", "kotlin", "builder","compiler_lib.jar")
                             )
                         )
                     }
@@ -87,10 +90,12 @@
     private class TCModule constructor(
         javaHome: Path,
         kotlinHome: Path,
+        bazelKotlinCompilersJar: File,
         kotlinLibraryDirectory: Path = kotlinHome.resolveVerified("lib").toPath(),
         kapt3Jar: File = kotlinLibraryDirectory.resolveVerified("kotlin-annotation-processing.jar"),
         classloader: ClassLoader = ClassPreloadingUtils.preloadClasses(
             mutableListOf<File>().let {
+                it.add(bazelKotlinCompilersJar)
                 it.addAll(kotlinLibraryDirectory.verifiedRelativeFiles(Paths.get("kotlin-compiler.jar")))
                 it.addAll(javaHome.verifiedRelativeFiles(Paths.get("lib", "tools.jar")))
                 it.toList()
@@ -129,7 +134,7 @@
         }
 
         private val kotlincInvoker = object : KotlincInvoker {
-            val compilerClass = classloader.loadClass("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
+            val compilerClass = classloader.loadClass("io.bazel.kotlin.compiler.BazelK2JVMCompiler")
             val exitCodeClass = classloader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode")
 
             val compiler = compilerClass.newInstance()
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 1ef89b4..e68f6e5 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt
@@ -106,7 +106,7 @@
  */
 fun Path.verifiedRelativeFiles(vararg paths: Path): List<File> = paths.map { relative -> resolve(relative).verified() }
 
-private fun Path.verified(): File = this.toFile().also { check(it.exists()) { "file did not exist: $this" } }
+fun Path.verified(): File = this.toFile().also { check(it.exists()) { "file did not exist: $this" } }
 
 
 val Throwable.rootCause: Throwable
diff --git a/kotlin/builder/src/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt b/kotlin/builder/src/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt
new file mode 100644
index 0000000..b42af31
--- /dev/null
+++ b/kotlin/builder/src/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 The Bazel Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.bazel.kotlin.compiler
+
+import org.jetbrains.kotlin.cli.common.ExitCode
+import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
+
+class BazelK2JVMCompiler(private val delegate: K2JVMCompiler = K2JVMCompiler()) {
+    fun exec(errStream: java.io.PrintStream, vararg args: kotlin.String): ExitCode {
+        return delegate.exec(errStream, *args)
+    }
+}
\ No newline at end of file
diff --git a/kotlin/kotlin.bzl b/kotlin/kotlin.bzl
index 0935acf..e8b3c5d 100644
--- a/kotlin/kotlin.bzl
+++ b/kotlin/kotlin.bzl
@@ -241,6 +241,8 @@
 _common_outputs = dict(
     jar = "%{name}.jar",
     jdeps = "%{name}.jdeps",
+    # The params file, declared here so that validate it can be validated for testing.
+    jar_2_params = "%{name}.jar-2.params",
     srcjar = "%{name}-sources.jar",
 )