From 842a985f90497d9790954003e60faa7f0f7785d4 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Fri, 20 Jan 2017 09:01:17 +0900 Subject: [PATCH] install *.so in different paths for their types Shared libraries are now installed to different directories depending on their types. * NDK libraries: /system/lib/ndk (with symlink from /system/lib) * VNDK libraries: /system/lib/vndk * VNDK-ext libraries: /system/lib/vndk-ext * Framework-only libraries: /system/lib * Vendor-only libraries: /vendor/lib * Same-process HALs: /vendor/lib/sameprocess However, if LOCAL_MODULE_PATH is explicitly set, then it is respected, with a warning message. Module owners are highly encouraged to investigate the warnings and use alternatives to LOCAL_MODULE_PATH; combination of LOCAL_[PROPRIETARY|OEM|ODM]_MODULE, LOCAL_MODULE_CLASS and LOCAL_RELATIVE_PATH will cover most of the cases. Furthermore, for each shared libraries whose path is changed, a symolic link from the original path to the new path is *temporarily* generated. e.g. /system/lib/libbase.so -> vndk/libbase.so. This is to prevent sudden breakage of the code expecting the lib from the old path. This symbolic links will eventually be removed before O launch (b/34917183). Finally, BOARD_SAME_PROCESS_HAL_DEPS is added. It contains the list of shared libraries implementing the same-process HALs and its internal sub libraries. This is designed to be defined in BoardConfig.mk Bug: 33681361 Test: build & run. Libraries must be in the correct directories. Symlinks from the old path to the new path must exist. Change-Id: I46130aac09ae65400fd4d0abbc2e12dddd154fb1 --- CleanSpec.mk | 5 ++ core/base_rules.mk | 169 ++++++++++++++++++++++++++++++++++++++++--- core/definitions.mk | 10 ++- core/soong_config.mk | 4 +- 4 files changed, 173 insertions(+), 15 deletions(-) diff --git a/CleanSpec.mk b/CleanSpec.mk index 9d3fc23c0f..e0c826cee2 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -400,6 +400,11 @@ $(call add-clean-step, rm -rf $(TARGET_OUT_TESTCASES)) $(call add-clean-step, rm -rf $(TARGET_OUT_ETC)/init) +# Libraries are moved from {system|vendor}/lib to ./lib/framework, ./lib/vndk, etc. +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/vendor/lib*) + # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/core/base_rules.mk b/core/base_rules.mk index e90c1bbd03..a3d5937f4f 100644 --- a/core/base_rules.mk +++ b/core/base_rules.mk @@ -78,6 +78,8 @@ ifdef LOCAL_2ND_ARCH_VAR_PREFIX endif endif +my_module_is_soong := $(if $(filter $(OUT_DIR)/soong/%,$(LOCAL_MODULE_MAKEFILE)),true,false) + # Ninja has an implicit dependency on the command being run, and kati will # regenerate the ninja manifest if any read makefile changes, so there is no # need to have dependencies on makefiles. @@ -163,6 +165,14 @@ my_module_path := $(strip $(LOCAL_MODULE_PATH)) endif my_module_path := $(patsubst %/,%,$(my_module_path)) my_module_relative_path := $(strip $(LOCAL_MODULE_RELATIVE_PATH)) + +# my_module_default_path is the path that is automatically chosen according to the attributes of +# a module. It is used when the module does not explicitly specify install path using LOCAL_MODULE_PATH. +# If LOCAL_MODULE_PATH is specified, it is always respected and my_module_default_path is +# ignored. However, for shared libraries, such conflict generates warning so that module owner +# can place the library in the correct location (, stop using LOCAL_MODULE_PATH, or migrate to Soong to +# be better). +my_module_default_path := ifdef LOCAL_IS_HOST_MODULE partition_tag := else @@ -180,20 +190,135 @@ else partition_tag := $(if $(call should-install-to-system,$(my_module_tags)),,_DATA) endif endif -ifeq ($(my_module_path),) - install_path_var := $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT$(partition_tag)_$(LOCAL_MODULE_CLASS) - ifeq (true,$(LOCAL_PRIVILEGED_MODULE)) - install_path_var := $(install_path_var)_PRIVILEGED - endif +install_path_var := $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT$(partition_tag)_$(LOCAL_MODULE_CLASS) +ifeq (true,$(LOCAL_PRIVILEGED_MODULE)) + install_path_var := $(install_path_var)_PRIVILEGED +endif - my_module_path := $($(install_path_var)) - ifeq ($(strip $(my_module_path)),) - $(error $(LOCAL_PATH): unhandled install path "$(install_path_var) for $(LOCAL_MODULE)") +my_module_default_path := $($(install_path_var)) +ifeq ($(strip $(my_module_path)$(my_module_default_path)),) + $(call pretty-error,internal error in base_rules.mk; $(install_path_var) is not defined.) +endif + +# Determine lib_type and do some sanity checks. +ifeq ($(LOCAL_IS_HOST_MODULE)$(LOCAL_MODULE_CLASS),SHARED_LIBRARIES) + ifneq ($(filter $(LOCAL_MODULE),$(addprefix lib,$(NDK_PREBUILT_SHARED_LIBRARIES))),) + ifneq ($(partition_tag),) + $(call pretty-error,"NDK library must be installed at system partition, where other libraries will look for it. It cannot be moved.") + endif + lib_type := ndk + else ifneq ($(filter $(LOCAL_MODULE),$(VNDK_LIBRARIES) $(VNDK_INDIRECT_LIBRARIES)),) + ifneq ($(partition_tag),) + $(call pretty-error,"VNDK library must be installed at system partition. DO NOT modify VNDK_LIBRARIES or VNDK_LIBRARIES. \ +If your library needs to be shared between system.img and vendor.img then define it as a VNDK-ext library. Use vndk_ext_library {...} \ +in Android.bp to do so.") + endif + lib_type := vndk + else ifneq ($(filter $(LOCAL_MODULE),$(BOARD_SAME_PROCESS_HAL_DEPS)),) + # List of libraries implementing same-process HALs (and their internal sub-libraries) is + # defined by vendors. + ifeq ($(partition_tag),) + $(call pretty-error,Sameprocess HAL must not be installed at system partition) + endif + lib_type := sameprocess_hal + else ifeq ($(LOCAL_IS_HOST_MODULE)$(partition_tag),) + lib_type := framework + else ifneq ($(partition_tag),_DATA) + # Here, vendor means vendor/oem/odm + lib_type := vendor_provided + else + # Test lib falls into this. No lib_type required for them. + ifneq ($(filter tests,$(LOCAL_MODULE_TAGS)),tests) + $(call pretty-error,Cannot determine the type of this library) + endif + lib_type := + endif +else + lib_type := +endif + +# This is the default path until N. From O, the default path is changed. +# Let's save the old default path in case we need a symlink to it later. +my_module_pre_o_default_path := $(my_module_default_path) + +# Special case for pre_o_default_path of Soong defined modules. +# For those modules, we guess their pre_o_default_path by removing /ndk, /vndk, etc. +# from their LOCAL_MODULE_PATH. This is because relative_install_path is already +# embedded to my_module_path. +ifeq ($(my_module_is_soong),true) +ifndef LOCAL_IS_HOST_MODULE +ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES) + my_module_pre_o_default_path := $(my_module_path) + my_module_pre_o_default_path := $(subst /vndk-ext,,$(my_module_pre_o_default_path)) + my_module_pre_o_default_path := $(subst /vndk,,$(my_module_pre_o_default_path)) + my_module_pre_o_default_path := $(subst /ndk,,$(my_module_pre_o_default_path)) + my_module_pre_o_default_path := $(subst /sameprocess,,$(my_module_pre_o_default_path)) +endif +endif +endif + +# Amend the default_path once again depending on lib_type. This is new from O. +ifeq ($(lib_type),vndk) + my_module_default_path := $(my_module_default_path)/vndk + # TODO(b/35020246): before P, we should support installing two snapshots of VNDK + # libraries. One for framework libs and execs and the other for vendor libs and execs. +else ifeq ($(lib_type),ndk) + my_module_default_path := $(my_module_default_path)/ndk +else ifeq ($(lib_type),sameprocess_hal) + my_module_default_path := $(my_module_default_path)/sameprocess +endif + +# Relative path is appended to path resolved so far +ifneq ($(my_module_relative_path),) + my_module_default_path := $(my_module_default_path)/$(my_module_relative_path) + my_module_pre_o_default_path := $(my_module_pre_o_default_path)/$(my_module_relative_path) + ifneq ($(my_module_path),) + my_module_path := $(my_module_path)/$(my_module_relative_path) endif endif -ifneq ($(my_module_relative_path),) - my_module_path := $(my_module_path)/$(my_module_relative_path) + +_lib_moved := +ifeq ($(my_module_path),) + # If LOCAL_MODULE_PATH is not specified, use the automatically determined path. + my_module_path := $(my_module_default_path) + + # Mark if the lib is installed to a different path than before. With this hint, + # a symlink is created if BOARD_SYMLINK_FOR_LIBS is true. + ifneq ($(my_module_path),$(my_module_pre_o_default_path)) + _lib_moved := true + endif +else + # If LOCAL_MODULE_PATH is specified, we respect it. + ifndef LOCAL_IS_HOST_MODULE + ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES) + ifeq ($(filter $(TARGET_OUT_DATA)%,$(my_module_path)),) + # However, we are kind enough to warn if it seems to be wrong. + # Warn only for Android.mk defined shared libraries that will be installed + # to system or vendor partition. For other types of files - especially + # Soong-defined libs -, we don't warn because Soong always gives us correct + # paths. + ifeq ($(my_module_is_soong),false) + ifneq ($(my_module_path),$(my_module_default_path)) + # TODO(b/35020635): s/warning/error/ + $(call pretty-warning,$(lib_type) library must be installed to \ +$(subst $(PRODUCT_OUT)/,,$(my_module_default_path)) but requested to be installed at \ +$(subst $(PRODUCT_OUT)/,,$(my_module_path)). Please fix.) + endif + else + # For Soong-defined module, symlink is provided if the path has been amended + # ...except for vndk-ext libraries because there already is a symlink for the + # vndk (unmodified) version of the vndk-ext library. + ifneq ($(my_module_path),$(my_module_pre_o_default_path)) + ifeq ($(filter vndk-ext,$(subst /,$(space),$(my_module_path))),) + _lib_moved := true + endif + endif + endif + endif + endif + endif endif + endif # not LOCAL_UNINSTALLABLE_MODULE ifneq ($(strip $(LOCAL_BUILT_MODULE)$(LOCAL_INSTALLED_MODULE)),) @@ -384,8 +509,30 @@ endif # !LOCAL_IS_HOST_MODULE # Rule to install the module's companion symlinks my_installed_symlinks := $(addprefix $(my_module_path)/,$(LOCAL_MODULE_SYMLINKS) $(LOCAL_MODULE_SYMLINKS_$(my_32_64_bit_suffix))) + +# If this lib is installed to the different directory than before, +# make a symlink from the old path to the new path. +# This symlink is required because there are so many plances that expect the old +# path (e.g. systemproperty rild.libpath). Until that places are all fixed, +# we keep this symlink. +# TODO(b/34917183): remove symlinks after everything migrations to the new paths; +# this should be done before O launch unless it will be a security hole that +# we can't restrict access to a certain set of libraries by using the directory +# path. +ifneq ($(BOARD_SYMLINK_FOR_LIBS),false) +ifeq ($(_lib_moved),true) + my_installed_symlinks += $(my_module_pre_o_default_path)/$(my_installed_module_stem) +endif +else +# Symlinks for ndk libs are permanent. +ifeq ($(lib_type)$(_lib_moved),ndktrue) + my_installed_symlinks += $(my_module_pre_o_default_path)/$(my_installed_module_stem) +endif +endif + +# Make a symlink $(symlink) -> $(LOCAL_INSTALLED_MODULE) $(foreach symlink,$(my_installed_symlinks),\ - $(call symlink-file,$(LOCAL_INSTALLED_MODULE),$(my_installed_module_stem),$(symlink))) + $(call symlink-file,$(LOCAL_INSTALLED_MODULE),$(LOCAL_INSTALLED_MODULE),$(symlink),true)) $(my_all_targets) : | $(my_installed_symlinks) diff --git a/core/definitions.mk b/core/definitions.mk index 556b41f75c..1145e97a84 100644 --- a/core/definitions.mk +++ b/core/definitions.mk @@ -2870,8 +2870,10 @@ endef # Define a rule to create a symlink to a file. # $(1): full path to source -# $(2): source (may be relative) -# $(3): full path to destination +# $(2): target of the link +# $(3): full path of the symlink +# $(4): (optional) when set to true, $(2) is recognized as a path from the build root and +# thus -r option is used to link $(3) to $(2). Off by default. define symlink-file $(eval $(_symlink-file)) endef @@ -2883,7 +2885,9 @@ $(3): | $(1) @echo "Symlink: $$@ -> $(2)" @mkdir -p $(dir $$@) @rm -rf $$@ - $(hide) ln -sf $(2) $$@ + $(if $(filter true,$(4)),\ + $(hide) python -c "import os.path; import os; os.symlink(os.path.relpath('$(2)','$(dir $(3))'), '$$@')",\ + $(hide) ln -sf $(2) $$@) endef ########################################################### diff --git a/core/soong_config.mk b/core/soong_config.mk index 576c8abe04..ff8a51d4f4 100644 --- a/core/soong_config.mk +++ b/core/soong_config.mk @@ -69,7 +69,9 @@ $(SOONG_VARIABLES): FORCE echo ''; \ echo ' "ArtUseReadBarrier": $(if $(filter false,$(PRODUCT_ART_USE_READ_BARRIER)),false,true),'; \ echo ''; \ - echo ' "BtConfigIncludeDir": "$(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR)"'; \ + echo ' "BtConfigIncludeDir": "$(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR)",'; \ + echo ''; \ + echo ' "SameProcessHalDeps": [$(if $(BOARD_SAME_PROCESS_HAL_DEPS),"$(subst $(space),"$(comma)",$(BOARD_SAME_PROCESS_HAL_DEPS))")]'; \ echo '}') > $(SOONG_VARIABLES_TMP); \ if ! cmp -s $(SOONG_VARIABLES_TMP) $(SOONG_VARIABLES); then \ mv $(SOONG_VARIABLES_TMP) $(SOONG_VARIABLES); \