Loading core/clear_vars.mk +1 −0 Original line number Diff line number Diff line Loading @@ -277,6 +277,7 @@ LOCAL_SOONG_BUILT_INSTALLED := LOCAL_SOONG_BUNDLE := LOCAL_SOONG_CLASSES_JAR := LOCAL_SOONG_DEX_JAR := LOCAL_SOONG_DEXPREOPT_CONFIG := LOCAL_SOONG_EXPORT_PROGUARD_FLAGS := LOCAL_SOONG_HEADER_JAR := LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR := Loading core/definitions.mk +0 −8 Original line number Diff line number Diff line Loading @@ -631,14 +631,6 @@ $(strip \ ) endef ########################################################### ## Convert install path to on-device path. ########################################################### # $(1): install path define install-path-to-on-device-path $(patsubst $(PRODUCT_OUT)%,%,$(1)) endef ########################################################### ## The intermediates directory. Where object files go for ## a given target. We could technically get away without Loading core/dex_preopt_config_merger.py 0 → 100755 +100 −0 Original line number Diff line number Diff line #!/usr/bin/env python # # Copyright (C) 2021 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ A tool for merging dexpreopt.config files for <uses-library> dependencies into the dexpreopt.config file of the library/app that uses them. This is needed to generate class loader context (CLC) for dexpreopt. In Make there is no topological order when processing different modules, so a <uses-library> dependency module may have not been processed yet by the time the dependent module is processed. Therefore makefiles communicate the information from dependencies via dexpreopt.config files and add file-level dependencies from a module dexpreopt.config to its dependency configs. The actual patching of configs is done by this script, which is called from the makefiles. """ from __future__ import print_function import json from collections import OrderedDict import sys def main(): """Program entry point.""" if len(sys.argv) < 2: raise SystemExit('usage: %s <main-config> [dep-config ...]' % sys.argv[0]) # 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)) # The first config is the dexpreopted library/app, the rest are its # <uses-library> dependencies. cfg0 = cfgs[0] # Put dependency configs in a map keyed on module name (for easier lookup). uses_libs = {} for cfg in cfgs[1:]: uses_libs[cfg['Name']] = cfg # Load the original CLC map. clc_map = cfg0['ClassLoaderContexts'] # Create a new CLC map that will be a copy of the original one with patched # fields from dependency dexpreopt.config files. clc_map2 = OrderedDict() # Patch CLC for each SDK version. Although this should not be necessary for # compatibility libraries (so-called "conditional CLC"), because they all have # known names, known paths in system/framework, and no subcontext. But keep # the loop in case this changes in the future. for sdk_ver in clc_map: clcs = clc_map[sdk_ver] clcs2 = OrderedDict() for lib in clcs: clc = clcs[lib] if lib in uses_libs: ulib = uses_libs[lib] # On-host (build) path to the dependency DEX jar file. clc['Host'] = ulib['BuildPath'] # On-device (install) path to the dependency DEX jar file. clc['Device'] = ulib['DexLocation'] # CLC of the dependency becomes a subcontext. We only need sub-CLC for # 'any' version because all other versions are for compatibility # libraries, which exist only for apps and not for libraries. clc['Subcontexts'] = ulib['ClassLoaderContexts'].get('any') # Patch the library name in the CLC as well. clcs2[ulib['ProvidesUsesLibrary']] = clc else: # dexpreopt.config for this <uses-library> is not among the script # arguments, which may be the case with compatibility libraries that # don't need patching anyway. Just use the original CLC. clcs2[lib] = clc clc_map2[sdk_ver] = clcs2 # Overwrite the original class loader context with the patched one. cfg0['ClassLoaderContexts'] = clc_map2 # Update dexpreopt.config file. with open(sys.argv[1], 'w') as f: f.write(json.dumps(cfgs[0], indent=4, separators=(',', ': '))) if __name__ == '__main__': main() core/dex_preopt_odex_install.mk +53 −22 Original line number Diff line number Diff line Loading @@ -189,6 +189,7 @@ ifdef LOCAL_DEX_PREOPT my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \ $(LOCAL_OPTIONAL_USES_LIBRARIES)) ifeq ($(LOCAL_MODULE_CLASS),APPS) # compatibility libraries are added to class loader context of an app only if # targetSdkVersion in the app's manifest is lower than the given SDK version Loading @@ -207,6 +208,9 @@ ifdef LOCAL_DEX_PREOPT $(my_dexpreopt_libs_compat_28) \ $(my_dexpreopt_libs_compat_29) \ $(my_dexpreopt_libs_compat_30) else my_extra_dexpreopt_libs := endif my_dexpreopt_libs := $(sort \ $(LOCAL_USES_LIBRARIES) \ Loading @@ -215,13 +219,25 @@ ifdef LOCAL_DEX_PREOPT # 1: SDK version # 2: list of libraries # # Make does not process modules in topological order wrt. <uses-library> # dependencies, therefore we cannot rely on variables to get the information # about dependencies (in particular, their on-device path and class loader # context). This information is communicated via dexpreopt.config files: each # config depends on configs for <uses-library> dependencies of this module, # and the dex_preopt_config_merger.py script reads all configs and inserts the # missing bits from dependency configs into the module config. # # By default on-device path is /system/framework/*.jar, and class loader # subcontext is empty. These values are correct for compatibility libraries, # which are special and not handled by dex_preopt_config_merger.py. # add_json_class_loader_context = \ $(call add_json_map, $(1)) \ $(foreach lib, $(2),\ $(call add_json_map, $(lib)) \ $(eval file := $(filter %/$(lib).jar, $(call module-installed-files,$(lib)))) \ $(call add_json_str, Host, $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \ $(call add_json_str, Device, $(call install-path-to-on-device-path,$(file))) \ $(call add_json_str, Device, /system/framework/$(lib).jar) \ $(call add_json_map, Subcontexts, ${$}) $(call end_json_map) \ $(call end_json_map)) \ $(call end_json_map) Loading Loading @@ -275,12 +291,27 @@ ifdef LOCAL_DEX_PREOPT my_dexpreopt_config := $(intermediates)/dexpreopt.config my_dexpreopt_script := $(intermediates)/dexpreopt.sh my_dexpreopt_zip := $(intermediates)/dexpreopt.zip my_dexpreopt_config_merger := $(BUILD_SYSTEM)/dex_preopt_config_merger.py # Module dexpreopt.config depends on dexpreopt.config files of each # <uses-library> dependency, because these libraries may be processed after # the current module by Make (there's no topological order), so the dependency # information (paths, class loader context) may not be ready yet by the time # this dexpreopt.config is generated. So it's necessary to add file-level # dependencies between dexpreopt.config files. my_dexpreopt_dep_configs := $(foreach lib, \ $(filter-out $(my_dexpreopt_libs_compat),$(LOCAL_USES_LIBRARIES) $(my_filtered_optional_uses_libraries)), \ $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,)/dexpreopt.config) $(my_dexpreopt_config): $(my_dexpreopt_dep_configs) $(my_dexpreopt_config_merger) $(my_dexpreopt_config): PRIVATE_MODULE := $(LOCAL_MODULE) $(my_dexpreopt_config): PRIVATE_CONTENTS := $(json_contents) $(my_dexpreopt_config): PRIVATE_DEP_CONFIGS := $(my_dexpreopt_dep_configs) $(my_dexpreopt_config): PRIVATE_CONFIG_MERGER := $(my_dexpreopt_config_merger) $(my_dexpreopt_config): @echo "$(PRIVATE_MODULE) dexpreopt.config" echo -e -n '$(subst $(newline),\n,$(subst ','\'',$(subst \,\\,$(PRIVATE_CONTENTS))))' > $@ $(PRIVATE_CONFIG_MERGER) $@ $(PRIVATE_DEP_CONFIGS) .KATI_RESTAT: $(my_dexpreopt_script) $(my_dexpreopt_script): PRIVATE_MODULE := $(LOCAL_MODULE) Loading core/soong_java_prebuilt.mk +7 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ # LOCAL_SOONG_HEADER_JAR # LOCAL_SOONG_DEX_JAR # LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR # LOCAL_SOONG_DEXPREOPT_CONFIG ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK)) $(call pretty-error,soong_java_prebuilt.mk may only be used from Soong) Loading Loading @@ -146,6 +147,12 @@ ifdef LOCAL_SOONG_AAR ALL_MODULES.$(my_register_name).AAR := $(LOCAL_SOONG_AAR) endif # Copy dexpreopt.config files from Soong libraries to the location where Make # modules can find them. ifdef LOCAL_SOONG_DEXPREOPT_CONFIG $(eval $(call copy-one-file,$(LOCAL_SOONG_DEXPREOPT_CONFIG), $(call local-intermediates-dir,)/dexpreopt.config)) endif javac-check : $(full_classes_jar) javac-check-$(LOCAL_MODULE) : $(full_classes_jar) .PHONY: javac-check-$(LOCAL_MODULE) Loading Loading
core/clear_vars.mk +1 −0 Original line number Diff line number Diff line Loading @@ -277,6 +277,7 @@ LOCAL_SOONG_BUILT_INSTALLED := LOCAL_SOONG_BUNDLE := LOCAL_SOONG_CLASSES_JAR := LOCAL_SOONG_DEX_JAR := LOCAL_SOONG_DEXPREOPT_CONFIG := LOCAL_SOONG_EXPORT_PROGUARD_FLAGS := LOCAL_SOONG_HEADER_JAR := LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR := Loading
core/definitions.mk +0 −8 Original line number Diff line number Diff line Loading @@ -631,14 +631,6 @@ $(strip \ ) endef ########################################################### ## Convert install path to on-device path. ########################################################### # $(1): install path define install-path-to-on-device-path $(patsubst $(PRODUCT_OUT)%,%,$(1)) endef ########################################################### ## The intermediates directory. Where object files go for ## a given target. We could technically get away without Loading
core/dex_preopt_config_merger.py 0 → 100755 +100 −0 Original line number Diff line number Diff line #!/usr/bin/env python # # Copyright (C) 2021 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ A tool for merging dexpreopt.config files for <uses-library> dependencies into the dexpreopt.config file of the library/app that uses them. This is needed to generate class loader context (CLC) for dexpreopt. In Make there is no topological order when processing different modules, so a <uses-library> dependency module may have not been processed yet by the time the dependent module is processed. Therefore makefiles communicate the information from dependencies via dexpreopt.config files and add file-level dependencies from a module dexpreopt.config to its dependency configs. The actual patching of configs is done by this script, which is called from the makefiles. """ from __future__ import print_function import json from collections import OrderedDict import sys def main(): """Program entry point.""" if len(sys.argv) < 2: raise SystemExit('usage: %s <main-config> [dep-config ...]' % sys.argv[0]) # 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)) # The first config is the dexpreopted library/app, the rest are its # <uses-library> dependencies. cfg0 = cfgs[0] # Put dependency configs in a map keyed on module name (for easier lookup). uses_libs = {} for cfg in cfgs[1:]: uses_libs[cfg['Name']] = cfg # Load the original CLC map. clc_map = cfg0['ClassLoaderContexts'] # Create a new CLC map that will be a copy of the original one with patched # fields from dependency dexpreopt.config files. clc_map2 = OrderedDict() # Patch CLC for each SDK version. Although this should not be necessary for # compatibility libraries (so-called "conditional CLC"), because they all have # known names, known paths in system/framework, and no subcontext. But keep # the loop in case this changes in the future. for sdk_ver in clc_map: clcs = clc_map[sdk_ver] clcs2 = OrderedDict() for lib in clcs: clc = clcs[lib] if lib in uses_libs: ulib = uses_libs[lib] # On-host (build) path to the dependency DEX jar file. clc['Host'] = ulib['BuildPath'] # On-device (install) path to the dependency DEX jar file. clc['Device'] = ulib['DexLocation'] # CLC of the dependency becomes a subcontext. We only need sub-CLC for # 'any' version because all other versions are for compatibility # libraries, which exist only for apps and not for libraries. clc['Subcontexts'] = ulib['ClassLoaderContexts'].get('any') # Patch the library name in the CLC as well. clcs2[ulib['ProvidesUsesLibrary']] = clc else: # dexpreopt.config for this <uses-library> is not among the script # arguments, which may be the case with compatibility libraries that # don't need patching anyway. Just use the original CLC. clcs2[lib] = clc clc_map2[sdk_ver] = clcs2 # Overwrite the original class loader context with the patched one. cfg0['ClassLoaderContexts'] = clc_map2 # Update dexpreopt.config file. with open(sys.argv[1], 'w') as f: f.write(json.dumps(cfgs[0], indent=4, separators=(',', ': '))) if __name__ == '__main__': main()
core/dex_preopt_odex_install.mk +53 −22 Original line number Diff line number Diff line Loading @@ -189,6 +189,7 @@ ifdef LOCAL_DEX_PREOPT my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \ $(LOCAL_OPTIONAL_USES_LIBRARIES)) ifeq ($(LOCAL_MODULE_CLASS),APPS) # compatibility libraries are added to class loader context of an app only if # targetSdkVersion in the app's manifest is lower than the given SDK version Loading @@ -207,6 +208,9 @@ ifdef LOCAL_DEX_PREOPT $(my_dexpreopt_libs_compat_28) \ $(my_dexpreopt_libs_compat_29) \ $(my_dexpreopt_libs_compat_30) else my_extra_dexpreopt_libs := endif my_dexpreopt_libs := $(sort \ $(LOCAL_USES_LIBRARIES) \ Loading @@ -215,13 +219,25 @@ ifdef LOCAL_DEX_PREOPT # 1: SDK version # 2: list of libraries # # Make does not process modules in topological order wrt. <uses-library> # dependencies, therefore we cannot rely on variables to get the information # about dependencies (in particular, their on-device path and class loader # context). This information is communicated via dexpreopt.config files: each # config depends on configs for <uses-library> dependencies of this module, # and the dex_preopt_config_merger.py script reads all configs and inserts the # missing bits from dependency configs into the module config. # # By default on-device path is /system/framework/*.jar, and class loader # subcontext is empty. These values are correct for compatibility libraries, # which are special and not handled by dex_preopt_config_merger.py. # add_json_class_loader_context = \ $(call add_json_map, $(1)) \ $(foreach lib, $(2),\ $(call add_json_map, $(lib)) \ $(eval file := $(filter %/$(lib).jar, $(call module-installed-files,$(lib)))) \ $(call add_json_str, Host, $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \ $(call add_json_str, Device, $(call install-path-to-on-device-path,$(file))) \ $(call add_json_str, Device, /system/framework/$(lib).jar) \ $(call add_json_map, Subcontexts, ${$}) $(call end_json_map) \ $(call end_json_map)) \ $(call end_json_map) Loading Loading @@ -275,12 +291,27 @@ ifdef LOCAL_DEX_PREOPT my_dexpreopt_config := $(intermediates)/dexpreopt.config my_dexpreopt_script := $(intermediates)/dexpreopt.sh my_dexpreopt_zip := $(intermediates)/dexpreopt.zip my_dexpreopt_config_merger := $(BUILD_SYSTEM)/dex_preopt_config_merger.py # Module dexpreopt.config depends on dexpreopt.config files of each # <uses-library> dependency, because these libraries may be processed after # the current module by Make (there's no topological order), so the dependency # information (paths, class loader context) may not be ready yet by the time # this dexpreopt.config is generated. So it's necessary to add file-level # dependencies between dexpreopt.config files. my_dexpreopt_dep_configs := $(foreach lib, \ $(filter-out $(my_dexpreopt_libs_compat),$(LOCAL_USES_LIBRARIES) $(my_filtered_optional_uses_libraries)), \ $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,)/dexpreopt.config) $(my_dexpreopt_config): $(my_dexpreopt_dep_configs) $(my_dexpreopt_config_merger) $(my_dexpreopt_config): PRIVATE_MODULE := $(LOCAL_MODULE) $(my_dexpreopt_config): PRIVATE_CONTENTS := $(json_contents) $(my_dexpreopt_config): PRIVATE_DEP_CONFIGS := $(my_dexpreopt_dep_configs) $(my_dexpreopt_config): PRIVATE_CONFIG_MERGER := $(my_dexpreopt_config_merger) $(my_dexpreopt_config): @echo "$(PRIVATE_MODULE) dexpreopt.config" echo -e -n '$(subst $(newline),\n,$(subst ','\'',$(subst \,\\,$(PRIVATE_CONTENTS))))' > $@ $(PRIVATE_CONFIG_MERGER) $@ $(PRIVATE_DEP_CONFIGS) .KATI_RESTAT: $(my_dexpreopt_script) $(my_dexpreopt_script): PRIVATE_MODULE := $(LOCAL_MODULE) Loading
core/soong_java_prebuilt.mk +7 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ # LOCAL_SOONG_HEADER_JAR # LOCAL_SOONG_DEX_JAR # LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR # LOCAL_SOONG_DEXPREOPT_CONFIG ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK)) $(call pretty-error,soong_java_prebuilt.mk may only be used from Soong) Loading Loading @@ -146,6 +147,12 @@ ifdef LOCAL_SOONG_AAR ALL_MODULES.$(my_register_name).AAR := $(LOCAL_SOONG_AAR) endif # Copy dexpreopt.config files from Soong libraries to the location where Make # modules can find them. ifdef LOCAL_SOONG_DEXPREOPT_CONFIG $(eval $(call copy-one-file,$(LOCAL_SOONG_DEXPREOPT_CONFIG), $(call local-intermediates-dir,)/dexpreopt.config)) endif javac-check : $(full_classes_jar) javac-check-$(LOCAL_MODULE) : $(full_classes_jar) .PHONY: javac-check-$(LOCAL_MODULE) Loading