Use OutputFilesProvider on java modules

In the context of incremental soong, the output files
inter-module-communication will be through OutputFilesProvider.
The OutputFileProducer interface will be deprecated.

Test: CI
Bug: 339477385
Change-Id: I3c9f0b766325dd490bc903dc65259c3953d34606
This commit is contained in:
mrziwang
2024-07-10 12:18:06 -07:00
parent 8dfc2bf163
commit 9f7b9f4a9a
10 changed files with 82 additions and 155 deletions

View File

@@ -2491,6 +2491,8 @@ func outputFilesForModule(ctx PathContext, module blueprint.Module, tag string)
if outputFilesFromProvider != nil || err != OutputFilesProviderNotSet {
return outputFilesFromProvider, err
}
// TODO: add error when outputFilesFromProvider and err are both nil after
// OutputFileProducer and SourceFileProducer are deprecated.
if outputFileProducer, ok := module.(OutputFileProducer); ok {
paths, err := outputFileProducer.OutputFiles(tag)
if err != nil {
@@ -2505,7 +2507,7 @@ func outputFilesForModule(ctx PathContext, module blueprint.Module, tag string)
paths := sourceFileProducer.Srcs()
return paths, nil
} else {
return nil, fmt.Errorf("module %q is not an OutputFileProducer or SourceFileProducer", pathContextName(ctx, module))
return nil, fmt.Errorf("module %q is not an SourceFileProducer or having valid output file for tag %q", pathContextName(ctx, module), tag)
}
}

View File

@@ -798,18 +798,6 @@ type AndroidLibrary struct {
aarFile android.WritablePath
}
var _ android.OutputFileProducer = (*AndroidLibrary)(nil)
// For OutputFileProducer interface
func (a *AndroidLibrary) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case ".aar":
return []android.Path{a.aarFile}, nil
default:
return a.Library.OutputFiles(tag)
}
}
var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -911,6 +899,13 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{
AconfigTextFiles: aconfigTextFilePaths,
})
a.setOutputFiles(ctx)
}
func (a *AndroidLibrary) setOutputFiles(ctx android.ModuleContext) {
ctx.SetOutputFiles([]android.Path{a.aarFile}, ".aar")
setOutputFiles(ctx, a.Library.Module)
}
func (a *AndroidLibrary) IDEInfo(dpInfo *android.IdeInfo) {

View File

@@ -159,19 +159,19 @@ func TestAndroidLibraryOutputFilesRel(t *testing.T) {
bar := result.ModuleForTests("bar", "android_common")
baz := result.ModuleForTests("baz", "android_common")
fooOutputPath := android.OutputFileForModule(android.PathContext(nil), foo.Module(), "")
fooOutputPaths := foo.OutputFiles(t, "")
barOutputPaths := bar.OutputFiles(t, "")
bazOutputPaths := baz.OutputFiles(t, "")
android.AssertPathRelativeToTopEquals(t, "foo output path",
"out/soong/.intermediates/foo/android_common/withres/foo.jar", fooOutputPath)
android.AssertPathsRelativeToTopEquals(t, "foo output path",
[]string{"out/soong/.intermediates/foo/android_common/withres/foo.jar"}, fooOutputPaths)
android.AssertPathsRelativeToTopEquals(t, "bar output path",
[]string{"out/soong/.intermediates/bar/android_common/aar/bar.jar"}, barOutputPaths)
android.AssertPathsRelativeToTopEquals(t, "baz output path",
[]string{"out/soong/.intermediates/baz/android_common/withres/baz.jar"}, bazOutputPaths)
android.AssertStringEquals(t, "foo relative output path",
"foo.jar", fooOutputPath.Rel())
"foo.jar", fooOutputPaths[0].Rel())
android.AssertStringEquals(t, "bar relative output path",
"bar.jar", barOutputPaths[0].Rel())
android.AssertStringEquals(t, "baz relative output path",

View File

@@ -1017,6 +1017,22 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
isPrebuilt: false,
},
)
a.setOutputFiles(ctx)
}
func (a *AndroidApp) setOutputFiles(ctx android.ModuleContext) {
ctx.SetOutputFiles([]android.Path{a.proguardOptionsFile}, ".aapt.proguardOptionsFile")
if a.aaptSrcJar != nil {
ctx.SetOutputFiles([]android.Path{a.aaptSrcJar}, ".aapt.srcjar")
}
if a.rJar != nil {
ctx.SetOutputFiles([]android.Path{a.rJar}, ".aapt.jar")
}
ctx.SetOutputFiles([]android.Path{a.outputFile}, ".apk")
ctx.SetOutputFiles([]android.Path{a.exportPackage}, ".export-package.apk")
ctx.SetOutputFiles([]android.Path{a.aapt.manifestPath}, ".manifest.xml")
setOutputFiles(ctx, a.Library.Module)
}
type appDepsInterface interface {
@@ -1207,31 +1223,6 @@ func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.
return a.Library.DepIsInSameApex(ctx, dep)
}
// For OutputFileProducer interface
func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
switch tag {
// In some instances, it can be useful to reference the aapt-generated flags from another
// target, e.g., system server implements services declared in the framework-res manifest.
case ".aapt.proguardOptionsFile":
return []android.Path{a.proguardOptionsFile}, nil
case ".aapt.srcjar":
if a.aaptSrcJar != nil {
return []android.Path{a.aaptSrcJar}, nil
}
case ".aapt.jar":
if a.rJar != nil {
return []android.Path{a.rJar}, nil
}
case ".apk":
return []android.Path{a.outputFile}, nil
case ".export-package.apk":
return []android.Path{a.exportPackage}, nil
case ".manifest.xml":
return []android.Path{a.aapt.manifestPath}, nil
}
return a.Library.OutputFiles(tag)
}
func (a *AndroidApp) Privileged() bool {
return Bool(a.appProperties.Privileged)
}

