Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bf58771 authored by Ulya Trafimovich's avatar Ulya Trafimovich
Browse files

Consolidate manifest_check for different module types.

Move manifest_check (a.k.a. verify_uses_libraries check) from makefiles
for specific module types to common makefile dex_preopt_odex_install.mk,
which is included by all Java modules that may require dexpreopt. If a
modules locally disables dexpreopt, it still goes through manifest_check
(unless dexpreopt is globally disabled or the module has no Java code).

This CL allows to have manifest_check and dexpreopt in the same makefile
(which is needed for a follow-up CL that will reuse dexpreopt variables
for manifest_check).

Bug: 132357300
Test: lunch cf_x86_64_phone-userdebug && m
Change-Id: Ia217cfc247ae43d8fc716bfc1fe9dcce1d00aa7f
parent 5dcd959a
Loading
Loading
Loading
Loading
+2 −49
Original line number Diff line number Diff line
@@ -92,55 +92,6 @@ my_preopt_for_extracted_apk := true
endif
endif

# Verify LOCAL_USES_LIBRARIES/LOCAL_OPTIONAL_USES_LIBRARIES
# If LOCAL_ENFORCE_USES_LIBRARIES is not set, default to true if either of LOCAL_USES_LIBRARIES or
# LOCAL_OPTIONAL_USES_LIBRARIES are specified.
# Will change the default to true unconditionally in the future.
ifndef LOCAL_ENFORCE_USES_LIBRARIES
  ifneq (,$(strip $(LOCAL_USES_LIBRARIES)$(LOCAL_OPTIONAL_USES_LIBRARIES)))
    LOCAL_ENFORCE_USES_LIBRARIES := true
  endif
endif

# Disable verify_uses_libraries check 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 ($(WITH_DEXPREOPT),true)
  LOCAL_ENFORCE_USES_LIBRARIES :=
endif

my_enforced_uses_libraries :=
ifdef LOCAL_ENFORCE_USES_LIBRARIES
  my_verify_script := build/soong/scripts/manifest_check.py
  my_uses_libs := $(patsubst %,--uses-library %,$(LOCAL_USES_LIBRARIES))
  my_optional_uses_libs := $(patsubst %,--optional-uses-library %, \
    $(LOCAL_OPTIONAL_USES_LIBRARIES))
  my_relax_check := $(if $(filter true,$(RELAX_USES_LIBRARY_CHECK)), \
    --enforce-uses-libraries-relax,)
  my_enforced_uses_libraries := $(intermediates.COMMON)/enforce_uses_libraries.status
  $(my_enforced_uses_libraries): PRIVATE_USES_LIBRARIES := $(my_uses_libs)
  $(my_enforced_uses_libraries): PRIVATE_OPTIONAL_USES_LIBRARIES := $(my_optional_uses_libs)
  $(my_enforced_uses_libraries): PRIVATE_RELAX_CHECK := $(my_relax_check)
  $(my_enforced_uses_libraries): $(AAPT)
  $(my_enforced_uses_libraries): $(my_verify_script)
  $(my_enforced_uses_libraries): $(my_prebuilt_src_file)
	@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_RELAX_CHECK) \
	  $<
  $(built_module) : $(my_enforced_uses_libraries)
endif

dex_preopt_profile_src_file := $(my_prebuilt_src_file)

rs_compatibility_jni_libs :=
include $(BUILD_SYSTEM)/install_jni_libs.mk

@@ -218,6 +169,8 @@ LOCAL_DEX_PREOPT := false
endif

my_dex_jar := $(my_prebuilt_src_file)
my_manifest_or_apk := $(my_prebuilt_src_file)
dex_preopt_profile_src_file := $(my_prebuilt_src_file)

#######################################
# defines built_odex along with rule to install odex
+140 −80
Original line number Diff line number Diff line
# 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,8 +31,9 @@ ifeq (false,$(LOCAL_DEX_PREOPT))
  LOCAL_DEX_PREOPT :=
endif

# Only enable preopt for non tests.
# Disable <uses-library> checks and preopt for tests.
ifneq (,$(filter $(LOCAL_MODULE_TAGS),tests))
  LOCAL_ENFORCE_USES_LIBRARIES := false
  LOCAL_DEX_PREOPT :=
endif

@@ -45,8 +47,14 @@ ifeq (true,$(DISABLE_PREOPT))
  LOCAL_DEX_PREOPT :=
endif

# Disable preopt if not WITH_DEXPREOPT
# Disable <uses-library> checks and preopt if not WITH_DEXPREOPT
#
# 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
  LOCAL_DEX_PREOPT :=
endif

@@ -54,7 +62,9 @@ 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 <uses-library> checks and preopt if the app contains no java code.
ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file)$(LOCAL_SOONG_DEX_JAR)))
  LOCAL_ENFORCE_USES_LIBRARIES := false
  LOCAL_DEX_PREOPT :=
endif

@@ -108,6 +118,132 @@ 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.base-V1.0-java \
    android.hidl.manager-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.
################################################################################

