Merge changes from topic "kapt" am: e153382e17 am: cae625c754

am: a2d2f2af1a

Change-Id: Ic3b8ef98f8bd5595762f6b28a7735bf57b62b1b3
This commit is contained in:
Colin Cross 2019-01-22 20:07:59 -08:00 committed by android-build-merger
commit 17bb64e300
9 changed files with 399 additions and 121 deletions

View File

@ -248,6 +248,7 @@ bootstrap_go_package {
"java/java.go",
"java/jdeps.go",
"java/java_resources.go",
"java/kotlin.go",
"java/prebuilt_apis.go",
"java/proto.go",
"java/sdk.go",
@ -260,6 +261,7 @@ bootstrap_go_package {
"java/dexpreopt_test.go",
"java/java_test.go",
"java/jdeps_test.go",
"java/kotlin_test.go",
"java/sdk_test.go",
],
pluginFor: ["soong_build"],

View File

@ -241,6 +241,7 @@ func TestArchConfig(buildDir string, env map[string]string) Config {
}
config.BuildOsVariant = config.Targets[BuildOs][0].String()
config.BuildOsCommonVariant = getCommonTargets(config.Targets[BuildOs])[0].String()
return testConfig
}

View File

@ -60,26 +60,6 @@ var (
"javacFlags", "bootClasspath", "classpath", "processorpath", "srcJars", "srcJarDir",
"outDir", "annoDir", "javaVersion")
kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
blueprint.RuleParams{
Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" && mkdir -p "$classesDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`${config.GenKotlinBuildFileCmd} $classpath $classesDir $out.rsp $srcJarDir/list > $kotlinBuildFile &&` +
`${config.KotlincCmd} $kotlincFlags ` +
`-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile && ` +
`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir`,
CommandDeps: []string{
"${config.KotlincCmd}",
"${config.KotlinCompilerJar}",
"${config.GenKotlinBuildFileCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
},
Rspfile: "$out.rsp",
RspfileContent: `$in`,
},
"kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile")
turbine = pctx.AndroidStaticRule("turbine",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@ -177,35 +157,6 @@ type javaBuilderFlags struct {
protoRoot bool
}
func TransformKotlinToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
srcFiles, srcJars android.Paths,
flags javaBuilderFlags) {
inputs := append(android.Paths(nil), srcFiles...)
var deps android.Paths
deps = append(deps, flags.kotlincClasspath...)
deps = append(deps, srcJars...)
ctx.Build(pctx, android.BuildParams{
Rule: kotlinc,
Description: "kotlinc",
Output: outputFile,
Inputs: inputs,
Implicits: deps,
Args: map[string]string{
"classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"),
"kotlincFlags": flags.kotlincFlags,
"srcJars": strings.Join(srcJars.Strings(), " "),
"classesDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
"srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
"kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
// http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
"kotlinJvmTarget": "1.8",
},
})
}
func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) {
@ -249,7 +200,7 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.
// ensure java does not fall back to the default bootclasspath.
bootClasspath = `--bootclasspath ""`
} else {
bootClasspath = strings.Join(flags.bootClasspath.FormTurbineClasspath("--bootclasspath"), " ")
bootClasspath = strings.Join(flags.bootClasspath.FormTurbineClasspath("--bootclasspath "), " ")
}
ctx.Build(pctx, android.BuildParams{
@ -262,7 +213,7 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.
"javacFlags": flags.javacFlags,
"bootClasspath": bootClasspath,
"srcJars": strings.Join(srcJars.Strings(), " "),
"classpath": strings.Join(flags.classpath.FormTurbineClasspath("--classpath"), " "),
"classpath": strings.Join(flags.classpath.FormTurbineClasspath("--classpath "), " "),
"outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(),
"javaVersion": flags.javaVersion,
},
@ -464,7 +415,7 @@ func (x *classpath) FormTurbineClasspath(optName string) []string {
}
flags := make([]string, len(*x))
for i, v := range *x {
flags[i] = optName + " " + v.String()
flags[i] = optName + v.String()
}
return flags

View File

@ -14,6 +14,8 @@
package config
import "strings"
var (
KotlinStdlibJar = "external/kotlinc/lib/kotlin-stdlib.jar"
KotlincIllegalFlags = []string{
@ -25,5 +27,14 @@ var (
func init() {
pctx.SourcePathVariable("KotlincCmd", "external/kotlinc/bin/kotlinc")
pctx.SourcePathVariable("KotlinCompilerJar", "external/kotlinc/lib/kotlin-compiler.jar")
pctx.SourcePathVariable("KotlinKaptJar", "external/kotlinc/lib/kotlin-annotation-processing.jar")
pctx.SourcePathVariable("KotlinStdlibJar", KotlinStdlibJar)
// These flags silence "Illegal reflective access" warnings when running kotlinc in OpenJDK9
pctx.StaticVariable("KotlincSuppressJDK9Warnings", strings.Join([]string{
"-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"-J--add-opens=java.base/sun.net.www.protocol.jar=ALL-UNNAMED",
}, " "))
}

View File

@ -85,8 +85,8 @@ func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
func (j *Module) d8Flags(ctx android.ModuleContext, flags javaBuilderFlags) ([]string, android.Paths) {
d8Flags := j.dexCommonFlags(ctx)
d8Flags = append(d8Flags, flags.bootClasspath.FormTurbineClasspath("--lib")...)
d8Flags = append(d8Flags, flags.classpath.FormTurbineClasspath("--lib")...)
d8Flags = append(d8Flags, flags.bootClasspath.FormTurbineClasspath("--lib ")...)
d8Flags = append(d8Flags, flags.classpath.FormTurbineClasspath("--lib ")...)
var d8Deps android.Paths
d8Deps = append(d8Deps, flags.bootClasspath...)

View File

@ -379,6 +379,7 @@ var (
frameworkResTag = dependencyTag{name: "framework-res"}
frameworkApkTag = dependencyTag{name: "framework-apk"}
kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
certificateTag = dependencyTag{name: "certificate"}
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
@ -483,6 +484,9 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
// Kotlin files
ctx.AddVariationDependencies(nil, kotlinStdlibTag, "kotlin-stdlib")
if len(j.properties.Annotation_processors) > 0 {
ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
}
}
if j.shouldInstrumentStatic(ctx) {
@ -564,6 +568,7 @@ type deps struct {
systemModules android.Path
aidlPreprocess android.OptionalPath
kotlinStdlib android.Paths
kotlinAnnotations android.Paths
}
func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
@ -723,6 +728,8 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
case kotlinStdlibTag:
deps.kotlinStdlib = dep.HeaderJars()
case kotlinAnnotationsTag:
deps.kotlinAnnotations = dep.HeaderJars()
}
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
@ -969,18 +976,28 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
flags.kotlincClasspath = append(flags.kotlincClasspath, deps.bootClasspath...)
flags.kotlincClasspath = append(flags.kotlincClasspath, deps.kotlinStdlib...)
flags.kotlincClasspath = append(flags.kotlincClasspath, deps.classpath...)
flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
if len(flags.processorPath) > 0 {
// Use kapt for annotation processing
kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
kotlinKapt(ctx, kaptSrcJar, kotlinSrcFiles, srcJars, flags)
srcJars = append(srcJars, kaptSrcJar)
// Disable annotation processing in javac, it's already been handled by kapt
flags.processorPath = nil
}
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
TransformKotlinToClasses(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags)
kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags)
if ctx.Failed() {
return
}
// Make javac rule depend on the kotlinc rule
flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
flags.classpath = append(flags.classpath, kotlinJar)
// Jar kotlin classes into the final jar after javac

View File

@ -121,6 +121,7 @@ func testContext(config android.Config, bp string,
"core.current.stubs",
"core.platform.api.stubs",
"kotlin-stdlib",
"kotlin-annotations",
}
for _, extra := range extraModules {
@ -571,68 +572,6 @@ func TestGeneratedSources(t *testing.T) {
}
}
func TestKotlin(t *testing.T) {
ctx := testJava(t, `
java_library {
name: "foo",
srcs: ["a.java", "b.kt"],
}
java_library {
name: "bar",
srcs: ["b.kt"],
libs: ["foo"],
static_libs: ["baz"],
}
java_library {
name: "baz",
srcs: ["c.java"],
}
`)
fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
fooKotlinc.Inputs[1].String() != "b.kt" {
t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, fooKotlinc.Inputs)
}
if len(fooJavac.Inputs) != 1 || fooJavac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
}
if !strings.Contains(fooJavac.Args["classpath"], fooKotlinc.Output.String()) {
t.Errorf("foo classpath %v does not contain %q",
fooJavac.Args["classpath"], fooKotlinc.Output.String())
}
if !inList(fooKotlinc.Output.String(), fooJar.Inputs.Strings()) {
t.Errorf("foo jar inputs %v does not contain %q",
fooJar.Inputs.Strings(), fooKotlinc.Output.String())
}
fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
if len(barKotlinc.Inputs) != 1 || barKotlinc.Inputs[0].String() != "b.kt" {
t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, barKotlinc.Inputs)
}
if !inList(fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
t.Errorf(`expected %q in bar implicits %v`,
fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
}
if !inList(bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
t.Errorf(`expected %q in bar implicits %v`,
bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
}
}
func TestTurbine(t *testing.T) {
ctx := testJava(t, `
java_library {

168
java/kotlin.go Normal file
View File

@ -0,0 +1,168 @@
// Copyright 2019 Google Inc. 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 java
import (
"bytes"
"encoding/base64"
"encoding/binary"
"strings"
"android/soong/android"
"github.com/google/blueprint"
)
var kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
blueprint.RuleParams{
Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" && mkdir -p "$classesDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`${config.GenKotlinBuildFileCmd} $classpath $classesDir $out.rsp $srcJarDir/list > $kotlinBuildFile &&` +
`${config.KotlincCmd} ${config.JavacHeapFlags} $kotlincFlags ` +
`-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile && ` +
`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir`,
CommandDeps: []string{
"${config.KotlincCmd}",
"${config.KotlinCompilerJar}",
"${config.GenKotlinBuildFileCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
},
Rspfile: "$out.rsp",
RspfileContent: `$in`,
},
"kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile")
// kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath,
srcFiles, srcJars android.Paths,
flags javaBuilderFlags) {
var deps android.Paths
deps = append(deps, flags.kotlincClasspath...)
deps = append(deps, srcJars...)
ctx.Build(pctx, android.BuildParams{
Rule: kotlinc,
Description: "kotlinc",
Output: outputFile,
Inputs: srcFiles,
Implicits: deps,
Args: map[string]string{
"classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"),
"kotlincFlags": flags.kotlincFlags,
"srcJars": strings.Join(srcJars.Strings(), " "),
"classesDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
"srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
"kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
// http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
"kotlinJvmTarget": "1.8",
},
})
}
var kapt = pctx.AndroidGomaStaticRule("kapt",
blueprint.RuleParams{
Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && mkdir -p "$srcJarDir" "$kaptDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`${config.GenKotlinBuildFileCmd} $classpath "" $out.rsp $srcJarDir/list > $kotlinBuildFile &&` +
`${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} $kotlincFlags ` +
`-Xplugin=${config.KotlinKaptJar} ` +
`-P plugin:org.jetbrains.kotlin.kapt3:sources=$kaptDir/sources ` +
`-P plugin:org.jetbrains.kotlin.kapt3:classes=$kaptDir/classes ` +
`-P plugin:org.jetbrains.kotlin.kapt3:stubs=$kaptDir/stubs ` +
`-P plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true ` +
`-P plugin:org.jetbrains.kotlin.kapt3:aptMode=stubsAndApt ` +
`-P plugin:org.jetbrains.kotlin.kapt3:javacArguments=$encodedJavacFlags ` +
`$kaptProcessorPath ` +
`-Xbuild-file=$kotlinBuildFile && ` +
`${config.SoongZipCmd} -jar -o $out -C $kaptDir/sources -D $kaptDir/sources`,
CommandDeps: []string{
"${config.KotlincCmd}",
"${config.KotlinCompilerJar}",
"${config.KotlinKaptJar}",
"${config.GenKotlinBuildFileCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
},
Rspfile: "$out.rsp",
RspfileContent: `$in`,
},
"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile")
// kotlinKapt 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, outputFile android.WritablePath,
srcFiles, srcJars android.Paths,
flags javaBuilderFlags) {
var deps android.Paths
deps = append(deps, flags.kotlincClasspath...)
deps = append(deps, srcJars...)
deps = append(deps, flags.processorPath...)
kaptProcessorPath := flags.processorPath.FormTurbineClasspath("-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=")
encodedJavacFlags := kaptEncodeFlags([][2]string{
{"-source", flags.javaVersion},
{"-target", flags.javaVersion},
})
ctx.Build(pctx, android.BuildParams{
Rule: kapt,
Description: "kapt",
Output: outputFile,
Inputs: srcFiles,
Implicits: deps,
Args: map[string]string{
"classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"),
"kotlincFlags": flags.kotlincFlags,
"srcJars": strings.Join(srcJars.Strings(), " "),
"srcJarDir": android.PathForModuleOut(ctx, "kapt", "srcJars").String(),
"kotlinBuildFile": android.PathForModuleOut(ctx, "kapt", "build.xml").String(),
"kaptProcessorPath": strings.Join(kaptProcessorPath, " "),
"kaptDir": android.PathForModuleOut(ctx, "kapt/gen").String(),
"encodedJavacFlags": encodedJavacFlags,
},
})
}
// kapt converts a list of key, value pairs into a base64 encoded Java serialization, which is what kapt expects.
func kaptEncodeFlags(options [][2]string) string {
buf := &bytes.Buffer{}
binary.Write(buf, binary.BigEndian, uint32(len(options)))
for _, option := range options {
binary.Write(buf, binary.BigEndian, uint16(len(option[0])))
buf.WriteString(option[0])
binary.Write(buf, binary.BigEndian, uint16(len(option[1])))
buf.WriteString(option[1])
}
header := &bytes.Buffer{}
header.Write([]byte{0xac, 0xed, 0x00, 0x05}) // java serialization header
if buf.Len() < 256 {
header.WriteByte(0x77) // blockdata
header.WriteByte(byte(buf.Len()))
} else {
header.WriteByte(0x7a) // blockdatalong
binary.Write(header, binary.BigEndian, uint32(buf.Len()))
}
return base64.StdEncoding.EncodeToString(append(header.Bytes(), buf.Bytes()...))
}

189
java/kotlin_test.go Normal file
View File

@ -0,0 +1,189 @@
// Copyright 2017 Google Inc. 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 java
import (
"strconv"
"strings"
"testing"
)
func TestKotlin(t *testing.T) {
ctx := testJava(t, `
java_library {
name: "foo",
srcs: ["a.java", "b.kt"],
}
java_library {
name: "bar",
srcs: ["b.kt"],
libs: ["foo"],
static_libs: ["baz"],
}
java_library {
name: "baz",
srcs: ["c.java"],
}
`)
fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
fooKotlinc.Inputs[1].String() != "b.kt" {
t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, fooKotlinc.Inputs)
}
if len(fooJavac.Inputs) != 1 || fooJavac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
}
if !strings.Contains(fooJavac.Args["classpath"], fooKotlinc.Output.String()) {
t.Errorf("foo classpath %v does not contain %q",
fooJavac.Args["classpath"], fooKotlinc.Output.String())
}
if !inList(fooKotlinc.Output.String(), fooJar.Inputs.Strings()) {
t.Errorf("foo jar inputs %v does not contain %q",
fooJar.Inputs.Strings(), fooKotlinc.Output.String())
}
fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
if len(barKotlinc.Inputs) != 1 || barKotlinc.Inputs[0].String() != "b.kt" {
t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, barKotlinc.Inputs)
}
if !inList(fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
t.Errorf(`expected %q in bar implicits %v`,
fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
}
if !inList(bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
t.Errorf(`expected %q in bar implicits %v`,
bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
}
}
func TestKapt(t *testing.T) {
ctx := testJava(t, `
java_library {
name: "foo",
srcs: ["a.java", "b.kt"],
annotation_processors: ["bar"],
}
java_library_host {
name: "bar",
}
`)
kapt := ctx.ModuleForTests("foo", "android_common").Rule("kapt")
kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
// Test that the kotlin and java sources are passed to kapt and kotlinc
if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" {
t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kapt.Inputs)
}
if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" || kotlinc.Inputs[1].String() != "b.kt" {
t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
}
// Test that only the java sources are passed to javac
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
}
// Test that the kapt srcjar is a dependency of kotlinc and javac rules
if !inList(kapt.Output.String(), kotlinc.Implicits.Strings()) {
t.Errorf("expected %q in kotlinc implicits %v", kapt.Output.String(), kotlinc.Implicits.Strings())
}
if !inList(kapt.Output.String(), javac.Implicits.Strings()) {
t.Errorf("expected %q in javac implicits %v", kapt.Output.String(), javac.Implicits.Strings())
}
// Test that the kapt srcjar is extracted by the kotlinc and javac rules
if kotlinc.Args["srcJars"] != kapt.Output.String() {
t.Errorf("expected %q in kotlinc srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
}
if javac.Args["srcJars"] != kapt.Output.String() {
t.Errorf("expected %q in javac srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
}
}
func TestKaptEncodeFlags(t *testing.T) {
// Compares the kaptEncodeFlags against the results of the example implementation at
// https://kotlinlang.org/docs/reference/kapt.html#apjavac-options-encoding
tests := []struct {
in [][2]string
out string
}{
{
// empty input
in: [][2]string{},
out: "rO0ABXcEAAAAAA==",
},
{
// common input
in: [][2]string{
{"-source", "1.8"},
{"-target", "1.8"},
},
out: "rO0ABXcgAAAAAgAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjg=",
},
{
// input that serializes to a 255 byte block
in: [][2]string{
{"-source", "1.8"},
{"-target", "1.8"},
{"a", strings.Repeat("b", 218)},
},
out: "rO0ABXf/AAAAAwAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjgAAWEA2mJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJi",
},
{
// input that serializes to a 256 byte block
in: [][2]string{
{"-source", "1.8"},
{"-target", "1.8"},
{"a", strings.Repeat("b", 219)},
},
out: "rO0ABXoAAAEAAAAAAwAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjgAAWEA22JiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYg==",
},
{
// input that serializes to a 257 byte block
in: [][2]string{
{"-source", "1.8"},
{"-target", "1.8"},
{"a", strings.Repeat("b", 220)},
},
out: "rO0ABXoAAAEBAAAAAwAHLXNvdXJjZQADMS44AActdGFyZ2V0AAMxLjgAAWEA3GJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmI=",
},
}
for i, test := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
got := kaptEncodeFlags(test.in)
if got != test.out {
t.Errorf("\nwant %q\n got %q", test.out, got)
}
})
}
}