Replace panic with ModuleErrorf

This is a followup cleanup for aosp/2876754 and replaces panic with
ctx.ModuleErrorf. The latter creates a more expressive build error.

Implementation details
- export moduleErrorf interface from build/soong/android. This minimal
  interface will be used as a parameter for `DexJarBuildPath`
- Add ModuleErrorf to the function signature of DexJarBuildPath. This
  parameter only gets used for Import and SdkLibraryImport structs.
  These two can have duplicate deapexer definitions, and ModuleErrorf
  will be used to report that error
- Create a minimal implementation of `ModuleErrorf` in tests of java and
  apex

Test: m nothing --no-skip-soong-tests
Change-Id: I0febec651f40c3f04deb957e64133c94b80fbd78
This commit is contained in:
Spandan Das
2024-01-09 21:35:56 +00:00
parent 208444ce5d
commit 59a4a2b8d2
13 changed files with 51 additions and 29 deletions

View File

@@ -181,13 +181,13 @@ type errorfContext interface {
var _ errorfContext = blueprint.SingletonContext(nil) var _ errorfContext = blueprint.SingletonContext(nil)
// moduleErrorf is the interface containing the ModuleErrorf method matching // ModuleErrorfContext is the interface containing the ModuleErrorf method matching
// the ModuleErrorf method in blueprint.ModuleContext. // the ModuleErrorf method in blueprint.ModuleContext.
type moduleErrorf interface { type ModuleErrorfContext interface {
ModuleErrorf(format string, args ...interface{}) ModuleErrorf(format string, args ...interface{})
} }
var _ moduleErrorf = blueprint.ModuleContext(nil) var _ ModuleErrorfContext = blueprint.ModuleContext(nil)
// reportPathError will register an error with the attached context. It // reportPathError will register an error with the attached context. It
// attempts ctx.ModuleErrorf for a better error message first, then falls // attempts ctx.ModuleErrorf for a better error message first, then falls
@@ -200,7 +200,7 @@ func reportPathError(ctx PathContext, err error) {
// attempts ctx.ModuleErrorf for a better error message first, then falls // attempts ctx.ModuleErrorf for a better error message first, then falls
// back to ctx.Errorf. // back to ctx.Errorf.
func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) { func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) {
if mctx, ok := ctx.(moduleErrorf); ok { if mctx, ok := ctx.(ModuleErrorfContext); ok {
mctx.ModuleErrorf(format, args...) mctx.ModuleErrorf(format, args...)
} else if ectx, ok := ctx.(errorfContext); ok { } else if ectx, ok := ctx.(errorfContext); ok {
ectx.Errorf(format, args...) ectx.Errorf(format, args...)

View File

@@ -1628,7 +1628,7 @@ func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.Platform
type javaModule interface { type javaModule interface {
android.Module android.Module
BaseModuleName() string BaseModuleName() string
DexJarBuildPath() java.OptionalDexJarPath DexJarBuildPath(ctx android.ModuleErrorfContext) java.OptionalDexJarPath
JacocoReportClassesFile() android.Path JacocoReportClassesFile() android.Path
LintDepSets() java.LintDepSets LintDepSets() java.LintDepSets
Stem() string Stem() string
@@ -1642,7 +1642,7 @@ var _ javaModule = (*java.SdkLibraryImport)(nil)
// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar. // apexFileForJavaModule creates an apexFile for a java module's dex implementation jar.
func apexFileForJavaModule(ctx android.BaseModuleContext, module javaModule) apexFile { func apexFileForJavaModule(ctx android.BaseModuleContext, module javaModule) apexFile {
return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath().PathOrNil()) return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath(ctx).PathOrNil())
} }
// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file. // apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file.

View File

@@ -5355,6 +5355,13 @@ func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
).RunTest(t) ).RunTest(t)
} }
// A minimal context object for use with DexJarBuildPath
type moduleErrorfTestCtx struct {
}
func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
}
// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the // These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
// propagation of paths to dex implementation jars from the former to the latter. // propagation of paths to dex implementation jars from the former to the latter.
func TestPrebuiltExportDexImplementationJars(t *testing.T) { func TestPrebuiltExportDexImplementationJars(t *testing.T) {
@@ -5364,7 +5371,7 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
t.Helper() t.Helper()
// Make sure the import has been given the correct path to the dex jar. // Make sure the import has been given the correct path to the dex jar.
p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency) p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
dexJarBuildPath := p.DexJarBuildPath().PathOrNil() dexJarBuildPath := p.DexJarBuildPath(moduleErrorfTestCtx{}).PathOrNil()
stem := android.RemoveOptionalPrebuiltPrefix(name) stem := android.RemoveOptionalPrebuiltPrefix(name)
android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.", android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.",
".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
@@ -8491,6 +8498,8 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
PrepareForTestWithApexBuildComponents, PrepareForTestWithApexBuildComponents,
) )
errCtx := moduleErrorfTestCtx{}
bpBase := ` bpBase := `
apex_set { apex_set {
name: "com.android.myapex", name: "com.android.myapex",
@@ -8540,7 +8549,7 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
usesLibraryDep := module.(java.UsesLibraryDependency) usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path", android.AssertPathRelativeToTopEquals(t, "dex jar path",
"out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
usesLibraryDep.DexJarBuildPath().Path()) usesLibraryDep.DexJarBuildPath(errCtx).Path())
}) })
t.Run("java_sdk_library_import", func(t *testing.T) { t.Run("java_sdk_library_import", func(t *testing.T) {
@@ -8563,7 +8572,7 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
usesLibraryDep := module.(java.UsesLibraryDependency) usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path", android.AssertPathRelativeToTopEquals(t, "dex jar path",
"out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
usesLibraryDep.DexJarBuildPath().Path()) usesLibraryDep.DexJarBuildPath(errCtx).Path())
}) })
t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) { t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {

View File

@@ -677,7 +677,7 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) {
func getDexJarPath(result *android.TestResult, name string) string { func getDexJarPath(result *android.TestResult, name string) string {
module := result.Module(name, "android_common") module := result.Module(name, "android_common")
return module.(java.UsesLibraryDependency).DexJarBuildPath().Path().RelativeToTop().String() return module.(java.UsesLibraryDependency).DexJarBuildPath(moduleErrorfTestCtx{}).Path().RelativeToTop().String()
} }
// TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are // TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are

View File

@@ -1284,7 +1284,7 @@ func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
return android.Paths{a.classpathFile} return android.Paths{a.classpathFile}
} }
func (a *AARImport) DexJarBuildPath() android.Path { func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
return nil return nil
} }

