blob: 8efabd077d497140908bb43ec4d395ff04b59c1b [file] [log] [blame]
/*
* 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
import com.google.common.collect.ImmutableSet
import com.google.inject.*
import com.google.inject.util.Modules
import io.bazel.kotlin.builder.utils.resolveVerified
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
import org.jetbrains.kotlin.preloading.Preloader
import java.io.File
import java.io.PrintStream
import java.io.PrintWriter
import java.nio.file.Path
import java.nio.file.Paths
import javax.inject.Qualifier
class KotlinToolchain private constructor(
internal val javaHome: Path,
val kotlinHome: Path,
internal val classLoader: ClassLoader,
val kotlinStandardLibraries: ImmutableSet<String> = ImmutableSet.of(
"kotlin-stdlib.jar",
"kotlin-stdlib-jdk7.jar",
"kotlin-stdlib-jdk8.jar"
)
) {
companion object {
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", "kotlin", "builder", "compiler_lib.jar")
if(!isJdk9OrNewer) {
it += javaHome.resolveVerified("lib", "tools.jar")
}
}
return ClassPreloadingUtils.preloadClasses(
preloadJars,
Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE,
ClassLoader.getSystemClassLoader(),
null
)
}
private fun createToolchain(): KotlinToolchain {
val kotlinHome = Paths.get("external", "com_github_jetbrains_kotlin")
val javaHome = Paths.get(System.getProperty("java.home")).let {
it.takeIf { !it.endsWith(Paths.get("jre")) } ?: it.parent
}
return KotlinToolchain(javaHome, kotlinHome, createClassLoader(javaHome, kotlinHome))
}
/**
* @param outputProvider A provider for the output stream to write to. A provider is used here as the System.err
* gets rebound when the worker is executing.
*/
@JvmStatic
fun createInjector(outputProvider: Provider<PrintStream>, overrides: Module? = null): Injector {
val toolchain = createToolchain()
val module = object : AbstractModule() {
override fun configure() {
bind(KotlinToolchain::class.java).toInstance(toolchain)
bind(PrintStream::class.java).toProvider(outputProvider)
install(KotlinToolchainModule)
}
}
return Guice.createInjector(
overrides?.let { Modules.override(module).with(it) } ?: module
)
}
}
data class CompilerPlugin(val jarPath: String, val id: String) {
@Qualifier
annotation class Kapt3
}
interface JavacInvoker {
fun compile(args: Array<String>): Int
fun compile(args: Array<String>, out: PrintWriter): Int
}
interface JDepsInvoker {
fun run(args: Array<String>, out: PrintWriter): Int
}
interface KotlincInvoker {
fun compile(args: Array<String>, out: PrintStream): Int
}
interface JarToolInvoker {
fun invoke(args: List<String>, directory: File? = null)
}
}