From be5a5be5494962159a50d47143ff1e516604c3ed Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Mon, 30 Mar 2020 15:54:08 +0100 Subject: [PATCH] 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 --- apex/apex.go | 41 ++++++++++++++++++++++++++--------------- apex/builder.go | 8 ++++++-- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index bc992f063..dd4b99954 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1973,9 +1973,13 @@ func (c *flattenedApexContext) InstallBypassMake() bool { 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 @@ func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, // 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 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { 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 @@ func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) { isExternal: externalDep, } } + + // As soon as the dependency graph crosses the APEX boundary, don't go further. + return !externalDep }) } diff --git a/apex/builder.go b/apex/builder.go index 67bc20603..5a2134a05 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -230,12 +230,16 @@ func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName string) android.NoticeOutputs { var noticeFiles android.Paths - 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 { - return + // As soon as the dependency graph crosses the APEX boundary, don't go further. + return false } + notices := to.NoticeFiles() noticeFiles = append(noticeFiles, notices...) + + return true }) if len(noticeFiles) == 0 {