Loading android/apex.go +50 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ import ( "fmt" "sort" "strconv" "strings" "sync" "github.com/google/blueprint" Loading Loading @@ -403,3 +404,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(), }, }) } apex/apex.go +1 −37 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) { buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() switch a.properties.ApexType { Loading Loading @@ -1956,7 +1921,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) Loading apex/apex_test.go +2 −2 Original line number Diff line number Diff line Loading @@ -504,7 +504,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") Loading Loading @@ -818,7 +818,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") Loading apex/builder.go +25 −17 Original line number Diff line number Diff line Loading @@ -688,29 +688,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 } 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, } 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(), }, // 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()}, }) } Loading
android/apex.go +50 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ import ( "fmt" "sort" "strconv" "strings" "sync" "github.com/google/blueprint" Loading Loading @@ -403,3 +404,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(), }, }) }
apex/apex.go +1 −37 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) { buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild() switch a.properties.ApexType { Loading Loading @@ -1956,7 +1921,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) Loading
apex/apex_test.go +2 −2 Original line number Diff line number Diff line Loading @@ -504,7 +504,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") Loading Loading @@ -818,7 +818,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") Loading
apex/builder.go +25 −17 Original line number Diff line number Diff line Loading @@ -688,29 +688,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 } 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, } 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(), }, // 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()}, }) }