add srcjar support to enable code gen plugins (#54)
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/KotlinBuilder.kt b/kotlin/builder/src/io/bazel/kotlin/builder/KotlinBuilder.kt
index 606fdbc..1bcece6 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/KotlinBuilder.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/KotlinBuilder.kt
@@ -30,6 +30,7 @@
}
private val compileActions: List<BuildAction> = listOf(
+ UnpackSourceJars(toolchain),
Initialize(toolchain),
KotlinMainCompile(toolchain),
JavaMainCompile(toolchain),
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/Initialize.kt b/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/Initialize.kt
index 845bf92..383a521 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/Initialize.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/Initialize.kt
@@ -52,7 +52,21 @@
private fun bindSources(ctx: Context) {
val javaSources = mutableListOf<String>()
val allSources = mutableListOf<String>()
- for (src in ctx.flags.source) {
+
+ val sourcePool = with(mutableListOf<String>()) {
+ ctx.flags.source?.also {
+ check(it.isNotEmpty())
+ addAll(it)
+ }
+ addAll(Metas.UNPACKED_SOURCES[ctx] ?: emptyList())
+ toList()
+ }
+
+ if(sourcePool.isEmpty()) {
+ throw RuntimeException("no compilable sources found")
+ }
+
+ for (src in sourcePool) {
when {
src.endsWith(".java") -> {
javaSources.add(src)
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/JavaMainCompile.kt b/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/JavaMainCompile.kt
index bed49a6..2b0f5bc 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/JavaMainCompile.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/JavaMainCompile.kt
@@ -46,7 +46,7 @@
it.addAll(javaSources)
it.addAll(additionalJavaSources)
}
- Result.runAndBind(ctx) { executeAndAwait(30, args) }
+ Result.runAndBind(ctx) { executeAndAwait(30, null, args) }
}
return 0
}
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/UnpackSourceJars.kt b/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/UnpackSourceJars.kt
new file mode 100644
index 0000000..46b305f
--- /dev/null
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/mode/jvm/actions/UnpackSourceJars.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.builder.mode.jvm.actions
+
+import io.bazel.kotlin.builder.BuildAction
+import io.bazel.kotlin.builder.Context
+import io.bazel.kotlin.builder.KotlinToolchain
+import io.bazel.kotlin.builder.model.Metas
+import io.bazel.kotlin.builder.utils.executeAndAwaitSuccess
+import java.nio.file.Paths
+
+/**
+ * Unpack files with the srcjar extension into a temp directory.
+ */
+class UnpackSourceJars(toolchain: KotlinToolchain) : BuildAction("unpack srcjars", toolchain) {
+ override fun invoke(ctx: Context): Int {
+ if (ctx.flags.sourceJars != null) {
+ check(ctx.flags.sourceJars.isNotEmpty())
+
+ val unpackDir = ctx.flags.tempDirPath.value.resolve("_srcjars").toFile()
+ .also {
+ try {
+ it.mkdirs()
+ } catch(ex: Exception) {
+ throw RuntimeException("could not create unpack directory at $it", ex)
+ }
+ }
+ ctx.flags.sourceJars.map { Paths.get(it) }.forEach { srcjar ->
+ try {
+ mutableListOf(
+ Paths.get(toolchain.JAR_TOOL_PATH).toAbsolutePath().toString(),
+ "xf", srcjar.toAbsolutePath().toString()
+ ).also { executeAndAwaitSuccess(10, unpackDir, it) }
+ } catch (e: Exception) {
+ throw RuntimeException("unable to unpack source jar: $srcjar", e)
+ }
+ }
+ unpackDir.walk()
+ .filter { it.name.endsWith(".kt") || it.name.endsWith(".java") }
+ .map { it.toString() }
+ .toList()
+ // bind the sources even if the list is empty. throw an appropriate error if needed in Initialize.
+ .also { Metas.UNPACKED_SOURCES[ctx] = it }
+ return 0
+ } else {
+ return 0
+ }
+ }
+}
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/model/Flags.kt b/kotlin/builder/src/io/bazel/kotlin/builder/model/Flags.kt
index f41f875..f3e4e84 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/model/Flags.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/model/Flags.kt
@@ -31,7 +31,9 @@
// val strictJavaDeps = argMap.mandatorySingle(JavaBuilderFlags.STRICT_JAVA_DEPS.flag)
val outputClassJar = argMap.mandatorySingle(JavaBuilderFlags.OUTPUT.flag)
- val source = argMap.mandatory(JavaBuilderFlags.SOURCES.flag)
+ val source = argMap.optional(JavaBuilderFlags.SOURCES.flag)
+ val sourceJars = argMap.optional(JavaBuilderFlags.SOURCE_JARS.flag)
+
val classpath = argMap.mandatory(JavaBuilderFlags.CLASSPATH.flag)
val plugins = argMap.optionalFromJson<PluginDescriptors>("--kt-plugins")
val outputJdeps = argMap.mandatorySingle("--output_jdeps")
diff --git a/kotlin/builder/src/io/bazel/kotlin/builder/model/Metas.kt b/kotlin/builder/src/io/bazel/kotlin/builder/model/Metas.kt
index 48ec630..32e845e 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/model/Metas.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/model/Metas.kt
@@ -16,6 +16,7 @@
package io.bazel.kotlin.builder.model
import io.bazel.kotlin.builder.MandatoryMeta
+import io.bazel.kotlin.builder.Meta
/**
* Listin of Meta keys that don't make sense as companion objects.
@@ -26,9 +27,11 @@
// The target part of the label.
val TARGET = MandatoryMeta<String>("target")
- //If this is non empty then it is a mixed mode operation.
+ // If this is non empty then it is a mixed mode operation.
val JAVA_SOURCES = MandatoryMeta<List<String>>("java_sources")
+ // .kt and .java source files unpacked from .srcjar files
+ val UNPACKED_SOURCES = Meta<List<String>>("unpacked_sources")
val ALL_SOURCES = MandatoryMeta<List<String>>("all_sources")
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 fd52c42..4da723c 100644
--- a/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt
+++ b/kotlin/builder/src/io/bazel/kotlin/builder/utils/IOUtils.kt
@@ -70,11 +70,12 @@
}
}
-fun executeAndAwait(timeoutSeconds: Int, args: List<String>): Int {
- val process = ProcessBuilder(*args.toTypedArray()).let {
- it.redirectError(ProcessBuilder.Redirect.PIPE)
- it.redirectOutput(ProcessBuilder.Redirect.PIPE)
- it.start()
+fun executeAndAwait(timeoutSeconds: Int, directory: File? = null, args: List<String>): Int {
+ val process = ProcessBuilder(*args.toTypedArray()).let { pb ->
+ pb.redirectError(ProcessBuilder.Redirect.PIPE)
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE)
+ directory?.also { pb.directory(it) }
+ pb.start()
}
var isr: BufferedReader? = null
@@ -91,7 +92,11 @@
}
fun executeAndAwaitSuccess(timeoutSeconds: Int, vararg command: String) {
- val status = executeAndAwait(timeoutSeconds, command.toList())
+ executeAndAwaitSuccess(timeoutSeconds, null, command = command.toList())
+}
+
+fun executeAndAwaitSuccess(timeoutSeconds: Int, directory: File?, command: List<String>) {
+ val status = executeAndAwait(timeoutSeconds, directory, command)
check(status == 0) {
"process failed with status: $status"
}
diff --git a/kotlin/internal/compile.bzl b/kotlin/internal/compile.bzl
index eefee9e..bce6126 100644
--- a/kotlin/internal/compile.bzl
+++ b/kotlin/internal/compile.bzl
@@ -15,6 +15,9 @@
load("//kotlin/internal:plugins.bzl", "plugins")
load("//kotlin/internal:utils.bzl", "utils")
+_src_file_types = FileType([".java", ".kt"])
+_srcjar_file_type = FileType([".srcjar"])
+
def _kotlin_do_compile_action(ctx, rule_kind, output_jar, compile_jars):
"""Internal macro that sets up a Kotlin compile action.
@@ -44,13 +47,25 @@
"--output", output_jar.path,
"--output_jdeps", ctx.outputs.jdeps.path,
"--classpath", "\n".join([f.path for f in compile_jars.to_list()]),
- "--sources", "\n".join([f.path for f in ctx.files.srcs]),
"--kotlin_jvm_target", tc.jvm_target,
"--kotlin_api_version", tc.api_version,
"--kotlin_language_version", tc.language_version,
"--kotlin_module_name", getattr(ctx.attr, "module_name", ""),
"--kotlin_passthrough_flags", "-Xcoroutines=%s" % tc.coroutines
]
+
+ srcs=[f.path for f in _src_file_types.filter(ctx.files.srcs)]
+ src_jars = [f.path for f in _srcjar_file_type.filter(ctx.files.srcs)]
+
+ if len(srcs) == 0 and len(src_jars) == 0:
+ fail("srcs did not contain kotlin/java files or any srcjars")
+
+ if len(srcs) > 0:
+ args += ["--sources", "\n".join(srcs)]
+
+ if len(src_jars) > 0:
+ args += ["--source_jars", "\n".join(src_jars)]
+
# Collect and prepare plugin descriptor for the worker.
plugin_info=plugins.merge_plugin_infos(ctx.attr.plugins + ctx.attr.deps)
if len(plugin_info.processors) > 0:
diff --git a/kotlin/kotlin.bzl b/kotlin/kotlin.bzl
index e1f564a..54049de 100644
--- a/kotlin/kotlin.bzl
+++ b/kotlin/kotlin.bzl
@@ -118,8 +118,10 @@
_kotlin_compiler_repository = "kotlin_compiler_repository",
)
-# The files types that may be passed to the core Kotlin compile rule.
_kt_compile_filetypes = FileType([
+ # source jars these will be unpacked by the compiler.
+ ".srcjar",
+ # The files types that may be passed to the core Kotlin compile rule.
".kt",
".java",
])