View File

@@ -119,10 +119,7 @@ func TestAppSplits(t *testing.T) {
foo.Output(expectedOutput)
}
outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("")
if err != nil {
t.Fatal(err)
}
outputFiles := foo.OutputFiles(t, "")
android.AssertPathsRelativeToTopEquals(t, `OutputFiles("")`, expectedOutputs, outputFiles)
}

View File

@@ -652,35 +652,21 @@ func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) {
android.SetProvider(ctx, hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
}
func (j *Module) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
case android.DefaultDistTag:
return android.Paths{j.outputFile}, nil
case ".jar":
return android.Paths{j.implementationAndResourcesJar}, nil
case ".hjar":
return android.Paths{j.headerJarFile}, nil
case ".proguard_map":
if j.dexer.proguardDictionary.Valid() {
return android.Paths{j.dexer.proguardDictionary.Path()}, nil
}
return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
case ".generated_srcjars":
return j.properties.Generated_srcjars, nil
case ".lint":
if j.linter.outputs.xml != nil {
return android.Paths{j.linter.outputs.xml}, nil
}
return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
// helper method for java modules to set OutputFilesProvider
func setOutputFiles(ctx android.ModuleContext, m Module) {
ctx.SetOutputFiles(append(android.Paths{m.outputFile}, m.extraOutputFiles...), "")
ctx.SetOutputFiles(android.Paths{m.outputFile}, android.DefaultDistTag)
ctx.SetOutputFiles(android.Paths{m.implementationAndResourcesJar}, ".jar")
ctx.SetOutputFiles(android.Paths{m.headerJarFile}, ".hjar")
if m.dexer.proguardDictionary.Valid() {
ctx.SetOutputFiles(android.Paths{m.dexer.proguardDictionary.Path()}, ".proguard_map")
}
ctx.SetOutputFiles(m.properties.Generated_srcjars, ".generated_srcjars")
if m.linter.outputs.xml != nil {
ctx.SetOutputFiles(android.Paths{m.linter.outputs.xml}, ".lint")
}
}
var _ android.OutputFileProducer = (*Module)(nil)
func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
initJavaModule(module, hod, false)
}

View File

@@ -977,6 +977,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
TestOnly: Bool(j.sourceProperties.Test_only),
TopLevelTarget: j.sourceProperties.Top_level_test_target,
})
setOutputFiles(ctx, j.Module)
}
func (j *Library) setInstallRules(ctx android.ModuleContext, installModuleName string) {
@@ -1836,6 +1838,8 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// libraries. This is verified by TestBinary.
j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
ctx.ModuleName()+ext, j.wrapperFile)
setOutputFiles(ctx, j.Library.Module)
}
}

View File

