Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 114ff53f authored by Jiyong Park's avatar Jiyong Park
Browse files

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
parent e6029182
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -185,8 +185,8 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
				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 != "" {
+19 −5
Original line number Diff line number Diff line
@@ -511,8 +511,13 @@ type apexBundle struct {
	// 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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
			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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
							//
							// 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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
						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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
						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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {

	apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())
	a.compatSymlinks = makeCompatSymlinks(apexName, ctx)
	a.buildApexDependencyInfo(ctx)
}

func newApexBundle() *apexBundle {
+19 −6
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*andr
		"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 @@ func TestBasicApex(t *testing.T) {
	}
	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 TestApexWithStubs(t *testing.T) {
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 @@ func TestApexWithExplicitStubsDependency(t *testing.T) {

	`)

	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 @@ func TestApexWithExplicitStubsDependency(t *testing.T) {
	// 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 @@ 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")
	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 @@ func TestInstallExtraFlattenedApexes(t *testing.T) {
		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)
+37 −0
Original line number Diff line number Diff line
@@ -553,3 +553,40 @@ func (a *apexBundle) getOverrideManifestPackageName(ctx android.ModuleContext) s
	}
	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},
	})
}
+25 −0
Original line number Diff line number Diff line
@@ -398,6 +398,13 @@ func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
	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 @@ type Module struct {
	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 @@ func orderStaticModuleDeps(module LinkableInterface, staticDeps []LinkableInterf
	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 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
		c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
	}

	c.allStaticDeps = gatherTransitiveStaticDeps(directStaticDeps)

	return depPaths
}

@@ -2463,6 +2484,10 @@ func (c *Module) installable() bool {
	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 {
Loading