diff options
Diffstat (limited to 'core/dex_preopt_odex_install.mk')
-rw-r--r-- | core/dex_preopt_odex_install.mk | 228 |
1 files changed, 197 insertions, 31 deletions
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk index 9dbddf6a59..a2837f3504 100644 --- a/core/dex_preopt_odex_install.mk +++ b/core/dex_preopt_odex_install.mk @@ -1,5 +1,6 @@ # dexpreopt_odex_install.mk is used to define odex creation rules for JARs and APKs # This file depends on variables set in base_rules.mk +# Input variables: my_manifest_or_apk # Output variables: LOCAL_DEX_PREOPT, LOCAL_UNCOMPRESS_DEX ifeq (true,$(LOCAL_USE_EMBEDDED_DEX)) @@ -30,7 +31,7 @@ ifeq (false,$(LOCAL_DEX_PREOPT)) LOCAL_DEX_PREOPT := endif -# Only enable preopt for non tests. +# Disable preopt for tests. ifneq (,$(filter $(LOCAL_MODULE_TAGS),tests)) LOCAL_DEX_PREOPT := endif @@ -40,8 +41,8 @@ ifneq (,$(filter $(LOCAL_MODULE),$(DEXPREOPT_DISABLED_MODULES))) LOCAL_DEX_PREOPT := endif -# Disable preopt for TARGET_BUILD_APPS -ifneq (,$(TARGET_BUILD_APPS)) +# Disable preopt for DISABLE_PREOPT +ifeq (true,$(DISABLE_PREOPT)) LOCAL_DEX_PREOPT := endif @@ -54,7 +55,8 @@ ifdef LOCAL_UNINSTALLABLE_MODULE LOCAL_DEX_PREOPT := endif -ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file)$(LOCAL_SOONG_DEX_JAR))) # contains no java code +# Disable preopt if the app contains no java code. +ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file)$(LOCAL_SOONG_DEX_JAR))) LOCAL_DEX_PREOPT := endif @@ -68,9 +70,10 @@ endif # /data. If we don't do this they will need to be extracted which is not favorable for RAM usage # or performance. If my_preopt_for_extracted_apk is true, we ignore the only preopt boot image # options. +system_server_jars := $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(call word-colon,2,$(m))) ifneq (true,$(my_preopt_for_extracted_apk)) ifeq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY)) - ifeq ($(filter $(PRODUCT_SYSTEM_SERVER_JARS) $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)),) + ifeq ($(filter $(system_server_jars) $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)),) LOCAL_DEX_PREOPT := endif endif @@ -108,10 +111,172 @@ ifeq (true,$(my_process_profile)) endif endif +################################################################################ +# Local module variables and functions used in dexpreopt and manifest_check. +################################################################################ + +my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \ + $(LOCAL_OPTIONAL_USES_LIBRARIES)) + +# TODO(b/132357300): This may filter out too much, as PRODUCT_PACKAGES doesn't +# include all packages (the full list is unknown until reading all Android.mk +# makefiles). As a consequence, a library may be present but not included in +# dexpreopt, which will result in class loader context mismatch and a failure +# to load dexpreopt code on device. We should fix this, either by deferring +# dependency computation until the full list of product packages is known, or +# by adding product-specific lists of missing libraries. +my_filtered_optional_uses_libraries := $(filter $(PRODUCT_PACKAGES), \ + $(my_filtered_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 + + my_dexpreopt_libs_compat_28 := \ + org.apache.http.legacy + + my_dexpreopt_libs_compat_29 := \ + android.hidl.manager-V1.0-java \ + android.hidl.base-V1.0-java + + my_dexpreopt_libs_compat_30 := \ + android.test.base \ + android.test.mock + + my_dexpreopt_libs_compat := \ + $(my_dexpreopt_libs_compat_28) \ + $(my_dexpreopt_libs_compat_29) \ + $(my_dexpreopt_libs_compat_30) +else + my_dexpreopt_libs_compat := +endif + +my_dexpreopt_libs := \ + $(LOCAL_USES_LIBRARIES) \ + $(my_filtered_optional_uses_libraries) + +# 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) + +# 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_array, $(1)) \ + $(foreach lib, $(2),\ + $(call add_json_map_anon) \ + $(call add_json_str, Name, $(lib)) \ + $(call add_json_str, Host, $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \ + $(call add_json_str, Device, /system/framework/$(lib).jar) \ + $(call add_json_val, Subcontexts, null) \ + $(call end_json_map)) \ + $(call end_json_array) + +################################################################################ +# Verify <uses-library> coherence between the build system and the manifest. +################################################################################ + +# Some libraries do not have a manifest, so there is nothing to check against. +# Handle it as if the manifest had zero <uses-library> tags: it is ok unless the +# module has non-empty LOCAL_USES_LIBRARIES or LOCAL_OPTIONAL_USES_LIBRARIES. +ifndef my_manifest_or_apk + ifneq (,$(strip $(LOCAL_USES_LIBRARIES)$(LOCAL_OPTIONAL_USES_LIBRARIES))) + $(error $(LOCAL_MODULE) has non-empty <uses-library> list but no manifest) + else + LOCAL_ENFORCE_USES_LIBRARIES := false + endif +endif + +# Disable the check for tests. +ifneq (,$(filter $(LOCAL_MODULE_TAGS),tests)) + LOCAL_ENFORCE_USES_LIBRARIES := false +endif +ifneq (,$(LOCAL_COMPATIBILITY_SUITE)) + LOCAL_ENFORCE_USES_LIBRARIES := false +endif + +# Disable the check if the app contains no java code. +ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file)$(LOCAL_SOONG_DEX_JAR))) + LOCAL_ENFORCE_USES_LIBRARIES := false +endif + +# Disable <uses-library> checks if dexpreopt is globally disabled. +# Without dexpreopt the check is not necessary, and although it is good to have, +# it is difficult to maintain on non-linux build platforms where dexpreopt is +# generally disabled (the check may fail due to various unrelated reasons, such +# as a failure to get manifest from an APK). +ifneq (true,$(WITH_DEXPREOPT)) + LOCAL_ENFORCE_USES_LIBRARIES := false +else ifeq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY)) + LOCAL_ENFORCE_USES_LIBRARIES := false +endif + +# Verify LOCAL_USES_LIBRARIES/LOCAL_OPTIONAL_USES_LIBRARIES against the manifest. +ifndef LOCAL_ENFORCE_USES_LIBRARIES + LOCAL_ENFORCE_USES_LIBRARIES := true +endif + +my_enforced_uses_libraries := +ifeq (true,$(LOCAL_ENFORCE_USES_LIBRARIES)) + my_verify_script := build/soong/scripts/manifest_check.py + my_uses_libs_args := $(patsubst %,--uses-library %,$(LOCAL_USES_LIBRARIES)) + my_optional_uses_libs_args := $(patsubst %,--optional-uses-library %, \ + $(LOCAL_OPTIONAL_USES_LIBRARIES)) + my_relax_check_arg := $(if $(filter true,$(RELAX_USES_LIBRARY_CHECK)), \ + --enforce-uses-libraries-relax,) + my_dexpreopt_config_args := $(patsubst %,--dexpreopt-config %,$(my_dexpreopt_dep_configs)) + + my_enforced_uses_libraries := $(intermediates.COMMON)/enforce_uses_libraries.status + $(my_enforced_uses_libraries): PRIVATE_USES_LIBRARIES := $(my_uses_libs_args) + $(my_enforced_uses_libraries): PRIVATE_OPTIONAL_USES_LIBRARIES := $(my_optional_uses_libs_args) + $(my_enforced_uses_libraries): PRIVATE_DEXPREOPT_CONFIGS := $(my_dexpreopt_config_args) + $(my_enforced_uses_libraries): PRIVATE_RELAX_CHECK := $(my_relax_check_arg) + $(my_enforced_uses_libraries): $(AAPT) + $(my_enforced_uses_libraries): $(my_verify_script) + $(my_enforced_uses_libraries): $(my_dexpreopt_dep_configs) + $(my_enforced_uses_libraries): $(my_manifest_or_apk) + @echo Verifying uses-libraries: $< + rm -f $@ + $(my_verify_script) \ + --enforce-uses-libraries \ + --enforce-uses-libraries-status $@ \ + --aapt $(AAPT) \ + $(PRIVATE_USES_LIBRARIES) \ + $(PRIVATE_OPTIONAL_USES_LIBRARIES) \ + $(PRIVATE_DEXPREOPT_CONFIGS) \ + $(PRIVATE_RELAX_CHECK) \ + $< + $(LOCAL_BUILT_MODULE) : $(my_enforced_uses_libraries) +endif + +################################################################################ +# Dexpreopt command. +################################################################################ + my_dexpreopt_archs := my_dexpreopt_images := my_dexpreopt_images_deps := -my_dexpreopt_image_locations := +my_dexpreopt_image_locations_on_host := +my_dexpreopt_image_locations_on_device := my_dexpreopt_infix := boot ifeq (true, $(DEXPREOPT_USE_ART_IMAGE)) my_dexpreopt_infix := art @@ -184,23 +349,8 @@ ifdef LOCAL_DEX_PREOPT endif # TARGET_2ND_ARCH endif # LOCAL_MODULE_CLASS - my_dexpreopt_image_locations += $(DEXPREOPT_IMAGE_LOCATIONS_$(my_dexpreopt_infix)) - - my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \ - $(LOCAL_OPTIONAL_USES_LIBRARIES)) - - # dexpreopt needs the paths to the dex jars of these libraries in case - # construct_context.sh needs to pass them to dex2oat. - my_extra_dexpreopt_libs := \ - org.apache.http.legacy \ - android.hidl.base-V1.0-java \ - android.hidl.manager-V1.0-java \ - - my_dexpreopt_libs := $(sort \ - $(LOCAL_USES_LIBRARIES) \ - $(my_filtered_optional_uses_libraries) \ - $(my_extra_dexpreopt_libs) \ - ) + my_dexpreopt_image_locations_on_host += $(DEXPREOPT_IMAGE_LOCATIONS_ON_HOST$(my_dexpreopt_infix)) + my_dexpreopt_image_locations_on_device += $(DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE$(my_dexpreopt_infix)) # Record dex-preopt config. DEXPREOPT.$(LOCAL_MODULE).DEX_PREOPT := $(LOCAL_DEX_PREOPT) @@ -228,16 +378,19 @@ ifdef LOCAL_DEX_PREOPT $(call add_json_list, PreoptFlags, $(LOCAL_DEX_PREOPT_FLAGS)) $(call add_json_str, ProfileClassListing, $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE))) $(call add_json_bool, ProfileIsTextListing, $(my_profile_is_text_listing)) - $(call add_json_bool, EnforceUsesLibraries, $(LOCAL_ENFORCE_USES_LIBRARIES)) - $(call add_json_list, OptionalUsesLibraries, $(my_filtered_optional_uses_libraries)) - $(call add_json_list, UsesLibraries, $(LOCAL_USES_LIBRARIES)) - $(call add_json_map, LibraryPaths) - $(foreach lib,$(my_dexpreopt_libs),\ - $(call add_json_str, $(lib), $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar)) + $(call add_json_str, EnforceUsesLibrariesStatusFile, $(my_enforced_uses_libraries)) + $(call add_json_bool, EnforceUsesLibraries, $(filter true,$(LOCAL_ENFORCE_USES_LIBRARIES))) + $(call add_json_str, ProvidesUsesLibrary, $(firstword $(LOCAL_PROVIDES_USES_LIBRARY) $(LOCAL_MODULE))) + $(call add_json_map, ClassLoaderContexts) + $(call add_json_class_loader_context, any, $(my_dexpreopt_libs)) + $(call add_json_class_loader_context, 28, $(my_dexpreopt_libs_compat_28)) + $(call add_json_class_loader_context, 29, $(my_dexpreopt_libs_compat_29)) + $(call add_json_class_loader_context, 30, $(my_dexpreopt_libs_compat_30)) $(call end_json_map) $(call add_json_list, Archs, $(my_dexpreopt_archs)) $(call add_json_list, DexPreoptImages, $(my_dexpreopt_images)) - $(call add_json_list, DexPreoptImageLocations, $(my_dexpreopt_image_locations)) + $(call add_json_list, DexPreoptImageLocationsOnHost, $(my_dexpreopt_image_locations_on_host)) + $(call add_json_list, DexPreoptImageLocationsOnDevice,$(my_dexpreopt_image_locations_on_device)) $(call add_json_list, PreoptBootClassPathDexFiles, $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)) $(call add_json_list, PreoptBootClassPathDexLocations,$(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS)) $(call add_json_bool, PreoptExtractedApk, $(my_preopt_for_extracted_apk)) @@ -248,14 +401,20 @@ ifdef LOCAL_DEX_PREOPT $(call json_end) my_dexpreopt_config := $(intermediates)/dexpreopt.config + my_dexpreopt_config_for_postprocessing := $(PRODUCT_OUT)/dexpreopt_config/$(LOCAL_MODULE)_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 + $(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) @@ -272,13 +431,18 @@ ifdef LOCAL_DEX_PREOPT -dexpreopt_script $@ \ -out_dir $(OUT_DIR) + $(eval $(call copy-one-file,$(my_dexpreopt_config),$(my_dexpreopt_config_for_postprocessing))) + my_dexpreopt_deps := $(my_dex_jar) my_dexpreopt_deps += $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE)) my_dexpreopt_deps += \ - $(foreach lib, $(my_dexpreopt_libs), \ + $(foreach lib, $(my_dexpreopt_libs) $(my_dexpreopt_libs_compat), \ $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) my_dexpreopt_deps += $(my_dexpreopt_images_deps) my_dexpreopt_deps += $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES) + ifeq ($(LOCAL_ENFORCE_USES_LIBRARIES),true) + my_dexpreopt_deps += $(intermediates.COMMON)/enforce_uses_libraries.status + endif $(my_dexpreopt_zip): PRIVATE_MODULE := $(LOCAL_MODULE) $(my_dexpreopt_zip): $(my_dexpreopt_deps) @@ -304,10 +468,12 @@ ifdef LOCAL_DEX_PREOPT $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD) $(LOCAL_INSTALLED_MODULE): $(my_dexpreopt_zip) + $(LOCAL_INSTALLED_MODULE): $(my_dexpreopt_config_for_postprocessing) $(my_all_targets): $(my_dexpreopt_zip) my_dexpreopt_config := my_dexpreopt_script := my_dexpreopt_zip := + my_dexpreopt_config_for_postprocessing := endif # LOCAL_DEX_PREOPT |