mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 08:27:12 -07:00
Add support for kapt3.
This commit is contained in:
parent
afacd86267
commit
9e1c9bd87b
2 changed files with 151 additions and 96 deletions
|
@ -3,8 +3,8 @@ package com.beust.kobalt.plugin.apt
|
|||
import com.beust.kobalt.Constants
|
||||
import com.beust.kobalt.TaskResult
|
||||
import com.beust.kobalt.api.*
|
||||
import com.beust.kobalt.api.annotation.AnnotationDefault
|
||||
import com.beust.kobalt.api.annotation.Directive
|
||||
import com.beust.kobalt.api.annotation.Task
|
||||
import com.beust.kobalt.homeDir
|
||||
import com.beust.kobalt.internal.CompilerUtils
|
||||
import com.beust.kobalt.maven.DependencyManager
|
||||
|
@ -12,6 +12,7 @@ import com.beust.kobalt.maven.aether.Filters
|
|||
import com.beust.kobalt.maven.aether.Scope
|
||||
import com.beust.kobalt.maven.dependency.FileDependency
|
||||
import com.beust.kobalt.misc.KFiles
|
||||
import com.beust.kobalt.misc.KobaltLogger
|
||||
import com.beust.kobalt.misc.warn
|
||||
import com.beust.kobalt.plugin.kotlin.KotlinPlugin
|
||||
import com.google.common.collect.ArrayListMultimap
|
||||
|
@ -21,7 +22,7 @@ import java.util.*
|
|||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* The AptPlugin has two components:
|
||||
* The AptPlugin manages both apt and kapt. Each of them has two components:
|
||||
* 1) A new apt directive inside a dependency{} block (similar to compile()) that declares where
|
||||
* the annotation processor is found
|
||||
* 2) An apt{} configuration on Project that lets the user configure how the annotation is performed
|
||||
|
@ -30,13 +31,53 @@ import javax.inject.Singleton
|
|||
@Singleton
|
||||
class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, val kotlinPlugin: KotlinPlugin,
|
||||
val compilerUtils: CompilerUtils)
|
||||
: BasePlugin(), ICompilerFlagContributor, ISourceDirectoryContributor {
|
||||
: BasePlugin(), ICompilerFlagContributor, ISourceDirectoryContributor, IClasspathContributor, ITaskContributor {
|
||||
|
||||
// ISourceDirectoryContributor
|
||||
companion object {
|
||||
const val PLUGIN_NAME = "Apt"
|
||||
const val KAPT_CONFIG = "kaptConfig"
|
||||
const val APT_CONFIG = "aptConfig"
|
||||
}
|
||||
|
||||
override val name = PLUGIN_NAME
|
||||
|
||||
var kaptConfig: KaptConfig? = null
|
||||
|
||||
override fun apply(project: Project, context: KobaltContext) {
|
||||
super.apply(project, context)
|
||||
kaptConfig = kaptConfigs[project.name]
|
||||
|
||||
// Delete the output directories
|
||||
listOf(aptConfigs[project.name]?.outputDir, kaptConfig?.outputDir)
|
||||
.filterNotNull()
|
||||
.distinct()
|
||||
.map { generatedDir(project, it) }
|
||||
.forEach {
|
||||
it.normalize().absolutePath.let { path ->
|
||||
context.logger.log(project.name, 1, " Deleting " + path)
|
||||
val success = it.deleteRecursively()
|
||||
if (!success) warn(" Couldn't delete " + path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IClasspathContributor
|
||||
override fun classpathEntriesFor(project: Project?, context: KobaltContext): Collection<IClasspathDependency> {
|
||||
val result = arrayListOf<IClasspathDependency>()
|
||||
if (project != null && kaptConfig != null) {
|
||||
kaptConfig?.let { config ->
|
||||
val c = generatedClasses(project, context, config.outputDir)
|
||||
File(c).mkdirs()
|
||||
result.add(FileDependency(c))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun generatedDir(project: Project, outputDir: String) : File
|
||||
= File(KFiles.joinDir(project.directory, KFiles.KOBALT_BUILD_DIR, outputDir))
|
||||
|
||||
// ISourceDirectoryContributor
|
||||
override fun sourceDirectoriesFor(project: Project, context: KobaltContext): List<File> {
|
||||
val result = arrayListOf<File>()
|
||||
aptConfigs[project.name]?.let { config ->
|
||||
|
@ -50,29 +91,6 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, va
|
|||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PLUGIN_NAME = "Apt"
|
||||
const val KAPT_CONFIG = "kaptConfig"
|
||||
const val APT_CONFIG = "aptConfig"
|
||||
}
|
||||
|
||||
override val name = PLUGIN_NAME
|
||||
|
||||
override fun apply(project: Project, context: KobaltContext) {
|
||||
super.apply(project, context)
|
||||
listOf(aptConfigs[project.name]?.outputDir, aptConfigs[project.name]?.outputDir)
|
||||
.filterNotNull()
|
||||
.distinct()
|
||||
.map { generatedDir(project, it) }
|
||||
.forEach {
|
||||
it.normalize().absolutePath.let { path ->
|
||||
context.logger.log(project.name, 1, " Deleting " + path)
|
||||
val success = it.deleteRecursively()
|
||||
if (!success) warn(" Couldn't delete " + path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generated(project: Project, context: KobaltContext, outputDir: String) =
|
||||
KFiles.joinAndMakeDir(project.directory, project.buildDirectory, outputDir,
|
||||
context.variant.toIntermediateDir())
|
||||
|
@ -84,13 +102,32 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, va
|
|||
private fun generatedClasses(project: Project, context: KobaltContext, outputDir: String) =
|
||||
KFiles.joinDir(generated(project, context, outputDir), "classes")
|
||||
|
||||
// @Task(name = "compileKapt", dependsOn = arrayOf("runKapt"), reverseDependsOn = arrayOf("compile"))
|
||||
// ITaskContributor
|
||||
override fun tasksFor(project: Project, context: KobaltContext): List<DynamicTask> {
|
||||
val result =
|
||||
if (kaptConfig != null) {
|
||||
listOf(
|
||||
DynamicTask(this, "runKapt", "Run kapt", AnnotationDefault.GROUP, project,
|
||||
reverseDependsOn = listOf("compile"), runAfter = listOf("clean"),
|
||||
closure = {p: Project -> taskRunKapt(p)}),
|
||||
DynamicTask(this, "compileKapt", "Compile the sources generated by kapt",
|
||||
AnnotationDefault.GROUP, project,
|
||||
dependsOn = listOf("runKapt"), reverseDependsOn = listOf("compile"),
|
||||
closure = {p: Project -> taskCompileKapt(p)})
|
||||
)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun taskCompileKapt(project: Project) : TaskResult {
|
||||
var success = true
|
||||
kaptConfigs[project.name]?.let { config ->
|
||||
val sourceDirs = listOf(
|
||||
generatedStubs(project, context, config.outputDir),
|
||||
generatedSources(project, context, config.outputDir))
|
||||
val sourceFiles = KFiles.findSourceFiles(project.directory, sourceDirs, listOf("kt", "java")).toList()
|
||||
val sourceFiles = KFiles.findSourceFiles(project.directory, sourceDirs, listOf("kt")).toList()
|
||||
val buildDirectory = File(KFiles.joinDir(project.directory,
|
||||
generatedClasses(project, context, config.outputDir)))
|
||||
val flags = listOf<String>()
|
||||
|
@ -98,10 +135,10 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, va
|
|||
buildDirectory, flags, emptyList(), forceRecompile = true)
|
||||
|
||||
val cr = compilerUtils.invokeCompiler(project, context, kotlinPlugin.compiler, cai)
|
||||
println("")
|
||||
success = cr.failedResult == null
|
||||
}
|
||||
|
||||
return TaskResult()
|
||||
return TaskResult(success)
|
||||
}
|
||||
|
||||
val annotationDependencyId = "org.jetbrains.kotlin:kotlin-annotation-processing:" +
|
||||
|
@ -121,31 +158,41 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, va
|
|||
return allDeps
|
||||
}
|
||||
|
||||
// @Task(name = "runKapt", reverseDependsOn = arrayOf("compile"), runAfter = arrayOf("clean"))
|
||||
fun taskRunKapt(project: Project) : TaskResult {
|
||||
var success = true
|
||||
val flags = arrayListOf<String>()
|
||||
kaptConfigs[project.name]?.let { config ->
|
||||
kaptConfig?.let { config ->
|
||||
|
||||
fun kaptPluginFlag(flagValue: String): String {
|
||||
return "plugin:org.jetbrains.kotlin.kapt3:$flagValue"
|
||||
}
|
||||
|
||||
val generated = generated(project, context, config.outputDir)
|
||||
val generatedSources = generatedSources(project, context, config.outputDir)
|
||||
val generatedSources = generatedSources(project, context, config.outputDir).replace("//", "/")
|
||||
File(generatedSources).mkdirs()
|
||||
|
||||
//
|
||||
// Tell the Kotlin compiler to use the annotation plug-in
|
||||
//
|
||||
val allDeps = allDependencies()
|
||||
flags.add("-Xplugin")
|
||||
flags.add(annotationProcessorDependency().jarFile.get().absolutePath)
|
||||
flags.add("-P")
|
||||
val kaptPluginFlags = arrayListOf<String>()
|
||||
// kaptPluginFlags.add(kaptPluginFlag("aptOnly=true"))
|
||||
|
||||
kaptPluginFlags.add(kaptPluginFlag("sources=" + generatedSources))
|
||||
kaptPluginFlags.add(kaptPluginFlag("classes=" + generatedClasses(project, context, config.outputDir)))
|
||||
kaptPluginFlags.add(kaptPluginFlag("stubs=" + generatedStubs(project, context, config.outputDir)))
|
||||
kaptPluginFlags.add(kaptPluginFlag("verbose=true"))
|
||||
kaptPluginFlags.add(kaptPluginFlag("aptOnly=false"))
|
||||
//
|
||||
// Pass options to the annotation plugin
|
||||
//
|
||||
fun kaptPluginFlag(flagValue: String) = "plugin:org.jetbrains.kotlin.kapt3:$flagValue"
|
||||
val kaptPluginFlags = arrayListOf<String>()
|
||||
val verbose = KobaltLogger.LOG_LEVEL >= 2
|
||||
listOf("sources=" + generatedSources,
|
||||
"classes=" + generatedClasses(project, context, config.outputDir),
|
||||
"stubs=" + generatedStubs(project, context, config.outputDir),
|
||||
"verbose=$verbose",
|
||||
"aptOnly=true").forEach {
|
||||
kaptPluginFlags.add(kaptPluginFlag(it))
|
||||
}
|
||||
|
||||
//
|
||||
// Dependencies for the annotation plug-in and the generation
|
||||
//
|
||||
val dependencies = dependencyManager.calculateDependencies(project, context,
|
||||
Filters.EXCLUDE_OPTIONAL_FILTER,
|
||||
listOf(Scope.COMPILE),
|
||||
|
@ -159,35 +206,30 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, va
|
|||
listOf("-language-version", "1.1", " -api-version", "1.1").forEach {
|
||||
flags.add(it)
|
||||
}
|
||||
val sourceFiles =
|
||||
// KFiles.findSourceFiles(project.directory,
|
||||
// listOf("src/tmp/kotlin"),
|
||||
// listOf("kt"))
|
||||
// .toList()
|
||||
|
||||
KFiles.findSourceFiles(project.directory, project.sourceDirectories, listOf("kt")).toList() +
|
||||
generatedSources
|
||||
//
|
||||
val sourceFiles =
|
||||
KFiles.findSourceFiles(project.directory, project.sourceDirectories, listOf("kt"))
|
||||
.toList() + generatedSources
|
||||
val buildDirectory = File(KFiles.joinDir(project.directory, generated))
|
||||
val cai = CompilerActionInfo(project.directory, allDeps, sourceFiles, listOf(".kt"),
|
||||
buildDirectory, flags, emptyList(), forceRecompile = true)
|
||||
|
||||
println("FLAGS: " + flags.joinToString("\n"))
|
||||
println(" " + kaptPluginFlags.joinToString("\n "))
|
||||
context.logger.log(project.name, 2, " " + kaptPluginFlags.joinToString("\n "))
|
||||
val cr = compilerUtils.invokeCompiler(project, context, kotlinPlugin.compiler, cai)
|
||||
println("")
|
||||
success = cr.failedResult == null
|
||||
}
|
||||
|
||||
return TaskResult()
|
||||
return TaskResult(success)
|
||||
}
|
||||
|
||||
// ICompilerFlagContributor
|
||||
override fun compilerFlagsFor(project: Project, context: KobaltContext, currentFlags: List<String>,
|
||||
suffixesBeingCompiled: List<String>): List<String> {
|
||||
if (!suffixesBeingCompiled.contains("java")) return emptyList()
|
||||
|
||||
val result = arrayListOf<String>()
|
||||
|
||||
// Only run for Java files
|
||||
if (!suffixesBeingCompiled.contains("java")) return emptyList()
|
||||
|
||||
fun addFlags(outputDir: String) {
|
||||
aptDependencies[project.name]?.let {
|
||||
result.add("-s")
|
||||
|
@ -199,10 +241,6 @@ class AptPlugin @Inject constructor(val dependencyManager: DependencyManager, va
|
|||
addFlags(config.outputDir)
|
||||
}
|
||||
|
||||
kaptConfigs[project.name]?.let { config ->
|
||||
addFlags(config.outputDir)
|
||||
}
|
||||
|
||||
context.logger.log(project.name, 2, "New flags from apt: " + result.joinToString(" "))
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ class KotlinCompiler @Inject constructor(
|
|||
var filesToCompile = 0
|
||||
if (! info.outputDir.path.endsWith("ript.jar")) {
|
||||
// Don't display the message if compiling Build.kt
|
||||
if (info.sourceFiles.isNotEmpty()) {
|
||||
filesToCompile =
|
||||
info.sourceFiles.map(::File).map {
|
||||
if (it.isDirectory) KFiles.findRecursively(it).size else 1
|
||||
|
@ -53,6 +54,7 @@ class KotlinCompiler @Inject constructor(
|
|||
kobaltLog.log(projectName ?: "", 1,
|
||||
" Kotlin $version compiling " + Strings.pluralizeAll(filesToCompile, "file"))
|
||||
}
|
||||
}
|
||||
val cp = compilerFirst(info.dependencies.map { it.jarFile.get() })
|
||||
val infoDir = info.directory
|
||||
val outputDir =
|
||||
|
@ -135,7 +137,9 @@ class KotlinCompiler @Inject constructor(
|
|||
val friends = info.friendPaths.toTypedArray()
|
||||
|
||||
// Collect the compiler args from kotlinCompiler{} and from settings.xml and parse them
|
||||
val args2 = (kotlinConfig(project)?.args ?: arrayListOf<String>()) +
|
||||
val args2 =
|
||||
info.compilerArgs +
|
||||
(kotlinConfig(project)?.args ?: arrayListOf<String>()) +
|
||||
(settings.kobaltCompilerFlags?.split(" ") ?: listOf<String>())
|
||||
val args = K2JVMCompilerArguments()
|
||||
val compiler = K2JVMCompiler()
|
||||
|
@ -185,13 +189,27 @@ class KotlinCompiler @Inject constructor(
|
|||
|
||||
fun logk(level: Int, message: CharSequence) = kobaltLog.log(projectName, level, message)
|
||||
|
||||
logk(2, " Invoking K2JVMCompiler with arguments:"
|
||||
fun pluginClasspaths(args: K2JVMCompilerArguments) : String {
|
||||
var result = ""
|
||||
args.pluginClasspaths?.forEach {
|
||||
result += " -Xplugin " + it
|
||||
}
|
||||
args.pluginOptions?.let {
|
||||
result += " -P "
|
||||
result += it.joinToString(",")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
logk(2, " Invoking K2JVMCompiler with arguments: kotlinc "
|
||||
+ if (args.skipMetadataVersionCheck) " -Xskip-metadata-version-check" else ""
|
||||
+ " -moduleName " + args.moduleName
|
||||
+ " -d " + args.destination
|
||||
+ " -friendPaths " + args.friendPaths.joinToString(";")
|
||||
+ " -classpath " + args.classpath
|
||||
+ pluginClasspaths(args)
|
||||
+ " " + sourceFiles.joinToString(" "))
|
||||
logk(2, " Additional kotlinc arguments: "
|
||||
+ " -moduleName " + args.moduleName
|
||||
+ " -friendPaths " + args.friendPaths.joinToString(";"))
|
||||
val collector = object : MessageCollector {
|
||||
override fun clear() {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
|
@ -214,7 +232,6 @@ class KotlinCompiler @Inject constructor(
|
|||
message: String, location: CompilerMessageLocation) {
|
||||
if (severity.isError) {
|
||||
"Couldn't compile file: ${dump(location, message)}".let { fullMessage ->
|
||||
System.err.println(fullMessage)
|
||||
throw KobaltException(fullMessage)
|
||||
}
|
||||
} else if (severity == CompilerMessageSeverity.WARNING && KobaltLogger.LOG_LEVEL >= 2) {
|
||||
|
@ -224,10 +241,10 @@ class KotlinCompiler @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.setProperty("kotlin.incremental.compilation", "true")
|
||||
// TODO: experimental should be removed as soon as it becomes standard
|
||||
System.setProperty("kotlin.incremental.compilation.experimental", "true")
|
||||
//
|
||||
// System.setProperty("kotlin.incremental.compilation", "true")
|
||||
// // TODO: experimental should be removed as soon as it becomes standard
|
||||
// System.setProperty("kotlin.incremental.compilation.experimental", "true")
|
||||
|
||||
val result =
|
||||
if (cliArgs.noIncrementalKotlin || Kobalt.context?.internalContext?.noIncrementalKotlin ?: false) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue