blob: 54d3d2a8983e9d84f2b233b7459199fda4fb95c3 [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.inject.Inject
import com.google.inject.Provider
import com.google.inject.Singleton
import io.bazel.kotlin.builder.mode.jvm.KotlinJvmCompilationExecutor
import io.bazel.kotlin.builder.utils.ArgMap
import io.bazel.kotlin.builder.utils.ArgMaps
import io.bazel.kotlin.model.KotlinModel
import java.nio.file.Files
import java.nio.file.Paths
@Singleton
@Suppress("MemberVisibilityCanBePrivate")
class KotlinBuilder @Inject internal constructor(
private val commandBuilder: BuildCommandBuilder,
private val jarToolInvoker: KotlinToolchain.JarToolInvoker,
private val compilationExector: KotlinJvmCompilationExecutor
) : CommandLineProgram {
fun execute(command: KotlinModel.BuilderCommand): Int =
prepareForExecution(command).let { doExecute(it) }
fun execute(args: List<String>): Int =
execute(ArgMaps.from(args))
fun execute(args: ArgMap): Int =
prepareForExecution(commandBuilder.fromInput(args)).let {
execute(it)
}
private fun doExecute(command: KotlinModel.BuilderCommand): Int {
return try {
compilationExector.compile(command)
0
} catch (ex: CompilationStatusException) {
ex.status
}
}
private fun prepareForExecution(originalCommand: KotlinModel.BuilderCommand): KotlinModel.BuilderCommand {
ensureOutputDirectories(originalCommand)
return expandWithSourceJarSources(originalCommand)
}
private fun ensureOutputDirectories(command: KotlinModel.BuilderCommand) {
Files.createDirectories(Paths.get(command.outputs.classDirectory))
Files.createDirectories(Paths.get(command.outputs.tempDirectory))
Files.createDirectories(Paths.get(command.outputs.sourceGenDir))
}
/**
* If any sourcejars were provided expand the jars sources and create a new [KotlinModel.BuilderCommand] with the
* Java and Kotlin sources merged in.
*/
private fun expandWithSourceJarSources(command: KotlinModel.BuilderCommand): KotlinModel.BuilderCommand =
if (command.inputs.sourceJarsList.isEmpty()) {
command
} else {
val sourceUnpackDirectory =
Paths.get(command.outputs.tempDirectory).let {
it.resolve("_srcjars").toFile().let {
try {
it.mkdirs(); it
} catch (ex: Exception) {
throw RuntimeException("could not create unpack directory at $it", ex)
}
}
}
for (sourceJar in command.inputs.sourceJarsList) {
jarToolInvoker.invoke(
listOf("xf", Paths.get(sourceJar).toAbsolutePath().toString()), sourceUnpackDirectory)
}
commandBuilder.withSources(
command,
sourceUnpackDirectory
.walk()
.filter { it.name.endsWith(".kt") || it.name.endsWith(".java") }
.map { it.toString() }
.iterator()
)
}
override fun apply(args: List<String>): Int {
return execute(args)
}
companion object {
@JvmStatic
fun main(args: Array<String>) {
val worker = KotlinToolchain.createInjector(Provider { System.err }).getInstance(BazelWorker::class.java)
System.exit(worker.apply(args.toList()))
}
}
}