m <apex_name>-deps-info prints the internal/external deps of the APEX
We need to have a way to see the list of modules that directly or
indirectly contribute to an APEX. People find it difficult to determine
whether a module is included in which APEXes because APEX tracks
indirect dependencies as well as direct dependencies. Therefore, just
looking at Android.bp for the APEX itself doesn't give the answer.
This change adds a new make target <apex_name>-deps-info, which
generates out/soong/<apex_name>-deps-info.txt file that shows the
internal and external dependencies of the said APEX.
Here, internal means the dependencies are actually part of the
APEX, while external means the dependencies are still external to the
APEX.
Bug: 146323213
Test: m (apex_test amended)
Change-Id: I33d1ccf5d1ca335d71cd6ced0f5f66b8c3886d13
diff --git a/apex/androidmk.go b/apex/androidmk.go
index c42b348..3462c7e 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -185,8 +185,8 @@
if len(moduleNames) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " "))
}
- if len(a.externalDeps) > 0 {
- fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.externalDeps, " "))
+ if len(a.requiredDeps) > 0 {
+ fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " "))
}
var postInstallCommands []string
if a.prebuiltFileToDelete != "" {
diff --git a/apex/apex.go b/apex/apex.go
index b27b54e..aadc2c1 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -511,8 +511,13 @@
// list of files to be included in this apex
filesInfo []apexFile
- // list of module names that this APEX is depending on
+ // list of module names that should be installed along with this APEX
+ requiredDeps []string
+
+ // list of module names that this APEX is depending on (to be shown via *-deps-info target)
externalDeps []string
+ // list of module names that this APEX is including (to be shown via *-deps-info target)
+ internalDeps []string
testApex bool
vndkApex bool
@@ -925,7 +930,7 @@
a.primaryApexType = true
if ctx.Config().InstallExtraFlattenedApexes() {
- a.externalDeps = append(a.externalDeps, a.Name()+flattenedSuffix)
+ a.requiredDeps = append(a.requiredDeps, a.Name()+flattenedSuffix)
}
}
case zipApex:
@@ -984,6 +989,9 @@
depTag := ctx.OtherModuleDependencyTag(child)
depName := ctx.OtherModuleName(child)
if _, isDirectDep := parent.(*apexBundle); isDirectDep {
+ if depTag != keyTag && depTag != certificateTag {
+ a.internalDeps = append(a.internalDeps, depName)
+ }
switch depTag {
case sharedLibTag:
if cc, ok := child.(*cc.Module); ok {
@@ -1114,9 +1122,10 @@
//
// Always include if we are a host-apex however since those won't have any
// system libraries.
- if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.externalDeps) {
- a.externalDeps = append(a.externalDeps, cc.Name())
+ if !android.DirectlyInAnyApex(ctx, cc.Name()) && !android.InList(cc.Name(), a.requiredDeps) {
+ a.requiredDeps = append(a.requiredDeps, cc.Name())
}
+ a.externalDeps = append(a.externalDeps, depName)
requireNativeLibs = append(requireNativeLibs, cc.OutputFile().Path().Base())
// Don't track further
return false
@@ -1124,6 +1133,8 @@
af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
af.transitiveDep = true
filesInfo = append(filesInfo, af)
+ a.internalDeps = append(a.internalDeps, depName)
+ a.internalDeps = append(a.internalDeps, cc.AllStaticDeps()...)
return true // track transitive dependencies
}
} else if cc.IsTestPerSrcDepTag(depTag) {
@@ -1139,8 +1150,10 @@
return true // track transitive dependencies
}
} else if java.IsJniDepTag(depTag) {
- // Do nothing for JNI dep. JNI libraries are always embedded in APK-in-APEX.
+ a.externalDeps = append(a.externalDeps, depName)
return true
+ } else if java.IsStaticLibDepTag(depTag) {
+ a.internalDeps = append(a.internalDeps, depName)
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %q for indirect dependency %q", depTag, depName)
}
@@ -1238,6 +1251,7 @@
apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())
a.compatSymlinks = makeCompatSymlinks(apexName, ctx)
+ a.buildApexDependencyInfo(ctx)
}
func newApexBundle() *apexBundle {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 0d929ed..9e9f882 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -219,6 +219,7 @@
"apex_manifest.json": nil,
"AndroidManifest.xml": nil,
"system/sepolicy/apex/myapex-file_contexts": nil,
+ "system/sepolicy/apex/myapex2-file_contexts": nil,
"system/sepolicy/apex/otherapex-file_contexts": nil,
"system/sepolicy/apex/commonapex-file_contexts": nil,
"system/sepolicy/apex/com.android.vndk-file_contexts": nil,
@@ -520,6 +521,12 @@
}
ensureListContains(t, noticeInputs, "NOTICE")
ensureListContains(t, noticeInputs, "custom_notice")
+
+ depsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("myapex-deps-info.txt").Args["content"], "\\n")
+ ensureListContains(t, depsInfo, "internal myjar")
+ ensureListContains(t, depsInfo, "internal mylib")
+ ensureListContains(t, depsInfo, "internal mylib2")
+ ensureListContains(t, depsInfo, "internal myotherjar")
}
func TestDefaults(t *testing.T) {
@@ -740,13 +747,13 @@
func TestApexWithExplicitStubsDependency(t *testing.T) {
ctx, _ := testApex(t, `
apex {
- name: "myapex",
- key: "myapex.key",
+ name: "myapex2",
+ key: "myapex2.key",
native_shared_libs: ["mylib"],
}
apex_key {
- name: "myapex.key",
+ name: "myapex2.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
@@ -779,7 +786,7 @@
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -791,7 +798,7 @@
// Ensure that dependency of stubs is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex2").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with version 10 of libfoo
ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
@@ -802,6 +809,12 @@
// 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")
+ ensureListContains(t, depsInfo, "internal mylib")
+ ensureListContains(t, depsInfo, "external libfoo")
+ ensureListNotContains(t, depsInfo, "internal libfoo")
+ ensureListNotContains(t, depsInfo, "external mylib")
}
func TestApexWithRuntimeLibsDependency(t *testing.T) {
@@ -2652,7 +2665,7 @@
config.TestProductVariables.InstallExtraFlattenedApexes = proptools.BoolPtr(true)
})
ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
- ensureListContains(t, ab.externalDeps, "myapex.flattened")
+ ensureListContains(t, ab.requiredDeps, "myapex.flattened")
mk := android.AndroidMkDataForTest(t, config, "", ab)
var builder strings.Builder
mk.Custom(&builder, ab.Name(), "TARGET_", "", mk)
diff --git a/apex/builder.go b/apex/builder.go
index fe465f5..5bc21d6 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -553,3 +553,40 @@
}
return ""
}
+
+func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) {
+ if !a.primaryApexType {
+ return
+ }
+
+ internalDeps := a.internalDeps
+ externalDeps := a.externalDeps
+
+ internalDeps = android.SortedUniqueStrings(internalDeps)
+ externalDeps = android.SortedUniqueStrings(externalDeps)
+ externalDeps = android.RemoveListFromList(externalDeps, internalDeps)
+
+ var content strings.Builder
+ for _, name := range internalDeps {
+ fmt.Fprintf(&content, "internal %s\\n", name)
+ }
+ for _, name := range externalDeps {
+ fmt.Fprintf(&content, "external %s\\n", name)
+ }
+
+ 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(),
+ },
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Phony,
+ Output: android.PathForPhony(ctx, a.Name()+"-deps-info"),
+ Inputs: []android.Path{depsInfoFile},
+ })
+}
diff --git a/cc/cc.go b/cc/cc.go
index 0c32225..0bab41f 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -398,6 +398,13 @@
return ok && ccDepTag.Shared
}
+func IsStaticDepTag(depTag blueprint.DependencyTag) bool {
+ ccDepTag, ok := depTag.(DependencyTag)
+ return ok && (ccDepTag == staticExportDepTag ||
+ ccDepTag == lateStaticDepTag ||
+ ccDepTag == wholeStaticDepTag)
+}
+
func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
ccDepTag, ok := depTag.(DependencyTag)
return ok && ccDepTag == runtimeDepTag
@@ -463,6 +470,9 @@
makeLinkType string
// Kythe (source file indexer) paths for this compilation module
kytheFiles android.Paths
+
+ // name of the modules that are direct or indirect static deps of this module
+ allStaticDeps []string
}
func (c *Module) Toc() android.OptionalPath {
@@ -1258,6 +1268,15 @@
return results
}
+func gatherTransitiveStaticDeps(staticDeps []LinkableInterface) []string {
+ var ret []string
+ for _, dep := range staticDeps {
+ ret = append(ret, dep.Module().Name())
+ ret = append(ret, dep.AllStaticDeps()...)
+ }
+ return android.FirstUniqueStrings(ret)
+}
+
func (c *Module) IsTestPerSrcAllTestsVariation() bool {
test, ok := c.linker.(testPerSrc)
return ok && test.isAllTestsVariation()
@@ -2328,6 +2347,8 @@
c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
}
+ c.allStaticDeps = gatherTransitiveStaticDeps(directStaticDeps)
+
return depPaths
}
@@ -2463,6 +2484,10 @@
return c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid()
}
+func (c *Module) AllStaticDeps() []string {
+ return c.allStaticDeps
+}
+
func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
if c.linker != nil {
if library, ok := c.linker.(*libraryDecorator); ok {
diff --git a/cc/linkable.go b/cc/linkable.go
index 815d405..106092b 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -51,6 +51,8 @@
ToolchainLibrary() bool
NdkPrebuiltStl() bool
StubDecorator() bool
+
+ AllStaticDeps() []string
}
type DependencyTag struct {
diff --git a/java/java.go b/java/java.go
index 27f69b8..9f26e19 100644
--- a/java/java.go
+++ b/java/java.go
@@ -492,6 +492,14 @@
usesLibTag = dependencyTag{name: "uses-library"}
)
+func IsLibDepTag(depTag blueprint.DependencyTag) bool {
+ return depTag == libTag
+}
+
+func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
+ return depTag == staticLibTag
+}
+
type sdkDep struct {
useModule, useFiles, useDefaultLibs, invalidVersion bool
diff --git a/rust/rust.go b/rust/rust.go
index 0eab8d2..14513fb 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -346,6 +346,11 @@
return nil
}
+func (mod *Module) AllStaticDeps() []string {
+ // TODO(jiyong): do this for rust?
+ return nil
+}
+
func (mod *Module) Module() android.Module {
return mod
}