Dexpreopt: prepare to merge class loader context from all deps.
The makefile implementation of dexpreopt is lagging behind the Soong implementation in the way it handles transitive dependencies: Soong propagates class loader context through transitive dependencies, such as static libraries, but makefiles only propagate that information through uses-library dependencies. This discrepancy is caused by the difficulty of handling class loader contexts in makefies: since there is no topological order in handling module and its dependencies, the information is propagated via file level dependencies on dexpreopt.configs and merged into the module's dexpreopt.config with a python script. To handle transitive dependencies correctly, it is necessary to generate dexpreopt.config files for all libraries, not just those that enable dexpreopt. This change only prepares dex_preopt_odex_install.mk for that and updates if for corresponding changes in manifest_check.py. It does not enable generation of dexpreopt.config files for non uses-library dependencies (e.g. static libraries). This will be done as a follow-up. Changes: - renamed option for dependency dexpreopt.config files - added option for self dexpreopt.config - moved variable definitions so that they can be used both by uses-library check and dexpreopt command - add 'Optional' field in makefile-generated dexpreopt.config to align it on par with Soong-generated configs - modify dex_preopt_config_merger.py to add uses-libraries propagated via dexpreopt.config files Bug: 214255490 Test: lunch aosp_cf_x86_64_phone-userdebug && m && launch_cvd \ && adb wait-for-device && adb root \ && adb logcat | grep -E 'ClassLoaderContext [a-z ]+ mismatch' # a few unrelated errors caused by missing optional uses-libraries # android.net.ipsec.ike # androidx.window.extensions # androidx.window.sidecar # that were present before this patch Change-Id: I6522319a8415f22f90fc96059a34675fb830e5cc
This commit is contained in:
@@ -31,6 +31,7 @@ from __future__ import print_function
|
||||
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
@@ -42,8 +43,9 @@ def main():
|
||||
# Read all JSON configs.
|
||||
cfgs = []
|
||||
for arg in sys.argv[1:]:
|
||||
with open(arg, 'r') as f:
|
||||
cfgs.append(json.load(f, object_pairs_hook=OrderedDict))
|
||||
if os.stat(arg).st_size != 0:
|
||||
with open(arg, 'r') as f:
|
||||
cfgs.append(json.load(f, object_pairs_hook=OrderedDict))
|
||||
|
||||
# The first config is the dexpreopted library/app, the rest are its
|
||||
# <uses-library> dependencies.
|
||||
@@ -88,6 +90,33 @@ def main():
|
||||
clcs2.append(clc)
|
||||
clc_map2[sdk_ver] = clcs2
|
||||
|
||||
# Go over all uses-libraries in dependency dexpreopt.config files (these don't
|
||||
# have to be uses-libraries themselves, they can be e.g. transitive static
|
||||
# library dependencies) and merge their CLC to the current one
|
||||
for ulib, cfg in uses_libs.items():
|
||||
any_sdk_ver = 'any' # not interested in compatibility libraries
|
||||
clcs = cfg['ClassLoaderContexts'].get(any_sdk_ver, [])
|
||||
|
||||
# If the dependency is a uses-library itself, its uses-library dependencies
|
||||
# are added as a subcontext, so don't add them to top-level CLC.
|
||||
dep_is_a_uses_lib = False
|
||||
for clc2 in clc_map2[any_sdk_ver]:
|
||||
if clc2['Name'] == cfg['ProvidesUsesLibrary']:
|
||||
dep_is_a_uses_lib = True
|
||||
if dep_is_a_uses_lib:
|
||||
continue
|
||||
|
||||
# Check if CLC for these libraries is already present (avoid duplicates).
|
||||
# Don't bother optimizing quadratic loop, since CLC is typically small.
|
||||
for clc in clcs:
|
||||
already_in_clc = False
|
||||
for clc2 in clc_map2[any_sdk_ver]:
|
||||
if clc2['Name'] == clc['Name']:
|
||||
already_in_clc = True
|
||||
break
|
||||
if not already_in_clc:
|
||||
clc_map2[any_sdk_ver] += clcs
|
||||
|
||||
# Overwrite the original class loader context with the patched one.
|
||||
cfg0['ClassLoaderContexts'] = clc_map2
|
||||
|
||||
|
Reference in New Issue
Block a user