Merge "Export depsInfo into android package."

This commit is contained in:
satayev 2020-05-05 10:00:41 +00:00 committed by Gerrit Code Review
commit 57769e469b
4 changed files with 78 additions and 56 deletions

View File

@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"sort" "sort"
"strconv" "strconv"
"strings"
"sync" "sync"
"github.com/google/blueprint" "github.com/google/blueprint"
@ -403,3 +404,52 @@ func InitApexModule(m ApexModule) {
m.AddProperties(&base.ApexProperties) 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(),
},
})
}

View File

@ -1276,12 +1276,6 @@ func (af *apexFile) AvailableToPlatform() bool {
return false return false
} }
type depInfo struct {
to string
from []string
isExternal bool
}
type apexBundle struct { type apexBundle struct {
android.ModuleBase android.ModuleBase
android.DefaultableModuleBase android.DefaultableModuleBase
@ -1316,7 +1310,7 @@ type apexBundle struct {
requiredDeps []string requiredDeps []string
// list of module names that this APEX is including (to be shown via *-deps-info target) // list of module names that this APEX is including (to be shown via *-deps-info target)
depInfos map[string]depInfo android.ApexBundleDepsInfo
testApex bool testApex bool
vndkApex bool vndkApex bool
@ -1890,35 +1884,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) { func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
switch a.properties.ApexType { switch a.properties.ApexType {
@ -1956,7 +1921,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.checkApexAvailability(ctx) a.checkApexAvailability(ctx)
a.checkUpdatable(ctx) a.checkUpdatable(ctx)
a.collectDepsInfo(ctx)
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case) handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)

View File

@ -504,7 +504,7 @@ func TestBasicApex(t *testing.T) {
ensureListContains(t, noticeInputs, "custom_notice") ensureListContains(t, noticeInputs, "custom_notice")
ensureListContains(t, noticeInputs, "custom_notice_for_static_lib") 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, "myjar <- myapex")
ensureListContains(t, depsInfo, "mylib <- myapex") ensureListContains(t, depsInfo, "mylib <- myapex")
ensureListContains(t, depsInfo, "mylib2 <- mylib") ensureListContains(t, depsInfo, "mylib2 <- mylib")
@ -818,7 +818,7 @@ func TestApexWithExplicitStubsDependency(t *testing.T) {
// Ensure that libfoo stubs is not linking to libbar (since it is a stubs) // Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
ensureNotContains(t, libFooStubsLdFlags, "libbar.so") 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, "mylib <- myapex2")
ensureListContains(t, depsInfo, "libbaz <- mylib") ensureListContains(t, depsInfo, "libbaz <- mylib")

View File

@ -688,29 +688,37 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
return return
} }
var content strings.Builder depInfos := android.DepNameToDepInfoMap{}
for _, key := range android.SortedStringKeys(a.depInfos) { a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
info := a.depInfos[key] if from.Name() == to.Name() {
toName := info.to // This can happen for cc.reuseObjTag. We are not interested in tracking this.
if info.isExternal { // As soon as the dependency graph crosses the APEX boundary, don't go further.
toName = toName + " (external)" return !externalDep
} }
fmt.Fprintf(&content, "%s <- %s\\n", toName, strings.Join(android.SortedUniqueStrings(info.from), ", "))
}
depsInfoFile := android.PathForOutput(ctx, a.Name()+"-deps-info.txt") if info, exists := depInfos[to.Name()]; exists {
ctx.Build(pctx, android.BuildParams{ if !android.InList(from.Name(), info.From) {
Rule: android.WriteFile, info.From = append(info.From, from.Name())
Description: "Dependency Info", }
Output: depsInfoFile, info.IsExternal = info.IsExternal && externalDep
Args: map[string]string{ depInfos[to.Name()] = info
"content": content.String(), } 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{ ctx.Build(pctx, android.BuildParams{
Rule: android.Phony, Rule: android.Phony,
Output: android.PathForPhony(ctx, a.Name()+"-deps-info"), Output: android.PathForPhony(ctx, a.Name()+"-deps-info"),
Inputs: []android.Path{depsInfoFile}, Inputs: []android.Path{a.ApexBundleDepsInfo.FullListPath()},
}) })
} }