From 334b51730aa2fe64a55dd6bf4e139f97448cc7b8 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Mon, 27 Apr 2020 17:08:37 +0100 Subject: [PATCH] Export depsInfo into android package. Move depsInfo into android for easier sharing with APK code. Bug: 149622332 Test: m, diff'ing outputs for conscrypt module. Change-Id: If0ee967d37425540e69b4ce9304229d9f2cd86bd Merged-In: If0ee967d37425540e69b4ce9304229d9f2cd86bd Exempt-From-Owner-Approval: cp from aosp (cherry picked from commit 872a144dca543f40ee232f26e0233e580d97e86d) --- android/apex.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++ apex/apex.go | 38 +---------------------------------- apex/apex_test.go | 4 ++-- apex/builder.go | 42 +++++++++++++++++++++++---------------- 4 files changed, 78 insertions(+), 56 deletions(-) diff --git a/android/apex.go b/android/apex.go index c7410a19c..19f58d32c 100644 --- a/android/apex.go +++ b/android/apex.go @@ -18,6 +18,7 @@ import ( "fmt" "sort" "strconv" + "strings" "sync" "github.com/google/blueprint" @@ -395,3 +396,52 @@ func InitApexModule(m ApexModule) { m.AddProperties(&base.ApexProperties) } + +// A dependency info for a single ApexModule, either direct or transitive. +type ApexModuleDepInfo struct { + // Name of the dependency + To string + // List of dependencies To belongs to. Includes APEX itself, if a direct dependency. + From []string + // Whether the dependency belongs to the final compiled APEX. + IsExternal bool +} + +// A map of a dependency name to its ApexModuleDepInfo +type DepNameToDepInfoMap map[string]ApexModuleDepInfo + +type ApexBundleDepsInfo struct { + fullListPath OutputPath +} + +type ApexDepsInfoIntf interface { + FullListPath() Path +} + +func (d *ApexBundleDepsInfo) FullListPath() Path { + return d.fullListPath +} + +var _ ApexDepsInfoIntf = (*ApexBundleDepsInfo)(nil) + +func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, depInfos DepNameToDepInfoMap) { + var content strings.Builder + for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) { + info := depInfos[key] + toName := info.To + if info.IsExternal { + toName = toName + " (external)" + } + fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", ")) + } + + d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath + ctx.Build(pctx, BuildParams{ + Rule: WriteFile, + Description: "Full Dependency Info", + Output: d.fullListPath, + Args: map[string]string{ + "content": content.String(), + }, + }) +} diff --git a/apex/apex.go b/apex/apex.go index 719136515..45ba9088b 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1276,12 +1276,6 @@ func (af *apexFile) AvailableToPlatform() bool { return false } -type depInfo struct { - to string - from []string - isExternal bool -} - type apexBundle struct { android.ModuleBase android.DefaultableModuleBase @@ -1316,7 +1310,7 @@ type apexBundle struct { requiredDeps []string // list of module names that this APEX is including (to be shown via *-deps-info target) - depInfos map[string]depInfo + android.ApexBundleDepsInfo testApex bool vndkApex bool @@ -1876,35 +1870,6 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { } } -// 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) bool { - if from.Name() == to.Name() { - // This can happen for cc.reuseObjTag. We are not interested in tracking this. - // As soon as the dependency graph crosses the APEX boundary, don't go further. - return !externalDep - } - - if info, exists := a.depInfos[to.Name()]; exists { - if !android.InList(from.Name(), info.from) { - info.from = append(info.from, from.Name()) - } - info.isExternal = info.isExternal && externalDep - a.depInfos[to.Name()] = info - } else { - a.depInfos[to.Name()] = depInfo{ - to: to.Name(), - from: []string{from.Name()}, - isExternal: externalDep, - } - } - - // As soon as the dependency graph crosses the APEX boundary, don't go further. - return !externalDep - }) -} - func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() switch a.properties.ApexType { @@ -1942,7 +1907,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.checkApexAvailability(ctx) a.checkUpdatable(ctx) - a.collectDepsInfo(ctx) handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case) diff --git a/apex/apex_test.go b/apex/apex_test.go index f1d80ae85..f0e7ff3c1 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -478,7 +478,7 @@ func TestBasicApex(t *testing.T) { ensureListContains(t, noticeInputs, "custom_notice") ensureListContains(t, noticeInputs, "custom_notice_for_static_lib") - depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("myapex-deps-info.txt").Args["content"], "\\n") + depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") ensureListContains(t, depsInfo, "myjar <- myapex") ensureListContains(t, depsInfo, "mylib <- myapex") ensureListContains(t, depsInfo, "mylib2 <- mylib") @@ -784,7 +784,7 @@ func TestApexWithExplicitStubsDependency(t *testing.T) { // Ensure that libfoo stubs is not linking to libbar (since it is a stubs) ensureNotContains(t, libFooStubsLdFlags, "libbar.so") - depsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("myapex2-deps-info.txt").Args["content"], "\\n") + depsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") ensureListContains(t, depsInfo, "mylib <- myapex2") ensureListContains(t, depsInfo, "libbaz <- mylib") diff --git a/apex/builder.go b/apex/builder.go index 0d7e80184..a3e692989 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -679,29 +679,37 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { return } - var content strings.Builder - for _, key := range android.SortedStringKeys(a.depInfos) { - info := a.depInfos[key] - toName := info.to - if info.isExternal { - toName = toName + " (external)" + depInfos := android.DepNameToDepInfoMap{} + 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. + // As soon as the dependency graph crosses the APEX boundary, don't go further. + return !externalDep } - fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(android.SortedUniqueStrings(info.from), ", ")) - } - depsInfoFile := android.PathForOutput(ctx, a.Name()+"-deps-info.txt") - ctx.Build(pctx, android.BuildParams{ - Rule: android.WriteFile, - Description: "Dependency Info", - Output: depsInfoFile, - Args: map[string]string{ - "content": content.String(), - }, + if info, exists := depInfos[to.Name()]; exists { + if !android.InList(from.Name(), info.From) { + info.From = append(info.From, from.Name()) + } + info.IsExternal = info.IsExternal && externalDep + depInfos[to.Name()] = info + } else { + depInfos[to.Name()] = android.ApexModuleDepInfo{ + To: to.Name(), + From: []string{from.Name()}, + IsExternal: externalDep, + } + } + + // As soon as the dependency graph crosses the APEX boundary, don't go further. + return !externalDep }) + a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, depInfos) + ctx.Build(pctx, android.BuildParams{ Rule: android.Phony, Output: android.PathForPhony(ctx, a.Name()+"-deps-info"), - Inputs: []android.Path{depsInfoFile}, + Inputs: []android.Path{a.ApexBundleDepsInfo.FullListPath()}, }) }