diff --git a/java/aar.go b/java/aar.go index d8db19251..e0bea5df3 100644 --- a/java/aar.go +++ b/java/aar.go @@ -694,6 +694,10 @@ func (a *AARImport) ExportedSdkLibs() []string { return nil } +func (d *AARImport) ExportedPlugins() (android.Paths, []string) { + return nil, nil +} + func (a *AARImport) SrcJarArgs() ([]string, android.Paths) { return nil, nil } diff --git a/java/device_host_converter.go b/java/device_host_converter.go index 14db52152..15244184e 100644 --- a/java/device_host_converter.go +++ b/java/device_host_converter.go @@ -162,6 +162,10 @@ func (d *DeviceHostConverter) ExportedSdkLibs() []string { return nil } +func (d *DeviceHostConverter) ExportedPlugins() (android.Paths, []string) { + return nil, nil +} + func (d *DeviceHostConverter) SrcJarArgs() ([]string, android.Paths) { return d.srcJarArgs, d.srcJarDeps } diff --git a/java/java.go b/java/java.go index d4f65ba42..1638e0c9f 100644 --- a/java/java.go +++ b/java/java.go @@ -145,6 +145,9 @@ type CompilerProperties struct { // List of modules to use as annotation processors Plugins []string + // List of modules to export to libraries that directly depend on this library as annotation processors + Exported_plugins []string + // The number of Java source entries each Javac instance can process Javac_shard_size *int64 @@ -360,10 +363,16 @@ type Module struct { // manifest file to use instead of properties.Manifest overrideManifest android.OptionalPath - // list of SDK lib names that this java moudule is exporting + // list of SDK lib names that this java module is exporting exportedSdkLibs []string - // list of source files, collected from srcFiles with uniqie java and all kt files, + // list of plugins that this java module is exporting + exportedPluginJars android.Paths + + // list of plugins that this java module is exporting + exportedPluginClasses []string + + // list of source files, collected from srcFiles with unique java and all kt files, // will be used by android.IDEInfo struct expandIDEInfoCompiledSrcs []string @@ -410,6 +419,7 @@ type Dependency interface { DexJar() android.Path AidlIncludeDirs() android.Paths ExportedSdkLibs() []string + ExportedPlugins() (android.Paths, []string) SrcJarArgs() ([]string, android.Paths) BaseModuleName() string } @@ -452,6 +462,7 @@ var ( libTag = dependencyTag{name: "javalib"} java9LibTag = dependencyTag{name: "java9lib"} pluginTag = dependencyTag{name: "plugin"} + exportedPluginTag = dependencyTag{name: "exported-plugin"} bootClasspathTag = dependencyTag{name: "bootclasspath"} systemModulesTag = dependencyTag{name: "system modules"} frameworkResTag = dependencyTag{name: "framework-res"} @@ -561,6 +572,7 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...) ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...) + ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...) android.ProtoDeps(ctx, &j.protoProperties) if j.hasSrcExt(".proto") { @@ -800,6 +812,8 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { // sdk lib names from dependencies are re-exported j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) + pluginJars, pluginClasses := dep.ExportedPlugins() + addPlugins(&deps, pluginJars, pluginClasses...) case java9LibTag: deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars()...) case staticLibTag: @@ -810,16 +824,31 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { // sdk lib names from dependencies are re-exported j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) + pluginJars, pluginClasses := dep.ExportedPlugins() + addPlugins(&deps, pluginJars, pluginClasses...) case pluginTag: if plugin, ok := dep.(*Plugin); ok { - deps.processorPath = append(deps.processorPath, dep.ImplementationAndResourcesJars()...) if plugin.pluginProperties.Processor_class != nil { - deps.processorClasses = append(deps.processorClasses, *plugin.pluginProperties.Processor_class) + addPlugins(&deps, plugin.ImplementationAndResourcesJars(), *plugin.pluginProperties.Processor_class) + } else { + addPlugins(&deps, plugin.ImplementationAndResourcesJars()) } deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api) } else { ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName) } + case exportedPluginTag: + if plugin, ok := dep.(*Plugin); ok { + if plugin.pluginProperties.Generates_api != nil && *plugin.pluginProperties.Generates_api { + ctx.PropertyErrorf("exported_plugins", "Cannot export plugins with generates_api = true, found %v", otherName) + } + j.exportedPluginJars = append(j.exportedPluginJars, plugin.ImplementationAndResourcesJars()...) + if plugin.pluginProperties.Processor_class != nil { + j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class) + } + } else { + ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName) + } case frameworkApkTag: if ctx.ModuleName() == "android_stubs_current" || ctx.ModuleName() == "android_system_stubs_current" || @@ -875,6 +904,11 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { return deps } +func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) { + deps.processorPath = append(deps.processorPath, pluginJars...) + deps.processorClasses = append(deps.processorClasses, pluginClasses...) +} + func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion { v := sdkContext.sdkVersion() // For PDK builds, use the latest SDK version instead of "current" @@ -1569,6 +1603,10 @@ func (j *Module) ExportedSdkLibs() []string { return j.exportedSdkLibs } +func (j *Module) ExportedPlugins() (android.Paths, []string) { + return j.exportedPluginJars, j.exportedPluginClasses +} + func (j *Module) SrcJarArgs() ([]string, android.Paths) { return j.srcJarArgs, j.srcJarDeps } @@ -2143,6 +2181,10 @@ func (j *Import) ExportedSdkLibs() []string { return j.exportedSdkLibs } +func (j *Import) ExportedPlugins() (android.Paths, []string) { + return nil, nil +} + func (j *Import) SrcJarArgs() ([]string, android.Paths) { return nil, nil } diff --git a/java/java_test.go b/java/java_test.go index efef7c1cc..dc498a492 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -332,6 +332,89 @@ func TestSimple(t *testing.T) { } } +func TestExportedPlugins(t *testing.T) { + type Result struct { + library string + processors string + } + var tests = []struct { + name string + extra string + results []Result + }{ + { + name: "Exported plugin is not a direct plugin", + extra: `java_library { name: "exports", srcs: ["a.java"], exported_plugins: ["plugin"] }`, + results: []Result{{library: "exports", processors: "-proc:none"}}, + }, + { + name: "Exports plugin to dependee", + extra: ` + java_library{name: "exports", exported_plugins: ["plugin"]} + java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} + java_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} + `, + results: []Result{ + {library: "foo", processors: "-processor com.android.TestPlugin"}, + {library: "bar", processors: "-processor com.android.TestPlugin"}, + }, + }, + { + name: "Exports plugin to android_library", + extra: ` + java_library{name: "exports", exported_plugins: ["plugin"]} + android_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} + android_library{name: "bar", srcs: ["a.java"], static_libs: ["exports"]} + `, + results: []Result{ + {library: "foo", processors: "-processor com.android.TestPlugin"}, + {library: "bar", processors: "-processor com.android.TestPlugin"}, + }, + }, + { + name: "Exports plugin is not propagated via transitive deps", + extra: ` + java_library{name: "exports", exported_plugins: ["plugin"]} + java_library{name: "foo", srcs: ["a.java"], libs: ["exports"]} + java_library{name: "bar", srcs: ["a.java"], static_libs: ["foo"]} + `, + results: []Result{ + {library: "foo", processors: "-processor com.android.TestPlugin"}, + {library: "bar", processors: "-proc:none"}, + }, + }, + { + name: "Exports plugin appends to plugins", + extra: ` + java_plugin{name: "plugin2", processor_class: "com.android.TestPlugin2"} + java_library{name: "exports", exported_plugins: ["plugin"]} + java_library{name: "foo", srcs: ["a.java"], libs: ["exports"], plugins: ["plugin2"]} + `, + results: []Result{ + {library: "foo", processors: "-processor com.android.TestPlugin,com.android.TestPlugin2"}, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ctx, _ := testJava(t, ` + java_plugin { + name: "plugin", + processor_class: "com.android.TestPlugin", + } + `+test.extra) + + for _, want := range test.results { + javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac") + if javac.Args["processor"] != want.processors { + t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"]) + } + } + }) + } +} + func TestSdkVersionByPartition(t *testing.T) { testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", ` java_library {