get builder tests passing on windows
diff --git a/src/main/kotlin/bootstrap.bzl b/src/main/kotlin/bootstrap.bzl index 5901cda..2668fc0 100644 --- a/src/main/kotlin/bootstrap.bzl +++ b/src/main/kotlin/bootstrap.bzl
@@ -47,32 +47,47 @@ visibility = ["//visibility:private"], ) command = """ -KOTLIN_HOME=external/com_github_jetbrains_kotlin - function join_by { local IFS="$$1"; shift; echo "$$*"; } - +case "$$(uname -s)" in + CYGWIN*|MINGW32*|MSYS*) + SEP=";" + ;; + *) + SEP=":" + ;; +esac NAME=%s -CP="$$(join_by : $(locations :%s))" +CP="$$(join_by $$SEP $(locations :%s))" ARGS="%s" -java -Xmx256M -Xms32M -noverify \ - -cp $${KOTLIN_HOME}/lib/kotlin-preloader.jar org.jetbrains.kotlin.preloading.Preloader \ - -cp $${KOTLIN_HOME}/lib/kotlin-compiler.jar org.jetbrains.kotlin.cli.jvm.K2JVMCompiler \ - -cp $${CP} -d $${NAME}_temp.jar $${ARGS} $(SRCS) +$(JAVA) -Xmx256M -Xms32M -noverify \ + -cp $(location @com_github_jetbrains_kotlin//:kotlin-preloader) org.jetbrains.kotlin.preloading.Preloader \ + -cp $(location @com_github_jetbrains_kotlin//:kotlin-compiler) org.jetbrains.kotlin.cli.jvm.K2JVMCompiler \ + -cp $${CP} -d $(@D)/$${NAME}_temp.jar $${ARGS} $(SRCS) -$(location @bazel_tools//tools/jdk:singlejar) \ +case "$(location @bazel_tools//tools/jdk:singlejar)" in + *.jar) + SJ="$(JAVA) -jar $(location @bazel_tools//tools/jdk:singlejar)" + ;; + *) + SJ="$(location @bazel_tools//tools/jdk:singlejar)" + ;; +esac + +$$SJ \ --normalize \ --compression \ - --sources $${NAME}_temp.jar \ + --sources $(@D)/$${NAME}_temp.jar \ --output $(OUTS) -rm $${NAME}_temp.jar +rm $(@D)/$${NAME}_temp.jar """ % (name, dep_label, " ".join(_BOOTSTRAP_LIB_ARGS)) native.genrule( name = jar_label, tools = [ "@com_github_jetbrains_kotlin//:home", - "@local_jdk//:jdk", + "@com_github_jetbrains_kotlin//:kotlin-preloader", + "@com_github_jetbrains_kotlin//:kotlin-compiler", "@bazel_tools//tools/jdk:singlejar", dep_label, ], @@ -80,6 +95,9 @@ outs = [name + ".jar"], tags = ["no-ide"], visibility = ["//visibility:private"], + toolchains = [ + "@bazel_tools//tools/jdk:current_host_java_runtime", + ], cmd = command, ) native.java_import(
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt index 83cc7e8..181fe8f 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JDepsGenerator.kt
@@ -66,7 +66,7 @@ JdepsParser.parse( command.info.label, command.outputs.jdeps, - joinedClasspath, + command.inputs.classpathList, it, isKotlinImplicit )
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt index c7385bb..606f644 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JavaCompiler.kt
@@ -20,6 +20,7 @@ import io.bazel.kotlin.builder.utils.addAll import io.bazel.kotlin.builder.utils.joinedClasspath import io.bazel.kotlin.model.JvmCompilationTask +import java.io.File import java.io.PrintWriter import javax.inject.Inject import javax.inject.Singleton @@ -28,12 +29,18 @@ internal class JavaCompiler @Inject constructor( private val javacInvoker: KotlinToolchain.JavacInvoker ) { + companion object { + /** + * Separator for a directory in the classpath. + */ + private val DIR_SEP = "${File.separatorChar}${File.pathSeparator}" + } fun compile(context: CompilationTaskContext, command: JvmCompilationTask) { val i = command.inputs val d = command.directories if (i.javaSourcesList.isNotEmpty()) { val args = mutableListOf( - "-cp", "${d.classes}/:${d.temp}/:${i.joinedClasspath}", + "-cp", "${d.classes}$DIR_SEP${d.temp}$DIR_SEP${i.joinedClasspath}", "-d", d.classes ).also { it.addAll(
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt index 0c923e6..c2c053e 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/tasks/jvm/JdepsParser.kt
@@ -113,15 +113,14 @@ fun parse( label: String, classJar: String, - classPath: String, - jdepLines: List<String>, + classPath: MutableList<String>, + lines: List<String>, isImplicit: Predicate<String> ): Deps.Dependencies { val filename = Paths.get(classJar).fileName.toString() val jdepsParser = JdepsParser(filename, isImplicit) - classPath.split(":".toRegex()).dropLastWhile { it.isEmpty() }.stream() - .forEach { x -> jdepsParser.consumeJarLine(x, Deps.Dependency.Kind.UNUSED) } - jdepLines.forEach { jdepsParser.processLine(it) } + classPath.forEach { x -> jdepsParser.consumeJarLine(x, Deps.Dependency.Kind.UNUSED) } + lines.forEach { jdepsParser.processLine(it) } val rootBuilder = Deps.Dependencies.newBuilder() rootBuilder.success = false
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 167ba0f..5fbf9e7 100644 --- a/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt +++ b/src/main/kotlin/io/bazel/kotlin/builder/toolchain/KotlinToolchain.kt
@@ -15,6 +15,7 @@ */ package io.bazel.kotlin.builder.toolchain +import io.bazel.kotlin.builder.utils.BazelRunFiles import io.bazel.kotlin.builder.utils.resolveVerified import org.jetbrains.kotlin.preloading.ClassPreloadingUtils import org.jetbrains.kotlin.preloading.Preloader @@ -45,31 +46,38 @@ internal val NO_ARGS = arrayOf<Any>() private val isJdk9OrNewer = !System.getProperty("java.version").startsWith("1.") - private val javaRunfiles get() = Paths.get(System.getenv("JAVA_RUNFILES")) - private fun createClassLoader(javaHome: Path, kotlinHome: Path): ClassLoader { - val preloadJars = mutableListOf<File>().also { - it += kotlinHome.resolveVerified("lib", "kotlin-compiler.jar") - it += javaRunfiles.resolveVerified("io_bazel_rules_kotlin", "src", "main", "kotlin", "compiler_lib.jar") - if (!isJdk9OrNewer) { - it += javaHome.resolveVerified("lib", "tools.jar") - } - } - return ClassPreloadingUtils.preloadClasses( - preloadJars, + private fun createClassLoader(javaHome: Path, baseJars: List<File>): ClassLoader = + ClassPreloadingUtils.preloadClasses( + mutableListOf<File>().also { + it += baseJars + if (!isJdk9OrNewer) { + it += javaHome.resolveVerified("lib", "tools.jar") + } + }, Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE, ClassLoader.getSystemClassLoader(), null ) - } @JvmStatic fun createToolchain(): KotlinToolchain { - val kotlinHome = Paths.get("external", "com_github_jetbrains_kotlin") val javaHome = Paths.get(System.getProperty("java.home")).let { path -> path.takeIf { !it.endsWith(Paths.get("jre")) } ?: path.parent } - return KotlinToolchain(kotlinHome, createClassLoader(javaHome, kotlinHome)) + val kotlinCompilerJar = BazelRunFiles.resolveVerified( + "external", "com_github_jetbrains_kotlin", "lib", "kotlin-compiler.jar") + return KotlinToolchain( + kotlinCompilerJar.toPath().parent.parent, + createClassLoader( + javaHome, + listOf( + kotlinCompilerJar, + BazelRunFiles.resolveVerified( + "io_bazel_rules_kotlin", "src", "main", "kotlin", "compiler_lib.jar") + ) + ) + ) } }
diff --git a/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelUtils.kt b/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelUtils.kt new file mode 100644 index 0000000..311327e --- /dev/null +++ b/src/main/kotlin/io/bazel/kotlin/builder/utils/BazelUtils.kt
@@ -0,0 +1,93 @@ +/* + * 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.utils + +import java.io.File +import java.io.FileInputStream +import java.nio.charset.Charset +import java.nio.file.Paths +import java.util.* + +/** Utility class for getting runfiles on windows and *nix. */ +object BazelRunFiles { + private val isWindows = System.getProperty("os.name").toLowerCase().indexOf("win") >= 0 + /** + * Populated on windows. The RUNFILES_MANIFEST_FILE is set on platforms other then windows but it can be empty,] + */ + private val manifestFile: String? = + if (isWindows) { + checkNotNull(System.getenv("RUNFILES_MANIFEST_FILE")) { "RUNFILES_MANIFEST_FILE not set in environment" } + } else null + + private val javaRunFiles = Paths.get(System.getenv("JAVA_RUNFILES")) + + private val runfiles by lazy { + with(mutableMapOf<String, String>()) { + FileInputStream(manifestFile) + .bufferedReader(Charset.forName("UTF-8")) + .lines() + .forEach { it -> + val line = it.trim { it <= ' ' } + if (!line.isEmpty()) { + // TODO(bazel-team): This is buggy when the path contains spaces, we should fix the manifest format. + line.split(" ").also { + check(it.size == 2) { "RunFiles manifest entry $line contains more than one space" } + put(it[0], it[1]) + } + } + } + Collections.unmodifiableMap(this) + } + } + + /** + * Resolve a run file on windows or *nix. + */ + @JvmStatic + fun resolveVerified(vararg path: String): File { + check(path.isNotEmpty()) + val fromManifest = manifestFile?.let { mf -> + path.joinToString("/").let { rfPath -> + // trim off the external/ prefix if it is present. + val trimmedPath = + if (rfPath.startsWith("external/")) { + rfPath.replaceFirst("external/", "") + } else { + rfPath + } + File( + checkNotNull(runfiles[trimmedPath]) { + "runfile manifest $mf did not contain path mapping for $rfPath" + } + ) + }.also { + check(it.exists()) { "file $it resolved from runfiles did not exist" } + } + } + if(fromManifest != null) { + return fromManifest + } + + /// if it could not be resolved from the manifest then first try to resolve it directly. + val resolvedDirect = File(path.joinToString(File.separator)).takeIf { it.exists() } + if(resolvedDirect != null) { + return resolvedDirect + } + + // Try the java runfiles as the last resort. + return javaRunFiles.resolveVerified(path.joinToString(File.separator)) + } +} \ No newline at end of file
diff --git a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt index baa7f49..061b962 100644 --- a/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt +++ b/src/main/kotlin/io/bazel/kotlin/compiler/BazelK2JVMCompiler.kt
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.config.Services +import java.io.File @Suppress("unused") class BazelK2JVMCompiler(private val delegate: K2JVMCompiler = K2JVMCompiler()) { @@ -34,7 +35,7 @@ // https://github.com/bazelbuild/rules_kotlin/issues/69: remove once jetbrains adds a flag for it. args[i].startsWith("--friend-paths") -> { i++ - friendsPaths = args[i].split(":").toTypedArray() + friendsPaths = args[i].split(File.pathSeparator).toTypedArray() } else -> tally += args[i] }