# Verify LOCAL_USES_LIBRARIES/LOCAL_OPTIONAL_USES_LIBRARIES
# If LOCAL_ENFORCE_USES_LIBRARIES is not set, default to true if either of LOCAL_USES_LIBRARIES or
# LOCAL_OPTIONAL_USES_LIBRARIES are specified.
# Will change the default to true unconditionally in the future.
ifndef LOCAL_ENFORCE_USES_LIBRARIES
  ifneq (,$(strip $(LOCAL_USES_LIBRARIES)$(LOCAL_OPTIONAL_USES_LIBRARIES)))
    LOCAL_ENFORCE_USES_LIBRARIES := true
  endif
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_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_RELAX_CHECK := $(my_relax_check_arg)
  $(my_enforced_uses_libraries): $(AAPT)
  $(my_enforced_uses_libraries): $(my_verify_script)
  $(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_RELAX_CHECK) \
	  $<
  $(built_module) : $(my_enforced_uses_libraries)
endif

################################################################################
# Dexpreopt command.
################################################################################

my_dexpreopt_archs :=
my_dexpreopt_images :=
my_dexpreopt_images_deps :=
@@ -186,72 +322,6 @@ ifdef LOCAL_DEX_PREOPT

  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))

  # 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.base-V1.0-java \
      android.hidl.manager-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)

  # 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)

  # Record dex-preopt config.
  DEXPREOPT.$(LOCAL_MODULE).DEX_PREOPT := $(LOCAL_DEX_PREOPT)
  DEXPREOPT.$(LOCAL_MODULE).MULTILIB := $(LOCAL_MULTILIB)
@@ -278,7 +348,7 @@ 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_str,  EnforceUsesLibrariesStatusFile, $(intermediates.COMMON)/enforce_uses_libraries.status)
  $(call add_json_str,  EnforceUsesLibrariesStatusFile, $(my_enforced_uses_libraries))
  $(call add_json_bool, EnforceUsesLibraries,           $(LOCAL_ENFORCE_USES_LIBRARIES))
  $(call add_json_str,  ProvidesUsesLibrary,            $(firstword $(LOCAL_PROVIDES_USES_LIBRARY) $(LOCAL_MODULE)))
  $(call add_json_map,  ClassLoaderContexts)
@@ -304,16 +374,6 @@ ifdef LOCAL_DEX_PREOPT
  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)
+2 −0
Original line number Diff line number Diff line
@@ -176,7 +176,9 @@ endif

#######################################
# defines built_odex along with rule to install odex
my_manifest_or_apk := $(full_android_manifest)
include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
my_manifest_or_apk :=
#######################################

# Make sure there's something to build.
+3 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ endif

ifeq ($(prebuilt_module_is_dex_javalib),true)
my_dex_jar := $(my_prebuilt_src_file)
my_manifest_or_apk := $(my_prebuilt_src_file)
# This is a target shared library, i.e. a jar with classes.dex.

$(foreach pair,$(PRODUCT_BOOT_JARS), \
@@ -43,7 +44,9 @@ ALL_MODULES.$(my_register_name).CLASSES_JAR := $(common_classes_jar)

#######################################
# defines built_odex along with rule to install odex
my_manifest_or_apk := $(my_prebuilt_src_file)
include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
my_manifest_or_apk :=
#######################################
$(built_module) : $(my_prebuilt_src_file)
	$(call copy-file-to-target)
+0 −25
Original line number Diff line number Diff line
@@ -472,31 +472,6 @@ $(LOCAL_BUILT_MODULE): PRIVATE_CERTIFICATE_LINEAGE := $(LOCAL_CERTIFICATE_LINEAG
# Set a actual_partition_tag (calculated in base_rules.mk) for the package.
PACKAGES.$(LOCAL_PACKAGE_NAME).PARTITION := $(actual_partition_tag)

# Verify LOCAL_USES_LIBRARIES/LOCAL_OPTIONAL_USES_LIBRARIES
# If LOCAL_ENFORCE_USES_LIBRARIES is not set, default to true if either of LOCAL_USES_LIBRARIES or
# LOCAL_OPTIONAL_USES_LIBRARIES are specified.
# Will change the default to true unconditionally in the future.
ifndef LOCAL_ENFORCE_USES_LIBRARIES
  ifneq (,$(strip $(LOCAL_USES_LIBRARIES)$(LOCAL_OPTIONAL_USES_LIBRARIES)))
    LOCAL_ENFORCE_USES_LIBRARIES := true
  endif
endif

my_enforced_uses_libraries :=
ifdef LOCAL_ENFORCE_USES_LIBRARIES
  my_manifest_check := $(intermediates.COMMON)/manifest/AndroidManifest.xml.check
  $(my_manifest_check): $(MANIFEST_CHECK)
  $(my_manifest_check): PRIVATE_USES_LIBRARIES := $(LOCAL_USES_LIBRARIES)
  $(my_manifest_check): PRIVATE_OPTIONAL_USES_LIBRARIES := $(LOCAL_OPTIONAL_USES_LIBRARIES)
  $(my_manifest_check): $(full_android_manifest)
	@echo Checking manifest: $<
	$(MANIFEST_CHECK) --enforce-uses-libraries \
	  $(addprefix --uses-library ,$(PRIVATE_USES_LIBRARIES)) \
	  $(addprefix --optional-uses-library ,$(PRIVATE_OPTIONAL_USES_LIBRARIES)) \
	  $< -o $@
  $(LOCAL_BUILT_MODULE): $(my_manifest_check)
endif

# Define the rule to build the actual package.
# PRIVATE_JNI_SHARED_LIBRARIES is a list of <abi>:<path_of_built_lib>.
$(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)