From 133608f60245697ed9c29abe06d9dd4d9845a787 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 Bug: 153306490 Test: m droid Merged-In: If46a2f74b6eca670befc3aeae430650e85542346 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 02aca445f..bb466129b 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1769,9 +1769,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() { @@ -1781,22 +1785,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 */) }) } @@ -1823,28 +1823,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 { @@ -1860,6 +1868,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 1fc2233d0..f84d426b3 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -219,14 +219,18 @@ 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 } + notice := to.NoticeFile() if notice.Valid() { noticeFiles = append(noticeFiles, notice.Path()) } + + return true }) if len(noticeFiles) == 0 {