Merge "Export depsInfo into android package."
This commit is contained in:
commit
57769e469b
|
@ -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(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
38
apex/apex.go
38
apex/apex.go
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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()},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue