Use kapt stubs for kotlin header jar for javac
When compling kotlin code with annotation processors we are generating java stubs for the kotlin sources using kapt, and parsing them in turbine when running the annotation processors. Passing --output to turbine will also compile the stubs into a header jar that can be used as a dependency to javac, allowing the javac and kotlinc rules to run in parallel. The turbine-apt header jar can't be used as the header jar for downstream modules as it doesn't contain the kotlin metadata needed by kotlinc rules, so the kotlinc gen-jvm-abi plugin output is still used for the module's final header jar. Test: TestKapt Bug: 222095735 Change-Id: I82d0900f3dc30f3e3ebd7cab0693dfe741d9b955
This commit is contained in:
30
java/base.go
30
java/base.go
@@ -1108,13 +1108,23 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
|
||||
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
|
||||
|
||||
if len(flags.processorPath) > 0 {
|
||||
useTurbineApt := len(flags.processorPath) > 0
|
||||
if useTurbineApt {
|
||||
// Use kapt for annotation processing
|
||||
kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
|
||||
kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
|
||||
kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
|
||||
srcJars = append(srcJars, kaptSrcJar)
|
||||
kotlinJars = append(kotlinJars, kaptResJar)
|
||||
kotlinTurbineAptHeaderJar := android.PathForModuleOut(ctx, "turbine-apt", "stubs-header.jar")
|
||||
kotlinTurbineAptSrcJar := android.PathForModuleOut(ctx, "turbine-apt", "anno-sources.jar")
|
||||
kotlinTurbineAptResJar := android.PathForModuleOut(ctx, "turbine-apt", "anno-res.jar")
|
||||
kotlinTurbineApt(ctx, kotlinTurbineAptHeaderJar, kotlinTurbineAptSrcJar, kotlinTurbineAptResJar,
|
||||
kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
|
||||
srcJars = append(srcJars, kotlinTurbineAptSrcJar)
|
||||
kotlinJars = append(kotlinJars, kotlinTurbineAptResJar)
|
||||
// When annotation processors are enabled we've already created java stubs for
|
||||
// kotlin files using kapt and compiled them in turbine-apt while running the
|
||||
// annotation processors, reuse the result as the kotlin header jar for the javac
|
||||
// action. It can't be used as the header jar for downstream modules to compile
|
||||
// against because it doesn't contain the kotlin-specific metadata that kotlinc
|
||||
// needs.
|
||||
flags.classpath = append(classpath{kotlinTurbineAptHeaderJar}, flags.classpath...)
|
||||
// Disable annotation processing in javac, it's already been handled by kapt
|
||||
flags.processorPath = nil
|
||||
flags.processors = nil
|
||||
@@ -1127,11 +1137,13 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||
return
|
||||
}
|
||||
|
||||
// Make javac rule depend on the kotlinc rule
|
||||
flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
|
||||
|
||||
kotlinJars = append(kotlinJars, kotlinJar)
|
||||
kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
|
||||
if !useTurbineApt {
|
||||
// When annotation processors are not enabled use the kotlinc gen-jvm-abi plugin
|
||||
// output as the header jar for javac in this module.
|
||||
flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
|
||||
}
|
||||
|
||||
// Jar kotlin classes into the final jar after javac
|
||||
if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
|
||||
|
@@ -415,7 +415,7 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.
|
||||
}
|
||||
|
||||
// TurbineApt produces a rule to run annotation processors using turbine.
|
||||
func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
|
||||
func TurbineApt(ctx android.ModuleContext, outputJar, outputSrcJar, outputResJar android.WritablePath,
|
||||
srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
|
||||
|
||||
turbineFlags, deps := turbineFlags(ctx, flags)
|
||||
@@ -426,8 +426,9 @@ func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.Wr
|
||||
turbineFlags += " " + flags.processorPath.FormTurbineClassPath("--processorpath ")
|
||||
turbineFlags += " --processors " + strings.Join(flags.processors, " ")
|
||||
|
||||
outputs := android.WritablePaths{outputSrcJar, outputResJar}
|
||||
outputFlags := "--gensrc_output " + outputSrcJar.String() + ".tmp " +
|
||||
outputs := android.WritablePaths{outputJar, outputSrcJar, outputResJar}
|
||||
outputFlags := "--output " + outputJar.String() + ".tmp " +
|
||||
"--gensrc_output " + outputSrcJar.String() + ".tmp " +
|
||||
"--resource_output " + outputResJar.String() + ".tmp"
|
||||
|
||||
rule := turbine
|
||||
@@ -442,7 +443,9 @@ func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.Wr
|
||||
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
|
||||
rule = turbineRE
|
||||
args["implicits"] = strings.Join(deps.Strings(), ",")
|
||||
args["rbeOutputs"] = outputSrcJar.String() + ".tmp," + outputResJar.String() + ".tmp"
|
||||
args["rbeOutputs"] = outputJar.String() + ".tmp," +
|
||||
outputSrcJar.String() + ".tmp," +
|
||||
outputResJar.String() + ".tmp"
|
||||
}
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: rule,
|
||||
|
@@ -163,11 +163,11 @@ var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupp
|
||||
"classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",
|
||||
"kotlinBuildFile", "name", "classesJarOut")
|
||||
|
||||
// kotlinKapt performs Kotlin-compatible annotation processing. It takes .kt and .java sources and srcjars, and runs
|
||||
// kotlinTurbineApt performs Kotlin-compatible annotation processing. It takes .kt and .java sources and srcjars, and runs
|
||||
// annotation processors over all of them, producing a srcjar of generated code in outputFile. The srcjar should be
|
||||
// added as an additional input to kotlinc and javac rules, and the javac rule should have annotation processing
|
||||
// disabled.
|
||||
func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile android.WritablePath,
|
||||
func kotlinTurbineApt(ctx android.ModuleContext, headerJarOutputFile, srcJarOutputFile, resJarOutputFile android.WritablePath,
|
||||
srcFiles, commonSrcFiles, srcJars android.Paths,
|
||||
flags javaBuilderFlags) {
|
||||
|
||||
@@ -231,7 +231,7 @@ func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile an
|
||||
// Then run turbine to perform annotation processing on the stubs and any .java srcFiles.
|
||||
javaSrcFiles := srcFiles.FilterByExt(".java")
|
||||
turbineSrcJars := append(android.Paths{kaptStubsJar}, srcJars...)
|
||||
TurbineApt(ctx, srcJarOutputFile, resJarOutputFile, javaSrcFiles, turbineSrcJars, flags)
|
||||
TurbineApt(ctx, headerJarOutputFile, srcJarOutputFile, resJarOutputFile, javaSrcFiles, turbineSrcJars, flags)
|
||||
}
|
||||
|
||||
// kapt converts a list of key, value pairs into a base64 encoded Java serialization, which is what kapt expects.
|
||||
|
@@ -155,22 +155,34 @@ func TestKapt(t *testing.T) {
|
||||
t.Errorf("expected %q in turbine-apt implicits %v", kaptStubs.Output.String(), kotlinc.Implicits.Strings())
|
||||
}
|
||||
|
||||
turbineAptSrcjarOutput := turbineApt.ImplicitOutputs[0]
|
||||
|
||||
// Test that the turbine-apt srcjar is a dependency of kotlinc and javac rules
|
||||
if !inList(turbineApt.Output.String(), kotlinc.Implicits.Strings()) {
|
||||
t.Errorf("expected %q in kotlinc implicits %v", turbineApt.Output.String(), kotlinc.Implicits.Strings())
|
||||
if !inList(turbineAptSrcjarOutput.String(), kotlinc.Implicits.Strings()) {
|
||||
t.Errorf("expected %q in kotlinc implicits %v", turbineAptSrcjarOutput.String(), kotlinc.Implicits.Strings())
|
||||
}
|
||||
if !inList(turbineApt.Output.String(), javac.Implicits.Strings()) {
|
||||
t.Errorf("expected %q in javac implicits %v", turbineApt.Output.String(), javac.Implicits.Strings())
|
||||
if !inList(turbineAptSrcjarOutput.String(), javac.Implicits.Strings()) {
|
||||
t.Errorf("expected %q in javac implicits %v", turbineAptSrcjarOutput.String(), javac.Implicits.Strings())
|
||||
}
|
||||
|
||||
// Test that the turbine-apt srcjar is extracted by the kotlinc and javac rules
|
||||
if kotlinc.Args["srcJars"] != turbineApt.Output.String() {
|
||||
t.Errorf("expected %q in kotlinc srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
|
||||
if kotlinc.Args["srcJars"] != turbineAptSrcjarOutput.String() {
|
||||
t.Errorf("expected %q in kotlinc srcjars %v", turbineAptSrcjarOutput.String(), kotlinc.Args["srcJars"])
|
||||
}
|
||||
if javac.Args["srcJars"] != turbineApt.Output.String() {
|
||||
t.Errorf("expected %q in javac srcjars %v", turbineApt.Output.String(), kotlinc.Args["srcJars"])
|
||||
if javac.Args["srcJars"] != turbineAptSrcjarOutput.String() {
|
||||
t.Errorf("expected %q in javac srcjars %v", turbineAptSrcjarOutput.String(), kotlinc.Args["srcJars"])
|
||||
}
|
||||
|
||||
// Test that the turbine-apt header jar is a dependency of the javac rules
|
||||
turbineAptHeaderjarOutput := turbineApt.Output
|
||||
android.AssertStringListContains(t, "javac dependency", javac.Implicits.Strings(), turbineAptHeaderjarOutput.String())
|
||||
android.AssertStringDoesContain(t, "javac classpath", javac.Args["classpath"], turbineAptHeaderjarOutput.String())
|
||||
|
||||
// Test that the kotlinc header jar is a not a dependency of the javac rules
|
||||
kotlincHeaderJarOutput := kotlinc.ImplicitOutput
|
||||
android.AssertStringListDoesNotContain(t, "javac dependency", javac.Implicits.Strings(), kotlincHeaderJarOutput.String())
|
||||
android.AssertStringDoesNotContain(t, "javac classpath", javac.Args["classpath"], kotlincHeaderJarOutput.String())
|
||||
|
||||
// Test that the processors are passed to kapt
|
||||
expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
|
||||
" -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
|
||||
|
Reference in New Issue
Block a user