@@ -2993,19 +2993,19 @@ func TestJavaLibraryOutputFilesRel(t *testing.T) {
bar := result.ModuleForTests("bar", "android_common")
baz := result.ModuleForTests("baz", "android_common")
fooOutputPath := android.OutputFileForModule(android.PathContext(nil), foo.Module(), "")
fooOutputPaths := foo.OutputFiles(t, "")
barOutputPaths := bar.OutputFiles(t, "")
bazOutputPaths := baz.OutputFiles(t, "")
android.AssertPathRelativeToTopEquals(t, "foo output path",
"out/soong/.intermediates/foo/android_common/javac/foo.jar", fooOutputPath)
android.AssertPathsRelativeToTopEquals(t, "foo output path",
[]string{"out/soong/.intermediates/foo/android_common/javac/foo.jar"}, fooOutputPaths)
android.AssertPathsRelativeToTopEquals(t, "bar output path",
[]string{"out/soong/.intermediates/bar/android_common/combined/bar.jar"}, barOutputPaths)
android.AssertPathsRelativeToTopEquals(t, "baz output path",
[]string{"out/soong/.intermediates/baz/android_common/combined/baz.jar"}, bazOutputPaths)
android.AssertStringEquals(t, "foo relative output path",
"foo.jar", fooOutputPath.Rel())
"foo.jar", fooOutputPaths[0].Rel())
android.AssertStringEquals(t, "bar relative output path",
"bar.jar", barOutputPaths[0].Rel())
android.AssertStringEquals(t, "baz relative output path",

View File

@@ -1086,57 +1086,26 @@ var tagSplitter = func() *regexp.Regexp {
return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp))
}()
// For OutputFileProducer interface
//
// .<scope>.<component name>, for all ComponentNames (for example: .public.removed-api.txt)
func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) {
if groups := tagSplitter.FindStringSubmatch(tag); groups != nil {
scopeName := groups[1]
component := groups[2]
if scope, ok := scopeByName[scopeName]; ok {
paths := c.findScopePaths(scope)
if paths == nil {
return nil, fmt.Errorf("%q does not provide api scope %s", c.module.RootLibraryName(), scopeName)
}
switch component {
case stubsSourceComponentName:
if paths.stubsSrcJar.Valid() {
return android.Paths{paths.stubsSrcJar.Path()}, nil
}
case apiTxtComponentName:
if paths.currentApiFilePath.Valid() {
return android.Paths{paths.currentApiFilePath.Path()}, nil
}
case removedApiTxtComponentName:
if paths.removedApiFilePath.Valid() {
return android.Paths{paths.removedApiFilePath.Path()}, nil
}
case annotationsComponentName:
if paths.annotationsZip.Valid() {
return android.Paths{paths.annotationsZip.Path()}, nil
}
}
return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName)
} else {
return nil, fmt.Errorf("unknown scope %s in %s", scope, tag)
func (module *commonToSdkLibraryAndImport) setOutputFiles(ctx android.ModuleContext) {
if module.doctagPaths != nil {
ctx.SetOutputFiles(module.doctagPaths, ".doctags")
}
for _, scopeName := range android.SortedKeys(scopeByName) {
paths := module.findScopePaths(scopeByName[scopeName])
if paths == nil {
continue
}
} else {
switch tag {
case ".doctags":
if c.doctagPaths != nil {
return c.doctagPaths, nil
} else {
return nil, fmt.Errorf("no doctag_files specified on %s", c.module.RootLibraryName())
componentToOutput := map[string]android.OptionalPath{
stubsSourceComponentName: paths.stubsSrcJar,
apiTxtComponentName: paths.currentApiFilePath,
removedApiTxtComponentName: paths.removedApiFilePath,
annotationsComponentName: paths.annotationsZip,
}
for _, component := range android.SortedKeys(componentToOutput) {
if componentToOutput[component].Valid() {
ctx.SetOutputFiles(android.Paths{componentToOutput[component].Path()}, "."+scopeName+"."+component)
}
}
return nil, nil
}
}
@@ -1579,20 +1548,6 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
}
}
func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
paths, err := module.commonOutputFiles(tag)
if paths != nil || err != nil {
return paths, err
}
if module.requiresRuntimeImplementationLibrary() {
return module.implLibraryModule.OutputFiles(tag)
}
if tag == "" {
return nil, nil
}
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if disableSourceApexVariant(ctx) {
// Prebuilts are active, do not create the installation rules for the source javalib.
@@ -1702,6 +1657,10 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
}
}
android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
module.setOutputFiles(ctx)
if module.requiresRuntimeImplementationLibrary() && module.implLibraryModule != nil {
setOutputFiles(ctx, module.implLibraryModule.Module)
}
}
func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall {
@@ -2937,18 +2896,6 @@ func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) an
var _ hiddenAPIModule = (*SdkLibraryImport)(nil)
func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
paths, err := module.commonOutputFiles(tag)
if paths != nil || err != nil {
return paths, err
}
if module.implLibraryModule != nil {
return module.implLibraryModule.OutputFiles(tag)
} else {
return nil, nil
}
}
func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.generateCommonBuildActions(ctx)
@@ -3031,6 +2978,11 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
}
}
}
module.setOutputFiles(ctx)
if module.implLibraryModule != nil {
setOutputFiles(ctx, module.implLibraryModule.Module)
}
}
func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {

View File

@@ -492,7 +492,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations(t *testing.T) {
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": failed to get output file from module "foo" at tag ".public.annotations.zip": annotations.zip not available for api scope public`)).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".public.annotations.zip"`)).
RunTestWithBp(t, `
java_sdk_library {
name: "foo",
@@ -517,7 +517,7 @@ func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"foo" does not provide api scope system`)).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".system.stubs.source"`)).
RunTestWithBp(t, `
java_sdk_library {
name: "foo",
@@ -606,7 +606,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
t.Run("stubs.source", func(t *testing.T) {
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`stubs.source not available for api scope public`)).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not an SourceFileProducer or having valid output file for tag ".public.stubs.source"`)).
RunTestWithBp(t, bp+`
java_library {
name: "bar",
@@ -621,7 +621,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
t.Run("api.txt", func(t *testing.T) {
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`api.txt not available for api scope public`)).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not an SourceFileProducer or having valid output file for tag ".public.api.txt"`)).
RunTestWithBp(t, bp+`
java_library {
name: "bar",
@@ -635,7 +635,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
t.Run("removed-api.txt", func(t *testing.T) {
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`removed-api.txt not available for api scope public`)).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not an SourceFileProducer or having valid output file for tag ".public.removed-api.txt"`)).
RunTestWithBp(t, bp+`
java_library {
name: "bar",