Allow walkPayloadDeps visitor to control walk flow
Delegate the responsibility for determining whether the
walkPayloadDeps() should visit a child dependency to its do function.
This is needed to allow the visitor in checkApexAvailability() to avoid
checking the apex_available setting after crossing the APEX boundary.
Bug: 152878661
Test: m droid
Change-Id: If46a2f74b6eca670befc3aeae430650e85542346
diff --git a/apex/apex.go b/apex/apex.go
index bc992f0..dd4b999 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1973,9 +1973,13 @@
return true
}
+// Function called while walking an APEX's payload dependencies.
+//
+// Return true if the `to` module should be visited, false otherwise.
+type payloadDepsCallback func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool
+
// Visit dependencies that contributes to the payload of this APEX
-func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext,
- do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) {
+func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, do payloadDepsCallback) {
ctx.WalkDeps(func(child, parent android.Module) bool {
am, ok := child.(android.ApexModule)
if !ok || !am.CanHaveApexVariants() {
@@ -1985,22 +1989,18 @@
// Check for the direct dependencies that contribute to the payload
if dt, ok := ctx.OtherModuleDependencyTag(child).(dependencyTag); ok {
if dt.payload {
- do(ctx, parent, am, false /* externalDep */)
- return true
+ return do(ctx, parent, am, false /* externalDep */)
}
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
}
// Check for the indirect dependencies if it is considered as part of the APEX
if am.ApexName() != "" {
- do(ctx, parent, am, false /* externalDep */)
- return true
+ return do(ctx, parent, am, false /* externalDep */)
}
- do(ctx, parent, am, true /* externalDep */)
-
- // As soon as the dependency graph crosses the APEX boundary, don't go further.
- return false
+ return do(ctx, parent, am, true /* externalDep */)
})
}
@@ -2030,28 +2030,36 @@
return
}
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ if externalDep {
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return false
+ }
+
apexName := ctx.ModuleName()
fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to)
- if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
- return
+ if to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
+ return true
}
message := ""
for _, m := range ctx.GetWalkPath()[1:] {
message = fmt.Sprintf("%s\n -> %s", message, m.String())
}
ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, message)
+ // Visit this module's dependencies to check and report any issues with their availability.
+ return true
})
}
// Collects the list of module names that directly or indirectly contributes to the payload of this APEX
func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
a.depInfos = make(map[string]depInfo)
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if from.Name() == to.Name() {
// This can happen for cc.reuseObjTag. We are not interested in tracking this.
- return
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return !externalDep
}
if info, exists := a.depInfos[to.Name()]; exists {
@@ -2067,6 +2075,9 @@
isExternal: externalDep,
}
}
+
+ // As soon as the dependency graph crosses the APEX boundary, don't go further.
+ return !externalDep
})
}