View File

@@ -1639,7 +1639,7 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName) replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
} }
clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
lib.DexJarBuildPath().PathOrNil(), lib.DexJarInstallPath(), lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(),
lib.ClassLoaderContexts()) lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() { } else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep}) ctx.AddMissingDependencies([]string{dep})

View File

@@ -1929,7 +1929,7 @@ func (j *Module) ImplementationJars() android.Paths {
return android.Paths{j.implementationJarFile} return android.Paths{j.implementationJarFile}
} }
func (j *Module) DexJarBuildPath() OptionalDexJarPath { func (j *Module) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return j.dexJarFile return j.dexJarFile
} }

View File

@@ -151,7 +151,7 @@ func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths {
return d.implementationAndResourceJars return d.implementationAndResourceJars
} }
func (d *DeviceHostConverter) DexJarBuildPath() android.Path { func (d *DeviceHostConverter) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
return nil return nil
} }

View File

@@ -291,7 +291,7 @@ func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.
if sdkLibrary, ok := module.(SdkLibraryDependency); ok { if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind) dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
} else if j, ok := module.(UsesLibraryDependency); ok { } else if j, ok := module.(UsesLibraryDependency); ok {
dexJar = j.DexJarBuildPath() dexJar = j.DexJarBuildPath(ctx)
} else { } else {
ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module)) ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
return nil return nil
@@ -1457,7 +1457,9 @@ func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module,
// However, under certain conditions, e.g. errors, or special build configurations it will return // However, under certain conditions, e.g. errors, or special build configurations it will return
// a path to a fake file. // a path to a fake file.
func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path { func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
bootDexJar := module.(interface{ DexJarBuildPath() OptionalDexJarPath }).DexJarBuildPath() bootDexJar := module.(interface {
DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
}).DexJarBuildPath(ctx)
if !bootDexJar.Valid() { if !bootDexJar.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name())) fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason()) handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())

View File

@@ -309,7 +309,8 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String()) android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String())
// Make sure that the encoded dex jar is the exported one. // Make sure that the encoded dex jar is the exported one.
exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath().Path() errCtx := moduleErrorfTestCtx{}
exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath(errCtx).Path()
android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar) android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar)
} }

View File

