manifest_check.py: translate library names using dexpreopt configs.

Java modules that are defined in makefiles are not processed in
topological order, so it is necessary to communicate information from
dependencies via dexpreopt.config files. This has already been done in
make/core/dex_preopt_config_merger.py, and now manifest_check.py also
needs to get library names from their dexpreopt.config files.

This is to accommodate Java libraries which name differs from their
modules name. Soong properties `uses_libs`/`optional_uses_libs` and
makefile vars `LOCAL_USES_LIBRARIES`/`LOCAL_OPTIONAL_USES_LIBRARIES`
contain module names, not library names, so it is necessary to translate
them when comparing against library names in the manifest.

Bug: 132357300

Test: lunch cf_x86_64_phone-userdebug && m && launch_cvd \
      adb wait-for-device && adb root && adb logcat \
      | grep -E 'ClassLoaderContext [a-z ]+ mismatch'
      # empty grep output, no errors

Change-Id: I7cfb17d6d74e37fc9f37d977f15f0d711bab5c8e
This commit is contained in:
Ulya Trafimovich 2021-03-04 18:06:27 +00:00
parent a76d6606ce
commit 3c902e7acc
1 changed files with 45 additions and 9 deletions

View File

@ -19,6 +19,7 @@
from __future__ import print_function
import argparse
import json
import re
import subprocess
import sys
@ -61,6 +62,10 @@ def parse_args():
dest='extract_target_sdk_version',
action='store_true',
help='print the targetSdkVersion from the manifest')
parser.add_argument('--dexpreopt-config',
dest='dexpreopt_configs',
action='append',
help='a paths to a dexpreopt.config of some library')
parser.add_argument('--aapt',
dest='aapt',
help='path to aapt executable')
@ -85,12 +90,6 @@ def enforce_uses_libraries(manifest, required, optional, relax, is_apk = False):
else:
manifest_required, manifest_optional = extract_uses_libs_xml(manifest)
if required is None:
required = []
if optional is None:
optional = []
err = []
if manifest_required != required:
err.append('Expected required <uses-library> tags "%s", got "%s"' %
@ -222,6 +221,35 @@ def extract_target_sdk_version_xml(xml):
return target_attr.value
def load_dexpreopt_configs(configs):
"""Load dexpreopt.config files and map module names to library names."""
module_to_libname = {}
if configs is None:
configs = []
for config in configs:
with open(config, 'r') as f:
contents = json.load(f)
module_to_libname[contents['Name']] = contents['ProvidesUsesLibrary']
return module_to_libname
def translate_libnames(modules, module_to_libname):
"""Translate module names into library names using the mapping."""
if modules is None:
modules = []
libnames = []
for name in modules:
if name in module_to_libname:
name = module_to_libname[name]
libnames.append(name)
return libnames
def main():
"""Program entry point."""
try:
@ -237,12 +265,20 @@ def main():
manifest = minidom.parse(args.input)
if args.enforce_uses_libraries:
# Load dexpreopt.config files and build a mapping from module names to
# library names. This is necessary because build system addresses
# libraries by their module name (`uses_libs`, `optional_uses_libs`,
# `LOCAL_USES_LIBRARIES`, `LOCAL_OPTIONAL_LIBRARY_NAMES` all contain
# module names), while the manifest addresses libraries by their name.
mod_to_lib = load_dexpreopt_configs(args.dexpreopt_configs)
required = translate_libnames(args.uses_libraries, mod_to_lib)
optional = translate_libnames(args.optional_uses_libraries, mod_to_lib)
# Check if the <uses-library> lists in the build system agree with those
# in the manifest. Raise an exception on mismatch, unless the script was
# passed a special parameter to suppress exceptions.
errmsg = enforce_uses_libraries(manifest, args.uses_libraries,
args.optional_uses_libraries, args.enforce_uses_libraries_relax,
is_apk)
errmsg = enforce_uses_libraries(manifest, required, optional,
args.enforce_uses_libraries_relax, is_apk)
# Create a status file that is empty on success, or contains an error
# message on failure. When exceptions are suppressed, dexpreopt command