Refactor the contruction of the manifest check inputs.
This is a no-op change for a majority of cases. Before this change, the contruction of the manifest check inputs is confusing. It mutates uses_libs properties in place just for the manifest check, by replacing module names with library names for direct dependencies and merging library names from CLC for both direct denpendencies and transitive denpendencies, and then constructs manifest check inputs from those mutated uses_libs properties. This is error-prone and leads to insistency: the goal is to check that the CLC matches the manifest, but the inputs to the check don't reflect the CLC. After this change, we no longer mutate uses_libs properties in place. Instead, we maintain a separate list of missing denpendencies, and then construct manifest check inputs directly from the CLC for all existing libraries, no matter they are direct or transtive, and from the separate list of missing libraries. This change makes the logic more consistent and straightforward, and it also allows us to easily do the next change, which is to propagate transtive missing denpendencies. In fact, this change revealed several bugs around library optionality and order in CLC construction, and fixed them. Bug: 331528424 Test: m --no-skip-soong-tests Ignore-AOSP-First: Depends on internal changes. Will cherry-pick once merged. Merged-In: I0de82e76c47995b54aba9efd41538d950256a95f Change-Id: I0de82e76c47995b54aba9efd41538d950256a95f
This commit is contained in:
committed by
Android Build Cherrypicker Worker
parent
f875565c7f
commit
f98da19a07
@@ -805,12 +805,12 @@ func (a *AndroidLibrary) OutputFiles(tag string) (android.Paths, error) {
|
||||
var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
|
||||
|
||||
func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
a.usesLibrary.deps(ctx, false)
|
||||
a.Module.deps(ctx)
|
||||
sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
|
||||
if sdkDep.hasFrameworkLibs() {
|
||||
a.aapt.deps(ctx, sdkDep)
|
||||
}
|
||||
a.usesLibrary.deps(ctx, false)
|
||||
|
||||
for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
|
||||
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
|
||||
@@ -1374,6 +1374,12 @@ func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
|
||||
|
||||
var _ android.PrebuiltInterface = (*AARImport)(nil)
|
||||
|
||||
func (a *AARImport) UsesLibrary() *usesLibrary {
|
||||
return &a.usesLibrary
|
||||
}
|
||||
|
||||
var _ ModuleWithUsesLibrary = (*AARImport)(nil)
|
||||
|
||||
// android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
|
||||
//
|
||||
// This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of
|
||||
|
77
java/app.go
77
java/app.go
@@ -249,13 +249,13 @@ func (c Certificate) AndroidMkString() string {
|
||||
}
|
||||
|
||||
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
a.Module.deps(ctx)
|
||||
|
||||
if String(a.appProperties.Stl) == "c++_shared" && !a.SdkVersion(ctx).Specified() {
|
||||
ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
|
||||
}
|
||||
|
||||
sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
|
||||
a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
|
||||
a.Module.deps(ctx)
|
||||
if sdkDep.hasFrameworkLibs() {
|
||||
a.aapt.deps(ctx, sdkDep)
|
||||
}
|
||||
@@ -285,9 +285,6 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
}
|
||||
ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)
|
||||
}
|
||||
|
||||
a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
|
||||
|
||||
for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
|
||||
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
|
||||
}
|
||||
@@ -811,18 +808,10 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
// The decision to enforce <uses-library> checks is made before adding implicit SDK libraries.
|
||||
a.usesLibrary.freezeEnforceUsesLibraries()
|
||||
|
||||
// Add implicit SDK libraries to <uses-library> list.
|
||||
requiredUsesLibs, optionalUsesLibs := a.classLoaderContexts.UsesLibs()
|
||||
for _, usesLib := range requiredUsesLibs {
|
||||
a.usesLibrary.addLib(usesLib, false)
|
||||
}
|
||||
for _, usesLib := range optionalUsesLibs {
|
||||
a.usesLibrary.addLib(usesLib, true)
|
||||
}
|
||||
|
||||
// Check that the <uses-library> list is coherent with the manifest.
|
||||
if a.usesLibrary.enforceUsesLibraries() {
|
||||
manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
|
||||
manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(
|
||||
ctx, a.mergedManifestFile, &a.classLoaderContexts)
|
||||
apkDeps = append(apkDeps, manifestCheckFile)
|
||||
}
|
||||
|
||||
@@ -1580,6 +1569,9 @@ type UsesLibraryProperties struct {
|
||||
// provide the android.test.base statically and use jarjar to rename them so they do not collide
|
||||
// with the classes provided by the android.test.base library.
|
||||
Exclude_uses_libs []string
|
||||
|
||||
// The module names of optional uses-library libraries that are missing from the source tree.
|
||||
Missing_optional_uses_libs []string `blueprint:"mutated"`
|
||||
}
|
||||
|
||||
// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
|
||||
@@ -1596,20 +1588,11 @@ type usesLibrary struct {
|
||||
shouldDisableDexpreopt bool
|
||||
}
|
||||
|
||||
func (u *usesLibrary) addLib(lib string, optional bool) {
|
||||
if !android.InList(lib, u.usesLibraryProperties.Uses_libs) && !android.InList(lib, u.usesLibraryProperties.Optional_uses_libs) {
|
||||
if optional {
|
||||
u.usesLibraryProperties.Optional_uses_libs = append(u.usesLibraryProperties.Optional_uses_libs, lib)
|
||||
} else {
|
||||
u.usesLibraryProperties.Uses_libs = append(u.usesLibraryProperties.Uses_libs, lib)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps bool) {
|
||||
if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
|
||||
ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
|
||||
ctx.AddVariationDependencies(nil, usesLibOptTag, u.presentOptionalUsesLibs(ctx)...)
|
||||
presentOptionalUsesLibs := u.presentOptionalUsesLibs(ctx)
|
||||
ctx.AddVariationDependencies(nil, usesLibOptTag, presentOptionalUsesLibs...)
|
||||
// Only add these extra dependencies if the module is an app that depends on framework
|
||||
// libs. This avoids creating a cyclic dependency:
|
||||
// e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
|
||||
@@ -1620,6 +1603,8 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps boo
|
||||
ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
|
||||
ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
|
||||
}
|
||||
_, diff, _ := android.ListSetDifference(u.usesLibraryProperties.Optional_uses_libs, presentOptionalUsesLibs)
|
||||
u.usesLibraryProperties.Missing_optional_uses_libs = diff
|
||||
} else {
|
||||
ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs...)
|
||||
ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...)
|
||||
@@ -1638,15 +1623,6 @@ func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []s
|
||||
return optionalUsesLibs
|
||||
}
|
||||
|
||||
// Helper function to replace string in a list.
|
||||
func replaceInList(list []string, oldstr, newstr string) {
|
||||
for i, str := range list {
|
||||
if str == oldstr {
|
||||
list[i] = newstr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a map of module names of shared library dependencies to the paths to their dex jars on
|
||||
// host and on device.
|
||||
func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap {
|
||||
@@ -1688,11 +1664,6 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
|
||||
libName := dep
|
||||
if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
|
||||
libName = *ulib.ProvidesUsesLib()
|
||||
// Replace module name with library name in `uses_libs`/`optional_uses_libs` in
|
||||
// order to pass verify_uses_libraries check (which compares these properties
|
||||
// against library names written in the manifest).
|
||||
replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
|
||||
replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
|
||||
}
|
||||
clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
|
||||
lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(),
|
||||
@@ -1726,7 +1697,7 @@ func (u *usesLibrary) freezeEnforceUsesLibraries() {
|
||||
// an APK with the manifest embedded in it (manifest_check will know which one it is by the file
|
||||
// extension: APKs are supposed to end with '.apk').
|
||||
func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile android.Path,
|
||||
outputFile android.WritablePath) android.Path {
|
||||
outputFile android.WritablePath, classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
|
||||
|
||||
statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
|
||||
|
||||
@@ -1754,27 +1725,37 @@ func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile a
|
||||
cmd.Flag("--enforce-uses-libraries-relax")
|
||||
}
|
||||
|
||||
for _, lib := range u.usesLibraryProperties.Uses_libs {
|
||||
requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
|
||||
for _, lib := range requiredUsesLibs {
|
||||
cmd.FlagWithArg("--uses-library ", lib)
|
||||
}
|
||||
|
||||
for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
|
||||
for _, lib := range optionalUsesLibs {
|
||||
cmd.FlagWithArg("--optional-uses-library ", lib)
|
||||
}
|
||||
|
||||
// Also add missing optional uses libs, as the manifest check expects them.
|
||||
// Note that what we add here are the module names of those missing libs, not library names, while
|
||||
// the manifest check actually expects library names. However, the case where a library is missing
|
||||
// and the module name != the library name is too rare for us to handle.
|
||||
for _, lib := range u.usesLibraryProperties.Missing_optional_uses_libs {
|
||||
cmd.FlagWithArg("--missing-optional-uses-library ", lib)
|
||||
}
|
||||
|
||||
rule.Build("verify_uses_libraries", "verify <uses-library>")
|
||||
return outputFile
|
||||
}
|
||||
|
||||
// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against
|
||||
// the build system and returns the path to a copy of the manifest.
|
||||
func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
|
||||
func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path,
|
||||
classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
|
||||
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
|
||||
return u.verifyUsesLibraries(ctx, manifest, outputFile)
|
||||
return u.verifyUsesLibraries(ctx, manifest, outputFile, classLoaderContexts)
|
||||
}
|
||||
|
||||
// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the build
|
||||
// system and returns the path to a copy of the APK.
|
||||
func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) {
|
||||
u.verifyUsesLibraries(ctx, apk, nil) // for APKs manifest_check does not write output file
|
||||
func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path,
|
||||
classLoaderContexts *dexpreopt.ClassLoaderContextMap) {
|
||||
u.verifyUsesLibraries(ctx, apk, nil, classLoaderContexts) // for APKs manifest_check does not write output file
|
||||
}
|
||||
|
@@ -355,7 +355,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
|
||||
}
|
||||
|
||||
if a.usesLibrary.enforceUsesLibraries() {
|
||||
a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
|
||||
a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk, &a.dexpreopter.classLoaderContexts)
|
||||
}
|
||||
|
||||
a.dexpreopter.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), jnisUncompressed)
|
||||
@@ -611,6 +611,12 @@ func createArchDpiVariantGroupType(archNames []string, dpiNames []string) reflec
|
||||
return return_struct
|
||||
}
|
||||
|
||||
func (a *AndroidAppImport) UsesLibrary() *usesLibrary {
|
||||
return &a.usesLibrary
|
||||
}
|
||||
|
||||
var _ ModuleWithUsesLibrary = (*AndroidAppImport)(nil)
|
||||
|
||||
// android_app_import imports a prebuilt apk with additional processing specified in the module.
|
||||
// DPI-specific apk source files can be specified using dpi_variants. Example:
|
||||
//
|
||||
|
@@ -3280,7 +3280,7 @@ func TestUsesLibraries(t *testing.T) {
|
||||
sdk_version: "current",
|
||||
optional_uses_libs: [
|
||||
"bar",
|
||||
"baz",
|
||||
"missing-lib-b",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -3295,7 +3295,7 @@ func TestUsesLibraries(t *testing.T) {
|
||||
],
|
||||
optional_uses_libs: [
|
||||
"bar",
|
||||
"baz",
|
||||
"missing-lib-b",
|
||||
],
|
||||
}
|
||||
`
|
||||
@@ -3317,10 +3317,10 @@ func TestUsesLibraries(t *testing.T) {
|
||||
// propagated from dependencies.
|
||||
actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
||||
expectManifestFixerArgs := `--extract-native-libs=true ` +
|
||||
`--uses-library qux ` +
|
||||
`--uses-library quuz ` +
|
||||
`--uses-library foo ` +
|
||||
`--uses-library com.non.sdk.lib ` +
|
||||
`--uses-library qux ` +
|
||||
`--uses-library quuz ` +
|
||||
`--uses-library runtime-library ` +
|
||||
`--uses-library runtime-required-x ` +
|
||||
`--uses-library runtime-required-y ` +
|
||||
@@ -3339,9 +3339,9 @@ func TestUsesLibraries(t *testing.T) {
|
||||
`--uses-library runtime-required-x ` +
|
||||
`--uses-library runtime-required-y ` +
|
||||
`--optional-uses-library bar ` +
|
||||
`--optional-uses-library baz ` +
|
||||
`--optional-uses-library runtime-optional-x ` +
|
||||
`--optional-uses-library runtime-optional-y `
|
||||
`--optional-uses-library runtime-optional-y ` +
|
||||
`--missing-optional-uses-library missing-lib-b `
|
||||
android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
|
||||
|
||||
// Test that all libraries are verified for an APK (library order matters).
|
||||
@@ -3350,7 +3350,7 @@ func TestUsesLibraries(t *testing.T) {
|
||||
`--uses-library com.non.sdk.lib ` +
|
||||
`--uses-library android.test.runner ` +
|
||||
`--optional-uses-library bar ` +
|
||||
`--optional-uses-library baz `
|
||||
`--missing-optional-uses-library missing-lib-b `
|
||||
android.AssertStringDoesContain(t, "verify apk cmd args", verifyApkCmd, verifyApkArgs)
|
||||
|
||||
// Test that necessary args are passed for constructing CLC in Ninja phase.
|
||||
|
16
java/base.go
16
java/base.go
@@ -837,9 +837,11 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
|
||||
if dep != nil {
|
||||
if component, ok := dep.(SdkLibraryComponentDependency); ok {
|
||||
if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
|
||||
// Add library as optional if it's one of the optional compatibility libs.
|
||||
// Add library as optional if it's one of the optional compatibility libs or it's
|
||||
// explicitly listed in the optional_uses_libs property.
|
||||
tag := usesLibReqTag
|
||||
if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) {
|
||||
if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) ||
|
||||
android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs) {
|
||||
tag = usesLibOptTag
|
||||
}
|
||||
ctx.AddVariationDependencies(nil, tag, *lib)
|
||||
@@ -2706,3 +2708,13 @@ type ModuleWithStem interface {
|
||||
}
|
||||
|
||||
var _ ModuleWithStem = (*Module)(nil)
|
||||
|
||||
type ModuleWithUsesLibrary interface {
|
||||
UsesLibrary() *usesLibrary
|
||||
}
|
||||
|
||||
func (j *Module) UsesLibrary() *usesLibrary {
|
||||
return &j.usesLibrary
|
||||
}
|
||||
|
||||
var _ ModuleWithUsesLibrary = (*Module)(nil)
|
||||
|
10
java/java.go
10
java/java.go
@@ -960,8 +960,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
}
|
||||
|
||||
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
j.deps(ctx)
|
||||
j.usesLibrary.deps(ctx, false)
|
||||
j.deps(ctx)
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -3138,7 +3138,13 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
|
||||
// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
|
||||
// from its CLC should be added to the current CLC.
|
||||
if sdkLib != nil {
|
||||
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
|
||||
optional := false
|
||||
if module, ok := ctx.Module().(ModuleWithUsesLibrary); ok {
|
||||
if android.InList(*sdkLib, module.UsesLibrary().usesLibraryProperties.Optional_uses_libs) {
|
||||
optional = true
|
||||
}
|
||||
}
|
||||
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, optional,
|
||||
dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
|
||||
} else {
|
||||
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
|
||||
|
Reference in New Issue
Block a user