blob: f90042ad22f35f9438effda6a12a8713d661fe15 [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.tasks
import io.bazel.kotlin.builder.tasks.jvm.KotlinJvmTaskExecutor
import io.bazel.kotlin.builder.toolchain.CompilationStatusException
import io.bazel.kotlin.builder.utils.ArgMaps
import io.bazel.kotlin.builder.utils.IS_JVM_SOURCE_FILE
import io.bazel.kotlin.builder.utils.ensureDirectories
import io.bazel.kotlin.builder.utils.expandWithSources
import io.bazel.kotlin.builder.utils.jars.SourceJarExtractor
import io.bazel.kotlin.model.KotlinModel
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.Files
import java.nio.file.Paths
import java.util.regex.Pattern
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
@Suppress("MemberVisibilityCanBePrivate")
class KotlinBuilder @Inject internal constructor(
private val taskBuilder: TaskBuilder,
private val jvmTaskExecutor: KotlinJvmTaskExecutor
) : CommandLineProgram {
companion object {
// regex that matches the regular bazel param file naming convention.
private val STANDARD_FLAGFILE_RE = Pattern.compile(""".*.jar-\d+.params$""").toRegex()
}
fun execute(args: List<String>): Int {
check(args.isNotEmpty() && args[0].startsWith("--flagfile=")) { "no flag file supplied" }
val flagFile = args[0].replace("--flagfile=", "")
val flagFilePath = Paths.get(flagFile)
check(flagFilePath.toFile().exists()) { "flagfile $flagFile does not exist" }
val task = when {
STANDARD_FLAGFILE_RE.matches(flagFile) -> {
Files.readAllLines(flagFilePath, UTF_8).let { loadedFlags ->
ArgMaps.from(loadedFlags).let {
taskBuilder.fromInput(it)
}
}
}
else -> throw IllegalStateException("unknown flag file format for $flagFile")
}
return execute(task)
}
fun execute(command: KotlinModel.CompilationTask): Int {
ensureDirectories(
command.directories.classes,
command.directories.temp,
command.directories.generatedSources,
command.directories.generatedClasses
)
val updatedCommand = expandWithSourceJarSources(command)
return try {
jvmTaskExecutor.compile(updatedCommand)
0
} catch (ex: CompilationStatusException) {
ex.status
}
}
/**
* If any sourcejars were provided expand the jars sources and create a new [KotlinModel.CompilationTask] with the
* Java and Kotlin sources merged in.
*/
private fun expandWithSourceJarSources(command: KotlinModel.CompilationTask): KotlinModel.CompilationTask =
if (command.inputs.sourceJarsList.isEmpty()) {
command
} else {
SourceJarExtractor(
destDir = Paths.get(command.directories.temp).resolve("_srcjars"),
fileMatcher = IS_JVM_SOURCE_FILE
).also {
it.jarFiles.addAll(command.inputs.sourceJarsList.map { Paths.get(it) })
it.execute()
}.let {
command.expandWithSources(it.sourcesList.iterator())
}
}
override fun apply(args: List<String>): Int {
return execute(args)
}
}