Fix broken compilation with BTAPI and add tests (#1663)
- Add missing dependency with `org.jetbrains.kotlin.daemon.common` package required for BTAPI infrastructure
- Pass the sources and the destination directory to the compiler as dedicated parameters.
- Introduce the `KotlinCompiler` interface defining the exec() function contract.
- Added `KotlinBuilderJvmBtaTest` and `useBuildToolsApi()` flag to test framework to enable compilation with BTAPI in tests.
In `KotlinAbstractTestBuilder` ensure that CompilationTaskInfo instance returned by CompilationTaskContext is the same as the JvmCompilationTask uses.
diff --git a/src/main/kotlin/BUILD.release.bazel b/src/main/kotlin/BUILD.release.bazel
index 4fadd45..84d9732 100644
--- a/src/main/kotlin/BUILD.release.bazel
+++ b/src/main/kotlin/BUILD.release.bazel
@@ -54,6 +54,7 @@
"//kotlin/compiler:jvm-abi-gen",
"//kotlin/compiler:kotlin-annotation-processing",
"//kotlin/compiler:kotlin-compiler",
+ "//kotlin/compiler:kotlin-daemon-client",
"//kotlin/compiler:kotlin-reflect",
"//src/main/kotlin/io/bazel/kotlin/compiler",
"@com_github_jetbrains_kotlin//:home",
@@ -71,6 +72,7 @@
"-D@com_github_jetbrains_kotlin...build-tools-api=$(rlocationpath @kotlin_build_tools_api//file)",
"-D@com_github_jetbrains_kotlin...jvm-abi-gen=$(rlocationpath //kotlin/compiler:jvm-abi-gen)",
"-D@com_github_jetbrains_kotlin...kotlin-compiler=$(rlocationpath //kotlin/compiler:kotlin-compiler)",
+ "-D@com_github_jetbrains_kotlin...kotlin-daemon-client=$(rlocationpath //kotlin/compiler:kotlin-daemon-client)",
"-D@com_github_jetbrains_kotlin...kapt=$(rlocationpath //kotlin/compiler:kotlin-annotation-processing)",
"-D@rules_kotlin...jdeps-gen=$(rlocationpath //src/main/kotlin:jdeps-gen)",
"-D@rules_kotlin...skip-code-gen=$(rlocationpath //src/main/kotlin:skip-code-gen)",
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel b/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel
index 1b46e99..93e2ed2 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel
+++ b/src/main/kotlin/io/bazel/kotlin/builder/cmd/BUILD.bazel
@@ -18,6 +18,7 @@
"//kotlin/compiler:jvm-abi-gen",
"//kotlin/compiler:kotlin-annotation-processing",
"//kotlin/compiler:kotlin-compiler",
+ "//kotlin/compiler:kotlin-daemon-client",
"//src/main/kotlin:jdeps-gen",
"//src/main/kotlin:skip-code-gen",
"//src/main/kotlin/io/bazel/kotlin/compiler:compiler.jar",
@@ -37,6 +38,7 @@
"-D@com_github_jetbrains_kotlin...build-tools-api=$(rlocationpath @kotlin_build_tools_api//file)",
"-D@com_github_jetbrains_kotlin...jvm-abi-gen=$(rlocationpath //kotlin/compiler:jvm-abi-gen)",
"-D@com_github_jetbrains_kotlin...kotlin-compiler=$(rlocationpath //kotlin/compiler:kotlin-compiler)",
+ "-D@com_github_jetbrains_kotlin...kotlin-daemon-client=$(rlocationpath //kotlin/compiler:kotlin-daemon-client)",
"-D@com_github_jetbrains_kotlin...kapt=$(rlocationpath //kotlin/compiler:kotlin-annotation-processing)",
"-D@rules_kotlin...jdeps-gen=$(rlocationpath //src/main/kotlin:jdeps-gen)",
"-D@rules_kotlin...skip-code-gen=$(rlocationpath //src/main/kotlin:skip-code-gen)",
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt
index 03d7fea..0a5fb77 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/CompilationTask.kt
@@ -54,8 +54,7 @@
CompilationArgs()
.absolutePaths(info.friendPathsList) {
"-Xfriend-paths=${it.joinToString(X_FRIENDS_PATH_SEPARATOR)}"
- }.flag("-d", directories.classes)
- .values(info.passthroughFlagsList)
+ }.values(info.passthroughFlagsList)
fun JvmCompilationTask.baseArgs(overrides: Map<String, String> = emptyMap()): CompilationArgs {
val classpath =
@@ -241,6 +240,7 @@
compiler: KotlinToolchain.KotlincInvoker,
): JvmCompilationTask {
return context.execute("kapt (${inputs.processorsList.joinToString(", ")})") {
+ val sources = (inputs.kotlinSourcesList + inputs.javaSourcesList).toTypedArray()
baseArgs()
.plus(
plugins(
@@ -249,14 +249,12 @@
),
).plus(
kaptArgs(context, plugins, "stubsAndApt"),
- ).flag("-d", directories.generatedClasses)
- .values(inputs.kotlinSourcesList)
- .values(inputs.javaSourcesList)
- .list()
+ ).list()
.let { args ->
context.executeCompilerTask(
- args,
- compiler::compile,
+ { out ->
+ compiler.compile(args.toTypedArray(), sources, directories.generatedClasses, out)
+ },
printOnSuccess = context.whenTracing { true } == true,
)
}.let { outputLines ->
@@ -387,23 +385,25 @@
writeJdeps(outputs.jdeps, emptyJdeps(info.label))
return emptyList()
} else {
+ val sources = (inputs.javaSourcesList + inputs.kotlinSourcesList).toTypedArray()
return (
args +
plugins(
options = inputs.compilerPluginOptionsList,
classpath = inputs.compilerPluginClasspathList,
)
- ).values(inputs.javaSourcesList)
- .values(inputs.kotlinSourcesList)
- .flag("-d", directories.classes)
- .list()
+ ).list()
.let {
context.whenTracing {
context.printLines("compileKotlin arguments:\n", it)
}
return@let context
- .executeCompilerTask(it, compiler::compile, printOnFail = printOnFail)
- .also {
+ .executeCompilerTask(
+ { out ->
+ compiler.compile(it.toTypedArray(), sources, directories.classes, out)
+ },
+ printOnFail = printOnFail,
+ ).also {
context.whenTracing {
printLines(
"kotlinc Files Created:",
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt
index 3b0fab2..7e02cdc 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/CompilationTaskContext.kt
@@ -112,20 +112,18 @@
* Execute a compilation task.
*
* @throws CompilationStatusException if the compiler returns a status of anything but zero.
- * @param args the compiler command line switches
* @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] exception.
- * @param compile the compilation method.
+ * @param compile the compilation method reporting its output to the given stream.
*/
fun executeCompilerTask(
- args: List<String>,
- compile: (Array<String>, PrintStream) -> Int,
+ compile: (PrintStream) -> Int,
printOnFail: Boolean = true,
printOnSuccess: Boolean = true,
): List<String> {
val outputStream = ByteArrayOutputStream()
val ps = PrintStream(outputStream)
- val result = compile(args.toTypedArray(), ps)
+ val result = compile(ps)
val output =
ByteArrayInputStream(outputStream.toByteArray())
.bufferedReader()
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt
index 2704d16..c04ffdc 100644
--- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt
+++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt
@@ -20,7 +20,8 @@
import io.bazel.kotlin.builder.utils.verified
import java.io.File
import java.io.PrintStream
-import java.lang.reflect.Method
+import java.lang.invoke.MethodHandle
+import java.lang.invoke.MethodHandles
import java.net.URLClassLoader
class KotlinToolchain private constructor(
@@ -73,6 +74,13 @@
).toPath()
}
+ private val KOTLIN_DAEMON_CLIENT by lazy {
+ BazelRunFiles
+ .resolveVerifiedFromProperty(
+ "@com_github_jetbrains_kotlin...kotlin-daemon-client",
+ ).toPath()
+ }
+
private val KOTLINX_SERIALIZATION_CORE_JVM by lazy {
BazelRunFiles
.resolveVerifiedFromProperty(
@@ -108,12 +116,11 @@
).toPath()
}
- internal val NO_ARGS = arrayOf<Any>()
-
@JvmStatic
fun createToolchain(): KotlinToolchain =
createToolchain(
KOTLINC.verified().absoluteFile,
+ KOTLIN_DAEMON_CLIENT.verified().absoluteFile,
BUILD_TOOLS_IMPL.verified().absoluteFile,
BUILD_TOOLS_API.verified().absoluteFile,
COMPILER.verified().absoluteFile,
@@ -129,6 +136,7 @@
@JvmStatic
fun createToolchain(
kotlinc: File,
+ kotlinDaemonClient: File,
buildTools: File,
buildToolsApi: File,
compiler: File,
@@ -143,6 +151,7 @@
KotlinToolchain(
listOf(
kotlinc,
+ kotlinDaemonClient,
compiler,
buildTools,
buildToolsApi,
@@ -193,18 +202,23 @@
clazz: String,
) {
private val compiler: Any
- private val execMethod: Method
- private val getCodeMethod: Method
+ private val execHandle: MethodHandle
+ private val getCodeHandle: MethodHandle
init {
val compilerClass = toolchain.classLoader.loadClass(clazz)
+ val compilerInterface =
+ toolchain.classLoader.loadClass("io.bazel.kotlin.compiler.KotlinCompiler")
val exitCodeClass =
toolchain.classLoader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode")
- compiler = compilerClass.getConstructor().newInstance()
- execMethod =
- compilerClass.getMethod("exec", PrintStream::class.java, Array<String>::class.java)
- getCodeMethod = exitCodeClass.getMethod("getCode")
+ compiler = compilerInterface.cast(compilerClass.getConstructor().newInstance())
+
+ // The interface is the source of truth for the exec method signature.
+ val execMethod = compilerInterface.declaredMethods.single { it.name == "exec" }
+ val lookup = MethodHandles.lookup()
+ execHandle = lookup.unreflect(execMethod)
+ getCodeHandle = lookup.unreflect(exitCodeClass.getMethod("getCode"))
}
// Kotlin error codes:
@@ -213,10 +227,12 @@
// 3 is the script execution error
fun compile(
args: Array<String>,
+ sources: Array<String>,
+ destination: String,
out: PrintStream,
): Int {
- val exitCodeInstance = execMethod.invoke(compiler, out, args)
- return getCodeMethod.invoke(exitCodeInstance, *NO_ARGS) as Int
+ val exitCode = execHandle.invoke(compiler, out, args, sources, destination)
+ return getCodeHandle.invoke(exitCode) as Int
}
}
diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt
index f42c2da..47844c1 100644
--- a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt
+++ b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt
@@ -20,16 +20,21 @@
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.config.Services
+import java.io.PrintStream
@Suppress("unused")
-class BazelK2JVMCompiler {
- fun exec(
- errStream: java.io.PrintStream,
- vararg args: String,
+class BazelK2JVMCompiler : KotlinCompiler {
+ override fun exec(
+ errStream: PrintStream,
+ args: Array<String>,
+ sources: Array<String>,
+ destination: String,
): ExitCode {
System.setProperty("zip.handler.uses.crc.instead.of.timestamp", "true")
val delegate: K2JVMCompiler = K2JVMCompiler()
- val arguments = delegate.createArguments().also { delegate.parseArguments(args, it) }
+
+ val cliArgs = args + arrayOf("-d", destination) + sources
+ val arguments = delegate.createArguments().also { delegate.parseArguments(cliArgs, it) }
val collector =
PrintingMessageCollector(errStream, MessageRenderer.PLAIN_RELATIVE_PATHS, arguments.verbose)
return delegate.exec(collector, Services.EMPTY, arguments)
diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/BuildToolsAPICompiler.kt b/src/main/kotlin/io/bazel/kotlin/compiler/BuildToolsAPICompiler.kt
index ced1579..aa14ce7 100644
--- a/src/main/kotlin/io/bazel/kotlin/compiler/BuildToolsAPICompiler.kt
+++ b/src/main/kotlin/io/bazel/kotlin/compiler/BuildToolsAPICompiler.kt
@@ -21,27 +21,28 @@
import org.jetbrains.kotlin.buildtools.api.getToolchain
import org.jetbrains.kotlin.buildtools.api.jvm.JvmPlatformToolchain
import org.jetbrains.kotlin.cli.common.ExitCode
-import java.nio.file.Path
+import java.io.PrintStream
+import java.nio.file.Paths
@Suppress("unused")
-class BuildToolsAPICompiler {
+class BuildToolsAPICompiler : KotlinCompiler {
@OptIn(ExperimentalBuildToolsApi::class)
- fun exec(
- errStream: java.io.PrintStream,
- vararg args: String,
+ override fun exec(
+ errStream: PrintStream,
+ args: Array<String>,
+ sources: Array<String>,
+ destination: String,
): ExitCode {
System.setProperty("zip.handler.uses.crc.instead.of.timestamp", "true")
val kotlinToolchains = KotlinToolchains.loadImplementation(this.javaClass.classLoader!!)
- // Create compilation operation with empty sources and dummy destination
- // (the actual sources/destination will be set via applyArgumentStrings)
val operationBuilder =
kotlinToolchains
.getToolchain<JvmPlatformToolchain>()
.jvmCompilationOperationBuilder(
- emptyList(),
- Path.of("."),
+ sources.map { Paths.get(it) },
+ Paths.get(destination),
)
// Apply raw CLI arguments - this parses the args and sets all compiler options
diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/KotlinCompiler.kt b/src/main/kotlin/io/bazel/kotlin/compiler/KotlinCompiler.kt
new file mode 100644
index 0000000..704fbdf
--- /dev/null
+++ b/src/main/kotlin/io/bazel/kotlin/compiler/KotlinCompiler.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2026 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 java.io.PrintStream
+
+/**
+ * The compilation contract between the worker and the compiler implementations loaded into the
+ * compiler classloader and invoked reflectively.
+ */
+interface KotlinCompiler {
+ fun exec(
+ errStream: PrintStream,
+ args: Array<String>,
+ sources: Array<String>,
+ destination: String,
+ ): ExitCode
+}
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java
index 6300f77..a5e3272 100644
--- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java
+++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinAbstractTestBuilder.java
@@ -20,6 +20,7 @@
import io.bazel.kotlin.builder.toolchain.CompilationTaskContext;
import io.bazel.kotlin.builder.toolchain.KotlinToolchain;
import io.bazel.kotlin.model.CompilationTaskInfo;
+import io.bazel.kotlin.model.JvmCompilationTaskOrBuilder;
import io.bazel.kotlin.model.KotlinToolchainInfo;
import io.bazel.kotlin.model.Platform;
import io.bazel.kotlin.model.RuleKind;
@@ -44,7 +45,7 @@
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList;
-abstract class KotlinAbstractTestBuilder<T> {
+abstract class KotlinAbstractTestBuilder<T extends JvmCompilationTaskOrBuilder> {
private static final Path BAZEL_TEST_DIR =
FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR"));
@@ -152,15 +153,13 @@
}
final <R> R runCompileTask(BiFunction<CompilationTaskContext, T, R> operation) {
- T task = buildTask();
- return runCompileTask(infoBuilder.build(), task, (ctx, t) -> operation.apply(ctx, task));
+ return runCompileTask(buildTask(), operation);
}
- private <R> R runCompileTask(
- CompilationTaskInfo info, T task, BiFunction<CompilationTaskContext, T, R> operation) {
+ private <R> R runCompileTask(T task, BiFunction<CompilationTaskContext, T, R> operation) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (PrintStream outputStream = new PrintStream(out)) {
- return operation.apply(new CompilationTaskContext(info, outputStream,
+ return operation.apply(new CompilationTaskContext(task.getInfo(), outputStream,
instanceRoot().toAbsolutePath() + File.separator), task);
} finally {
outLines = unmodifiableList(
@@ -229,6 +228,7 @@
static KotlinToolchain toolchainForTest() {
return KotlinToolchain.createToolchain(
new File(Deps.Dep.fromLabel("//kotlin/compiler:kotlin-compiler").singleCompileJar()),
+ new File(Deps.Dep.fromLabel("//kotlin/compiler:kotlin-daemon-client").singleCompileJar()),
new File(Deps.Dep.fromLabel("@kotlin_build_tools_impl//file").singleCompileJar()),
new File(Deps.Dep.fromLabel("@kotlin_build_tools_api//file").singleCompileJar()),
new File(Deps.Dep.fromLabel("//src/main/kotlin/io/bazel/kotlin/compiler:compiler.jar").singleCompileJar()),
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java
index 08f91bf..f17e91b 100644
--- a/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java
+++ b/src/test/kotlin/io/bazel/kotlin/builder/KotlinJvmTestBuilder.java
@@ -132,13 +132,13 @@
);
return Dep.builder()
- .label(taskBuilder.getInfo().getLabel())
+ .label(task.getInfo().getLabel())
.compileJars(ImmutableList.of(
outputs.getAbijar().isEmpty() ? outputs.getJar() : outputs.getAbijar()
))
.jdeps(outputs.getJdeps())
- .runtimeDeps(ImmutableList.copyOf(taskBuilder.getInputs().getClasspathList()))
- .sourceJar(taskBuilder.getOutputs().getSrcjar())
+ .runtimeDeps(ImmutableList.copyOf(task.getInputs().getClasspathList()))
+ .sourceJar(outputs.getSrcjar())
.build();
});
}
@@ -268,5 +268,10 @@
.setLanguageVersion("2.0");
return this;
}
+
+ public TaskBuilder useBuildToolsApi() {
+ taskBuilder.getInfoBuilder().setBuildToolsApi(true);
+ return this;
+ }
}
}
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel
index c1af861..c5bd529 100644
--- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel
+++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/BUILD.bazel
@@ -61,6 +61,11 @@
)
kt_rules_test(
+ name = "KotlinBuilderJvmBtaTest",
+ srcs = ["jvm/KotlinBuilderJvmBtaTest.java"],
+)
+
+kt_rules_test(
name = "KotlinBuilderJvmJdepsTest",
size = "large",
srcs = ["jvm/KotlinBuilderJvmJdepsTest.kt"],
@@ -139,6 +144,7 @@
":KotlinBuilderBuildTest",
":KotlinBuilderJvmAbiTest",
":KotlinBuilderJvmBasicTest",
+ ":KotlinBuilderJvmBtaTest",
":KotlinBuilderJvmCoverageTest",
":KotlinBuilderJvmJdepsTest",
":KotlinBuilderJvmKaptTest",
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderBuildTest.kt b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderBuildTest.kt
index 550be58..95b738a 100644
--- a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderBuildTest.kt
+++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderBuildTest.kt
@@ -86,6 +86,7 @@
val toolchain =
KotlinToolchain.createToolchain(
File(Deps.Dep.fromLabel("//kotlin/compiler:kotlin-compiler").singleCompileJar()),
+ File(Deps.Dep.fromLabel("//kotlin/compiler:kotlin-daemon-client").singleCompileJar()),
File(Deps.Dep.fromLabel("@kotlin_build_tools_impl//file").singleCompileJar()),
File(Deps.Dep.fromLabel("@kotlin_build_tools_api//file").singleCompileJar()),
File(
diff --git a/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBtaTest.java b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBtaTest.java
new file mode 100644
index 0000000..0953e31
--- /dev/null
+++ b/src/test/kotlin/io/bazel/kotlin/builder/tasks/jvm/KotlinBuilderJvmBtaTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2026 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.builder.tasks.jvm;
+
+import io.bazel.kotlin.builder.DirectoryType;
+import io.bazel.kotlin.builder.KotlinJvmTestBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Compiles through the Build Tools API path ({@code --build_tools_api=true}). */
+@RunWith(JUnit4.class)
+public class KotlinBuilderJvmBtaTest {
+ private static final KotlinJvmTestBuilder ctx = new KotlinJvmTestBuilder();
+
+ @Test
+ public void testSimpleKotlinCompile() {
+ ctx.runCompileTask(
+ c -> {
+ c.useBuildToolsApi();
+ c.compileKotlin();
+ c.addSource("AClass.kt", "package something;" + "class AClass{}");
+ c.outputJar();
+ c.outputJdeps();
+ });
+ ctx.assertFilesExist(DirectoryType.CLASSES, "something/AClass.class");
+ }
+
+ @Test
+ public void testMixedModeCompile() {
+ // The Kotlin class references the Java class, so the compilation is only successful, if the .java source reaches the compiler's source list.
+ ctx.runCompileTask(
+ c -> {
+ c.useBuildToolsApi();
+ c.compileKotlin();
+ c.addSource(
+ "AClass.kt",
+ "package something;" + "class AClass{ val other = AnotherClass() }");
+ c.addSource(
+ "AnotherClass.java",
+ "package something;",
+ "",
+ "public class AnotherClass{}");
+ c.outputJar();
+ c.outputJdeps();
+ });
+ ctx.assertFilesExist(DirectoryType.CLASSES, "something/AClass.class");
+ }
+}
diff --git a/src/test/kotlin/io/bazel/kotlin/defs.bzl b/src/test/kotlin/io/bazel/kotlin/defs.bzl
index 2d55c0d..31b0aba 100644
--- a/src/test/kotlin/io/bazel/kotlin/defs.bzl
+++ b/src/test/kotlin/io/bazel/kotlin/defs.bzl
@@ -37,6 +37,7 @@
"//kotlin/compiler:annotations",
"//kotlin/compiler:jvm-abi-gen",
"//kotlin/compiler:kotlin-compiler",
+ "//kotlin/compiler:kotlin-daemon-client",
"//kotlin/compiler:kotlin-stdlib",
"//kotlin/compiler:kotlin-stdlib-jdk7",
"//kotlin/compiler:kotlin-stdlib-jdk8",