@@ -315,7 +315,7 @@ type ApexDependency interface {
// Provides build path and install path to DEX jars. // Provides build path and install path to DEX jars.
type UsesLibraryDependency interface { type UsesLibraryDependency interface {
DexJarBuildPath() OptionalDexJarPath DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
DexJarInstallPath() android.Path DexJarInstallPath() android.Path
ClassLoaderContexts() dexpreopt.ClassLoaderContextMap ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
} }
@@ -2011,7 +2011,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}) })
} }
func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath { func (al *ApiLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return al.dexJarFile return al.dexJarFile
} }
@@ -2378,9 +2378,9 @@ func (j *Import) ImplementationAndResourcesJars() android.Paths {
return android.Paths{j.combinedClasspathFile} return android.Paths{j.combinedClasspathFile}
} }
func (j *Import) DexJarBuildPath() OptionalDexJarPath { func (j *Import) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
if j.dexJarFileErr != nil { if j.dexJarFileErr != nil {
panic(j.dexJarFileErr.Error()) ctx.ModuleErrorf(j.dexJarFileErr.Error())
} }
return j.dexJarFile return j.dexJarFile
} }
@@ -2631,7 +2631,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
} }
} }
func (j *DexImport) DexJarBuildPath() OptionalDexJarPath { func (j *DexImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return j.dexJarFile return j.dexJarFile
} }
@@ -2799,7 +2799,7 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
// from its CLC should be added to the current CLC. // from its CLC should be added to the current CLC.
if sdkLib != nil { if sdkLib != nil {
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
dep.DexJarBuildPath().PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts()) dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else { } else {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName) clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
} }

View File

@@ -528,6 +528,15 @@ func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
} }
} }
// A minimal context object for use with DexJarBuildPath
type moduleErrorfTestCtx struct {
}
func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
}
var _ android.ModuleErrorfContext = (*moduleErrorfTestCtx)(nil)
func TestPrebuilts(t *testing.T) { func TestPrebuilts(t *testing.T) {
ctx, _ := testJava(t, ` ctx, _ := testJava(t, `
java_library { java_library {
@@ -595,7 +604,8 @@ func TestPrebuilts(t *testing.T) {
t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String()) t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
} }
barDexJar := barModule.Module().(*Import).DexJarBuildPath() errCtx := moduleErrorfTestCtx{}
barDexJar := barModule.Module().(*Import).DexJarBuildPath(errCtx)
if barDexJar.IsSet() { if barDexJar.IsSet() {
t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar) t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar)
} }
@@ -608,7 +618,7 @@ func TestPrebuilts(t *testing.T) {
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String()) t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
} }
bazDexJar := bazModule.Module().(*Import).DexJarBuildPath().Path() bazDexJar := bazModule.Module().(*Import).DexJarBuildPath(errCtx).Path()
expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar" expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar) android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)

View File

@@ -678,7 +678,7 @@ func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.Modul
paths.stubsImplPath = lib.ImplementationJars paths.stubsImplPath = lib.ImplementationJars
libDep := dep.(UsesLibraryDependency) libDep := dep.(UsesLibraryDependency)
paths.stubsDexJarPath = libDep.DexJarBuildPath() paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
return nil return nil
} else { } else {
return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library") return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
@@ -2752,11 +2752,11 @@ func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleCont
} }
// to satisfy UsesLibraryDependency interface // to satisfy UsesLibraryDependency interface
func (module *SdkLibraryImport) DexJarBuildPath() OptionalDexJarPath { func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
// The dex implementation jar extracted from the .apex file should be used in preference to the // The dex implementation jar extracted from the .apex file should be used in preference to the
// source. // source.
if module.dexJarFileErr != nil { if module.dexJarFileErr != nil {
panic(module.dexJarFileErr.Error()) ctx.ModuleErrorf(module.dexJarFileErr.Error())
} }
if module.dexJarFile.IsSet() { if module.dexJarFile.IsSet() {
return module.dexJarFile return module.dexJarFile
@@ -2764,7 +2764,7 @@ func (module *SdkLibraryImport) DexJarBuildPath() OptionalDexJarPath {
if module.implLibraryModule == nil { if module.implLibraryModule == nil {
return makeUnsetDexJarPath() return makeUnsetDexJarPath()
} else { } else {
return module.implLibraryModule.DexJarBuildPath() return module.implLibraryModule.DexJarBuildPath(ctx)
} }
} }