diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-11 07:33:59 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-11 07:33:59 +0000 |
commit | a3e61930c3b8a88bf31f12f0e0e6de2204ce8df6 (patch) | |
tree | cf7c0616a16d879b6c0e8518ee5a78046e7cb03f | |
parent | feff1fb6596150491e46168e94f98d9a98df2bd1 (diff) | |
parent | fe60f6c8922a9563bb238ab38ca50d8eb8e38b7d (diff) | |
download | android_development-a3e61930c3b8a88bf31f12f0e0e6de2204ce8df6.tar.gz android_development-a3e61930c3b8a88bf31f12f0e0e6de2204ce8df6.tar.bz2 android_development-a3e61930c3b8a88bf31f12f0e0e6de2204ce8df6.zip |
release-request-f326290a-f111-4b0c-bfd0-2a38565f6bf2-for-git_oc-dr1-release-4090242 snap-temp-L86400000073092233
Change-Id: I3055bf573768f31d5b9638c7d7abe308d96420dd
-rw-r--r-- | vndk/tools/definition-tool/README.md | 58 | ||||
-rw-r--r-- | vndk/tools/definition-tool/templates/extra_vndk_sp_indirect.txt | 39 | ||||
-rw-r--r-- | vndk/tools/definition-tool/templates/vndk.txt | 69 | ||||
-rw-r--r-- | vndk/tools/definition-tool/templates/vndk_ext.txt | 37 | ||||
-rwxr-xr-x | vndk/tools/definition-tool/tests/test_elf_linker.py | 1 | ||||
-rwxr-xr-x | vndk/tools/definition-tool/tests/test_ndk_libs.py | 18 | ||||
-rwxr-xr-x | vndk/tools/definition-tool/vndk_definition_tool.py | 383 |
7 files changed, 394 insertions, 211 deletions
diff --git a/vndk/tools/definition-tool/README.md b/vndk/tools/definition-tool/README.md index acf582464..c9afd8eab 100644 --- a/vndk/tools/definition-tool/README.md +++ b/vndk/tools/definition-tool/README.md @@ -23,42 +23,48 @@ The high-level overview of the command line usage is: This command will print several lines such as: - extra_vndk_sp_indirect: libexample1.so - extra_vndk_sp_indirect: libexample2.so - vndk_ext: libexample3.so - vndk_ext: libexample4.so + vndk-sp: libexample1.so + vndk-sp-ext: libexample2.so + extra-vendor-libs: libexample3.so -This output implies: +The output implies: -1. `libexample1.so` and `libexample2.so` should be copied into - `/vendor/lib[64]/vndk-sp`. +1. `libexample1.so` should be copied to `/system/lib[64]/vndk-sp`. +2. `libexample2.so` should be copied to `/vendor/lib[64]/vndk-sp`. +3. `libexample3.so` should be copied to `/vendor/lib[64]`. -2. `libexample3.so` and `libexample4.so` should be copied into - `/vendor/lib[64]`. - -# Boilerplates +# Makefile Boilerplates There are some boilerplates in `templates` directory that can automate the -process to copy shared libraries. +process to copy shared libraries. Please copy a boilerplate, rename it as +`Android.mk`, and replace the placeholders with corresponding values: + +* `##_VNDK_SP_##` should be replaced by library names tagged with `vndk_sp`. + +* `##_VNDK_SP_EXT_##` should be replaced by library names tagged with + `vndk_sp_ext`. + +* `##_EXTRA_VENDOR_LIBS_##` should be replaced by library names tagged with + `extra_vendor_libs`. + +* `$(YOUR_DEVICE_NAME)` has to be replaced by your own device product name. -If the output tagged some shared libraries with `extra_vndk_sp_indirect`, then -copy `templates/extra_vndk_sp_indirect.txt` to an Android.mk and substitute -`##_EXTRA_VNDK_SP_INDIRECT_##` with library names (without `.so`). +VNDK definition tool can fill in the library names and generate an `Android.mk` +when the `--output-format=make` is specified: -If the output tagged some shared libraries with `vndk_ext`, then copy -`templates/vndk_ext.txt` to an Android.mk and substitute `##_VNDK_EXT_##` with -library names (without `.so`). + $ python3 ./vndk_definition_tool.py vndk \ + --system "/path/to/your/product_out/system" \ + --vendor "/path/to/your/product_out/vendor" \ + --aosp-system "/path/to/aosp/generic/system" \ + --tag-file "eligible-list-v3.0.csv" \ + --output-format=make These boilerplates only define the modules to copy shared libraries. -Developers have to add those modules to the `PRODUCT_PACKAGES` variable in -their `device.mk`. For example, in the example mentioned above, following -`PRODUCT_PACKAGES` changes are necessary for that target: - - PRODUCT_PACKAGES += libexample1.vndk-sp-ext - PRODUCT_PACKAGES += libexample2.vndk-sp-ext - PRODUCT_PACKAGES += libexample3.vndk-ext - PRODUCT_PACKAGES += libexample4.vndk-ext +Developers have to add the phony package name to `PRODUCT_PACKAGES` variable in +the `device.mk` for their devices. + + PRODUCT_PACKAGES += $(YOUR_DEVICE_NAME)-vndk ## Ignore Subdirectories diff --git a/vndk/tools/definition-tool/templates/extra_vndk_sp_indirect.txt b/vndk/tools/definition-tool/templates/extra_vndk_sp_indirect.txt deleted file mode 100644 index 58e9b5110..000000000 --- a/vndk/tools/definition-tool/templates/extra_vndk_sp_indirect.txt +++ /dev/null @@ -1,39 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -EXTRA_VNDK_SP_INDIRECT_LIBRARIES := ##_EXTRA_VNDK_SP_INDIRECT_## - -define define-vndk-sp-indirect-ext-lib -include $$(CLEAR_VARS) -LOCAL_MODULE := $1.vndk-sp-ext -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_PREBUILT_MODULE_FILE := $$(call intermediates-dir-for,SHARED_LIBRARIES,$1,,,,)/PACKED/$1.so -LOCAL_MULTILIB := first -LOCAL_MODULE_TAGS := optional -LOCAL_INSTALLED_MODULE_STEM := $1.so -LOCAL_MODULE_SUFFIX := .so -LOCAL_MODULE_RELATIVE_PATH := vndk-sp -LOCAL_VENDOR_MODULE := true -include $$(BUILD_PREBUILT) - -ifneq ($$(TARGET_2ND_ARCH),) -ifneq ($$(TARGET_TRANSLATE_2ND_ARCH),true) -include $$(CLEAR_VARS) -LOCAL_MODULE := $1.vndk-sp-ext -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_PREBUILT_MODULE_FILE := $$(call intermediates-dir-for,SHARED_LIBRARIES,$1,,,$$(TARGET_2ND_ARCH_VAR_PREFIX),)/PACKED/$1.so -LOCAL_MULTILIB := 32 -LOCAL_MODULE_TAGS := optional -LOCAL_INSTALLED_MODULE_STEM := $1.so -LOCAL_MODULE_SUFFIX := .so -LOCAL_MODULE_RELATIVE_PATH := vndk-sp -LOCAL_VENDOR_MODULE := true -include $$(BUILD_PREBUILT) -endif # TARGET_TRANSLATE_2ND_ARCH is not true -endif # TARGET_2ND_ARCH is not empty -endef - -$(foreach lib,$(VNDK_SP_LIBRARIES),\ - $(eval $(call define-vndk-sp-indirect-ext-lib,$(lib)))) - -# Add following module names to PRODUCT_PACKAGES: -# PRODUCT_PACKAGES += $(addsuffix .vndk-sp-ext,$(EXTRA_VNDK_SP_INDIRECT_LIBRARIES)) diff --git a/vndk/tools/definition-tool/templates/vndk.txt b/vndk/tools/definition-tool/templates/vndk.txt new file mode 100644 index 000000000..889b6ea07 --- /dev/null +++ b/vndk/tools/definition-tool/templates/vndk.txt @@ -0,0 +1,69 @@ +ifneq ($(filter $(YOUR_DEVICE_NAME),$(TARGET_DEVICE)),) + + +VNDK_SP_LIBRARIES := ##_VNDK_SP_## + +VNDK_SP_EXT_LIBRARIES := ##_VNDK_SP_EXT_## + +EXTRA_VENDOR_LIBRARIES := ##_EXTRA_VENDOR_LIBS_## + + +#------------------------------------------------------------------------------- +# VNDK Modules +#------------------------------------------------------------------------------- +LOCAL_PATH := $(call my-dir) + +define define-vndk-lib +include $$(CLEAR_VARS) +LOCAL_MODULE := $1.$2 +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_PREBUILT_MODULE_FILE := $$(TARGET_OUT_INTERMEDIATE_LIBRARIES)/$1.so +LOCAL_STRIP_MODULE := false +LOCAL_MULTILIB := first +LOCAL_MODULE_TAGS := optional +LOCAL_INSTALLED_MODULE_STEM := $1.so +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_RELATIVE_PATH := $3 +LOCAL_VENDOR_MODULE := $4 +include $$(BUILD_PREBUILT) + +ifneq ($$(TARGET_2ND_ARCH),) +ifneq ($$(TARGET_TRANSLATE_2ND_ARCH),true) +include $$(CLEAR_VARS) +LOCAL_MODULE := $1.$2 +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_PREBUILT_MODULE_FILE := $$($$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/$1.so +LOCAL_STRIP_MODULE := false +LOCAL_MULTILIB := 32 +LOCAL_MODULE_TAGS := optional +LOCAL_INSTALLED_MODULE_STEM := $1.so +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_RELATIVE_PATH := $3 +LOCAL_VENDOR_MODULE := $4 +include $$(BUILD_PREBUILT) +endif # TARGET_TRANSLATE_2ND_ARCH is not true +endif # TARGET_2ND_ARCH is not empty +endef + +$(foreach lib,$(VNDK_SP_LIBRARIES),\ + $(eval $(call define-vndk-lib,$(lib),vndk-sp-gen,vndk-sp,))) +$(foreach lib,$(VNDK_SP_EXT_LIBRARIES),\ + $(eval $(call define-vndk-lib,$(lib),vndk-sp-ext-gen,vndk-sp,true))) +$(foreach lib,$(EXTRA_VENDOR_LIBRARIES),\ + $(eval $(call define-vndk-lib,$(lib),vndk-ext-gen,,true))) + + +#------------------------------------------------------------------------------- +# Phony Package +#------------------------------------------------------------------------------- + +include $(CLEAR_VARS) +LOCAL_MODULE := $(YOUR_DEVICE_NAME)-vndk +LOCAL_MODULE_TAGS := optional +LOCAL_REQUIRED_MODULES := \ + $(addsuffix .vndk-sp-gen,$(VNDK_SP_LIBRARIES)) \ + $(addsuffix .vndk-sp-ext-gen,$(VNDK_SP_EXT_LIBRARIES)) \ + $(addsuffix .vndk-ext-gen,$(VNDK_EXT_LIBRARIES)) +include $(BUILD_PHONY_PACKAGE) + +endif # ifneq ($(filter $(YOUR_DEVICE_NAME),$(TARGET_DEVICE)),) diff --git a/vndk/tools/definition-tool/templates/vndk_ext.txt b/vndk/tools/definition-tool/templates/vndk_ext.txt deleted file mode 100644 index 307128056..000000000 --- a/vndk/tools/definition-tool/templates/vndk_ext.txt +++ /dev/null @@ -1,37 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -VNDK_EXT_LIBRARIES := ##_VNDK_EXT_## - -define define-vndk-ext-lib -include $$(CLEAR_VARS) -LOCAL_MODULE := $1.vndk-ext -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_PREBUILT_MODULE_FILE := $$(call intermediates-dir-for,SHARED_LIBRARIES,$1,,,,)/PACKED/$1.so -LOCAL_MULTILIB := first -LOCAL_MODULE_TAGS := optional -LOCAL_INSTALLED_MODULE_STEM := $1.so -LOCAL_MODULE_SUFFIX := .so -LOCAL_VENDOR_MODULE := true -include $$(BUILD_PREBUILT) - -ifneq ($$(TARGET_2ND_ARCH),) -ifneq ($$(TARGET_TRANSLATE_2ND_ARCH),true) -include $$(CLEAR_VARS) -LOCAL_MODULE := $1.vndk-ext -LOCAL_MODULE_CLASS := SHARED_LIBRARIES -LOCAL_PREBUILT_MODULE_FILE := $$(call intermediates-dir-for,SHARED_LIBRARIES,$1,,,$$(TARGET_2ND_ARCH_VAR_PREFIX),)/PACKED/$1.so -LOCAL_MULTILIB := 32 -LOCAL_MODULE_TAGS := optional -LOCAL_INSTALLED_MODULE_STEM := $1.so -LOCAL_MODULE_SUFFIX := .so -LOCAL_VENDOR_MODULE := true -include $$(BUILD_PREBUILT) -endif # TARGET_TRANSLATE_2ND_ARCH is not true -endif # TARGET_2ND_ARCH is not empty -endef - -$(foreach lib,$(VNDK_SP_LIBRARIES),\ - $(eval $(call define-vndk-ext-lib,$(lib)))) - -# Add following module names to PRODUCT_PACKAGES: -# PRODUCT_PACKAGES += $(addsuffix .vndk-ext,$(VNDK_EXT_LIBRARIES)) diff --git a/vndk/tools/definition-tool/tests/test_elf_linker.py b/vndk/tools/definition-tool/tests/test_elf_linker.py index 68109f26f..d3eecdd1e 100755 --- a/vndk/tools/definition-tool/tests/test_elf_linker.py +++ b/vndk/tools/definition-tool/tests/test_elf_linker.py @@ -273,7 +273,6 @@ class ELFLinkerTest(unittest.TestCase): 'libhidltransport', 'libhwbinder', 'libutils', - 'libz', ) # Add VNDK-SP libraries. diff --git a/vndk/tools/definition-tool/tests/test_ndk_libs.py b/vndk/tools/definition-tool/tests/test_ndk_libs.py index 976badccb..00a4c180c 100755 --- a/vndk/tools/definition-tool/tests/test_ndk_libs.py +++ b/vndk/tools/definition-tool/tests/test_ndk_libs.py @@ -19,6 +19,8 @@ class NDKLibDictTest(unittest.TestCase): self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libm.so')) self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libstdc++.so')) self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libvndksupport.so')) + self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libandroid_net.so')) + self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libz.so')) self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libc.so')) self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libdl.so')) @@ -26,13 +28,11 @@ class NDKLibDictTest(unittest.TestCase): self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libm.so')) self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libstdc++.so')) self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libvndksupport.so')) + self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libandroid_net.so')) + self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libz.so')) self.assertFalse(NDK_LIBS.is_ll_ndk('/system/lib/libm')) - # libz.so is not LL-NDK anymore. - self.assertFalse(NDK_LIBS.is_ll_ndk('/system/lib/libz.so')) - self.assertFalse(NDK_LIBS.is_ll_ndk('/system/lib64/libz.so')) - def test_is_sp_ndk(self): self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib/libEGL.so')) self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib/libGLESv1_CM.so')) @@ -104,12 +104,18 @@ class NDKLibDictTest(unittest.TestCase): self.assertTrue(NDK_LIBS.is_ndk('/system/lib/liblog.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib/libm.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib/libstdc++.so')) + self.assertTrue(NDK_LIBS.is_ndk('/system/lib/libvndksupport.so')) + self.assertTrue(NDK_LIBS.is_ndk('/system/lib/libandroid_net.so')) + self.assertTrue(NDK_LIBS.is_ndk('/system/lib/libz.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libc.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libdl.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/liblog.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libm.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libstdc++.so')) + self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libvndksupport.so')) + self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libandroid_net.so')) + self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libz.so')) # SP-NDK self.assertTrue(NDK_LIBS.is_ndk('/system/lib/libEGL.so')) @@ -139,10 +145,6 @@ class NDKLibDictTest(unittest.TestCase): self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libmediandk.so')) self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libvulkan.so')) - # libz.so is not NDK anymore. - self.assertFalse(NDK_LIBS.is_ndk('/system/lib/libz.so')) - self.assertFalse(NDK_LIBS.is_ndk('/system/lib64/libz.so')) - def test_classify(self): self.assertEqual(NDK_LIBS.NOT_NDK, NDK_LIBS.classify('/system/lib/libfoo.so')) diff --git a/vndk/tools/definition-tool/vndk_definition_tool.py b/vndk/tools/definition-tool/vndk_definition_tool.py index aeefd2cbc..3830025f3 100755 --- a/vndk/tools/definition-tool/vndk_definition_tool.py +++ b/vndk/tools/definition-tool/vndk_definition_tool.py @@ -542,6 +542,8 @@ class NDKLibDict(object): 'libm.so', 'libstdc++.so', 'libvndksupport.so', + 'libandroid_net.so', + 'libz.so', ) SP_NDK_LIB_NAMES = ( @@ -841,10 +843,16 @@ _VNDK_RESULT_FIELD_NAMES = ( 'vndk_sp_indirect_unused', 'vndk_sp_indirect_private', 'vndk', 'vndk_indirect', 'fwk_only', 'fwk_only_rs', 'sp_hal', 'sp_hal_dep', 'vnd_only', 'vndk_ext', 'vndk_sp_ext', 'vndk_sp_indirect_ext', - 'extra_vndk_sp_indirect') + 'extra_vendor_libs') VNDKResult = defaultnamedtuple('VNDKResult', _VNDK_RESULT_FIELD_NAMES, set()) +_SIMPLE_VNDK_RESULT_FIELD_NAMES = ( + 'vndk_sp', 'vndk_sp_ext', 'extra_vendor_libs') + +SimpleVNDKResult = defaultnamedtuple( + 'SimpleVNDKResult', _SIMPLE_VNDK_RESULT_FIELD_NAMES, set()) + class ELFLibDict(defaultnamedtuple('ELFLibDict', ('lib32', 'lib64'), {})): def get_lib_dict(self, elf_class): @@ -1098,8 +1106,8 @@ class ELFLinker(object): def compute_predefined_fwk_only_rs(self): """Find all fwk-only-rs libraries.""" path_patterns = ( - '^/system/lib(?:64)?/libft2\\.so$', - '^/system/lib(?:64)?/libmediandk\\.so', + '^/system/lib(?:64)?/(?:vndk-sp/)?libft2\\.so$', + '^/system/lib(?:64)?/(?:vndk-sp/)?libmediandk\\.so', ) return self.compute_path_matched_lib(path_patterns) @@ -1124,7 +1132,6 @@ class ELFLinker(object): '^.*/libhidltransport\\.so$', '^.*/libhwbinder\\.so$', '^.*/libutils\\.so$', - '^.*/libz\\.so$', # Only for o-release '^.*/android\\.hidl\\.base@1\\.0\\.so$', @@ -1261,27 +1268,28 @@ class ELFLinker(object): new_path = lib.path.replace('/system/', '/vendor/') self.rename_lib(lib, PT_VENDOR, new_path) - def compute_degenerated_vndk(self, sp_lib, generic_refs, - tagged_paths=None, - action_ineligible_vndk_sp='follow,warn', - action_ineligible_vndk='follow,warn'): + @staticmethod + def _parse_action_on_ineligible_lib(arg): + follow = False + warn = False + for flag in arg.split(','): + if flag == 'follow': + follow = True + elif flag == 'warn': + warn = True + elif flag == 'ignore': + continue + else: + raise ValueError('unknown action \"{}\"'.format(flag)) + return (follow, warn) + + def compute_degenerated_vndk(self, generic_refs, tagged_paths=None, + action_ineligible_vndk_sp='warn', + action_ineligible_vndk='warn'): # Find LL-NDK and SP-NDK libs. ll_ndk = set(lib for lib in self.all_libs() if lib.is_ll_ndk) - - def is_not_ll_ndk_indirect(lib): - return lib.is_ll_ndk - - ll_ndk_indirect = self.compute_closure(ll_ndk, is_not_ll_ndk_indirect) - ll_ndk_indirect -= ll_ndk - sp_ndk = set(lib for lib in self.all_libs() if lib.is_sp_ndk) - def is_not_sp_ndk_indirect(lib): - return lib.is_ll_ndk or lib.is_sp_ndk or lib in ll_ndk_indirect - - sp_ndk_indirect = self.compute_closure(sp_ndk, is_not_sp_ndk_indirect) - sp_ndk_indirect -= sp_ndk - # Find SP-HAL libs. sp_hal = self.compute_predefined_sp_hal() @@ -1291,14 +1299,18 @@ class ELFLinker(object): self.normalize_partition_tags(sp_hal, generic_refs) # Find SP-HAL-Dep libs. - def is_not_sp_hal_dep(lib): - if lib.is_ll_ndk or lib.is_sp_ndk or lib in sp_hal: - return True + def is_aosp_lib(lib): if not generic_refs: - # Use simple heuristic when generic reference is not available. + # If generic reference is not available, then assume all system + # libs are AOSP libs. return lib.partition == PT_SYSTEM return generic_refs.has_same_name_lib(lib) + def is_not_sp_hal_dep(lib): + if lib.is_ll_ndk or lib.is_sp_ndk or lib in sp_hal: + return True + return is_aosp_lib(lib) + sp_hal_dep = self.compute_closure(sp_hal, is_not_sp_hal_dep) sp_hal_dep -= sp_hal @@ -1310,7 +1322,8 @@ class ELFLinker(object): return lib.is_ll_ndk or lib.is_sp_ndk or lib in sp_hal or \ lib in sp_hal_dep - action_ineligible_vndk_sp = set(action_ineligible_vndk_sp.split(',')) + follow_ineligible_vndk_sp, warn_ineligible_vndk_sp = \ + self._parse_action_on_ineligible_lib(action_ineligible_vndk_sp) predefined_vndk_sp = self.compute_predefined_vndk_sp() vndk_sp = set() for lib in itertools.chain(sp_hal, sp_hal_dep): @@ -1320,18 +1333,13 @@ class ELFLinker(object): if dep in predefined_vndk_sp: vndk_sp.add(dep) continue - if 'warn' in action_ineligible_vndk_sp: + if warn_ineligible_vndk_sp: print('error: SP-HAL {} depends on non vndk-sp ' 'library {}.'.format(lib.path, dep.path), file=sys.stderr) - if 'follow' in action_ineligible_vndk_sp: + if follow_ineligible_vndk_sp: vndk_sp.add(dep) - # Add other predefined VNDK-SP even if they are not actually used by - # SP-HAL libs. - vndk_sp_unused = set(lib for lib in predefined_vndk_sp - if self._is_in_vndk_sp_dir(lib.path)) - vndk_sp - # Find VNDK-SP-Indirect libs. def is_not_vndk_sp_indirect(lib): return lib.is_ll_ndk or lib.is_sp_ndk or lib in vndk_sp or \ @@ -1341,6 +1349,13 @@ class ELFLinker(object): vndk_sp, is_not_vndk_sp_indirect) vndk_sp_indirect -= vndk_sp + # Find unused predefined VNDK-SP libs. + vndk_sp_unused = set(lib for lib in predefined_vndk_sp + if self._is_in_vndk_sp_dir(lib.path)) + vndk_sp_unused -= vndk_sp + vndk_sp_unused -= vndk_sp_indirect + + # Find dependencies of unused predefined VNDK-SP libs. def is_not_vndk_sp_indirect_unused(lib): return is_not_vndk_sp_indirect(lib) or lib in vndk_sp_indirect vndk_sp_indirect_unused = self.compute_closure( @@ -1350,57 +1365,139 @@ class ELFLinker(object): # TODO: Compute VNDK-SP-Indirect-Private. vndk_sp_indirect_private = set() - predefined_vndk_sp_indirect = self.compute_predefined_vndk_sp_indirect() + # Define helper functions for vndk_sp sets. + def is_vndk_sp_public(lib): + return lib in vndk_sp or lib in vndk_sp_unused or \ + lib in vndk_sp_indirect or \ + lib in vndk_sp_indirect_unused - # TODO: Compute VNDK-SP-Ext and VNDK-SP-Indirect-Ext. + def is_vndk_sp(lib): + return is_vndk_sp_public(lib) or lib in vndk_sp_indirect_private + + def is_vndk_sp_unused(lib): + return lib in vndk_sp_unused or lib in vndk_sp_indirect_unused + + def relabel_vndk_sp_as_used(lib): + assert is_vndk_sp_unused(lib) + + if lib in vndk_sp_unused: + vndk_sp_unused.remove(lib) + vndk_sp.add(lib) + else: + vndk_sp_indirect_unused.remove(lib) + vndk_sp_indirect.add(lib) + + closure = self.compute_closure({lib}, is_not_vndk_sp_indirect) + closure -= vndk_sp + vndk_sp_indirect_unused.difference_update(closure) + vndk_sp_indirect.update(closure) + + # Find VNDK-SP-Ext libs. vndk_sp_ext = set() + def collect_vndk_ext(libs): + result = set() + for lib in libs: + for dep in lib.imported_ext_symbols: + if dep in vndk_sp and dep not in vndk_sp_ext: + result.add(dep) + return result - def is_not_vndk_sp_indirect_ext(lib): - return lib.is_ll_ndk or lib.is_sp_ndk or lib in vndk_sp_ext or \ - lib in predefined_vndk_sp or \ - lib in predefined_vndk_sp_indirect + candidates = collect_vndk_ext(self.lib_pt[PT_VENDOR].values()) + while candidates: + vndk_sp_ext |= candidates + candidates = collect_vndk_ext(candidates) - vndk_sp_indirect_ext = self.compute_closure( - vndk_sp_ext, is_not_vndk_sp_indirect_ext) - vndk_sp_indirect_ext -= vndk_sp_ext + # Find VNDK-SP-Indirect-Ext libs. + predefined_vndk_sp_indirect = self.compute_predefined_vndk_sp_indirect() + vndk_sp_indirect_ext = set() + def collect_vndk_sp_indirect_ext(libs): + result = set() + for lib in libs: + exts = set(lib.imported_ext_symbols.keys()) + for dep in lib.deps: + if not is_vndk_sp_public(dep): + continue + if dep in vndk_sp_ext or dep in vndk_sp_indirect_ext: + continue + # If lib is using extended definition from deps, then we + # have to make a copy of dep. + if dep in exts: + result.add(dep) + continue + # If lib is using non-predefined VNDK-SP-Indirect, then we + # have to make a copy of dep. + if dep not in predefined_vndk_sp and \ + dep not in predefined_vndk_sp_indirect: + result.add(dep) + continue + return result - extra_vndk_sp_indirect = vndk_sp - predefined_vndk_sp - \ - predefined_vndk_sp_indirect + def is_not_vndk_sp_indirect(lib): + return lib.is_ll_ndk or lib.is_sp_ndk or lib in vndk_sp or \ + lib in fwk_only_rs + + candidates = collect_vndk_sp_indirect_ext(vndk_sp_ext) + while candidates: + vndk_sp_indirect_ext |= candidates + candidates = collect_vndk_sp_indirect_ext(candidates) # Find VNDK libs (a.k.a. system shared libs directly used by vendor # partition.) def is_not_vndk(lib): - if lib.is_ll_ndk or lib.is_sp_ndk or lib in vndk_sp: - return True - if lib.partition != PT_SYSTEM: + if lib.is_ll_ndk or lib.is_sp_ndk or is_vndk_sp_public(lib) or \ + lib in fwk_only_rs: return True - if not generic_refs: - # If generic reference is not available, we assume all system - # libs are eligible vndk. - return False - return not generic_refs.has_same_name_lib(lib) + return lib.partition != PT_SYSTEM - action_ineligible_vndk = set(action_ineligible_vndk.split(',')) + def is_eligible_lib_access(lib, dep): + return not tagged_paths or \ + tagged_paths.is_path_visible(lib.path, dep.path) + + follow_ineligible_vndk, warn_ineligible_vndk = \ + self._parse_action_on_ineligible_lib(action_ineligible_vndk) vndk = set() - for lib in self.lib_pt[PT_VENDOR].values(): - for dep in lib.deps: - if is_not_vndk(dep): - continue - if not tagged_paths or \ - tagged_paths.is_path_visible(lib.path, dep.path): - vndk.add(dep) - continue - if 'warn' in action_ineligible_vndk: - print('warning: vendor lib/exe {} depends on ineligible ' - 'framework shared lib {}.' - .format(lib.path, dep.path), file=sys.stderr) - if 'follow' in action_ineligible_vndk: - vndk.add(dep) + extra_vendor_libs = set() + def collect_vndk(vendor_libs): + next_vendor_libs = set() + for lib in vendor_libs: + for dep in lib.deps: + if is_vndk_sp_unused(dep): + relabel_vndk_sp_as_used(dep) + continue + if is_not_vndk(dep): + continue + if not is_aosp_lib(dep): + # The dependency should be copied into vendor partition + # as an extra vendor lib. + if dep not in extra_vendor_libs: + next_vendor_libs.add(dep) + extra_vendor_libs.add(dep) + continue + if is_eligible_lib_access(lib, dep): + vndk.add(dep) + continue + if warn_ineligible_vndk: + print('warning: vendor lib/exe {} depends on ' + 'ineligible framework shared lib {}.' + .format(lib.path, dep.path), file=sys.stderr) + if follow_ineligible_vndk: + vndk.add(dep) + return next_vendor_libs + + candidates = collect_vndk(self.lib_pt[PT_VENDOR].values()) + while candidates: + candidates = collect_vndk(candidates) vndk_indirect = self.compute_closure(vndk, is_not_vndk) - vndk_indirect -= vndk_indirect + vndk_indirect -= vndk + + def is_vndk(lib): + return lib in vndk or lib in vndk_indirect + + # Find VNDK-EXT libs (VNDK libs with extended definitions and the + # extended definitions are used by the vendor modules (including + # extra_vendor_libs). - # Compute the extended usages from vendor partition. # FIXME: DAUX libraries won't be found by the following algorithm. vndk_ext = set() @@ -1413,11 +1510,27 @@ class ELFLinker(object): return result candidates = collect_vndk_ext(self.lib_pt[PT_VENDOR].values()) + candidates |= collect_vndk_ext(extra_vendor_libs) while candidates: vndk_ext |= candidates candidates = collect_vndk_ext(candidates) + # Compute LL-NDK-Indirect and SP-NDK-Indirect. + def is_not_ll_ndk_indirect(lib): + return lib.is_ll_ndk or is_vndk_sp(lib) or is_vndk(lib) + + ll_ndk_indirect = self.compute_closure(ll_ndk, is_not_ll_ndk_indirect) + ll_ndk_indirect -= ll_ndk + + def is_not_sp_ndk_indirect(lib): + return lib.is_ll_ndk or lib.is_sp_ndk or lib in ll_ndk_indirect or \ + is_vndk_sp(lib) or is_vndk(lib) + + sp_ndk_indirect = self.compute_closure(sp_ndk, is_not_sp_ndk_indirect) + sp_ndk_indirect -= sp_ndk + + # Return the VNDK classifications. return VNDKResult( ll_ndk=ll_ndk, ll_ndk_indirect=ll_ndk_indirect, @@ -1436,9 +1549,9 @@ class ELFLinker(object): sp_hal_dep=sp_hal_dep, # vnd_only=vnd_only, vndk_ext=vndk_ext, - # vndk_sp_ext=vndk_sp_ext, - # vndk_sp_indirect_ext=vndk_sp_indirect_ext, - extra_vndk_sp_indirect=extra_vndk_sp_indirect) + vndk_sp_ext=vndk_sp_ext, + vndk_sp_indirect_ext=vndk_sp_indirect_ext, + extra_vendor_libs=extra_vendor_libs) def compute_vndk_cap(self, banned_libs): # ELF files on vendor partitions are banned unconditionally. ELF files @@ -1748,6 +1861,18 @@ class VNDKCommandBase(ELFGraphCommand): parser.add_argument('--no-default-dlopen-deps', action='store_true', help='do not add default dlopen dependencies') + parser.add_argument('--tag-file', help='lib tag file') + + parser.add_argument( + '--action-ineligible-vndk-sp', default='warn', + help='action when a sp-hal uses non-vndk-sp libs ' + '(option: follow,warn,ignore)') + + parser.add_argument( + '--action-ineligible-vndk', default='warn', + help='action when a vendor lib/exe uses fwk-only libs ' + '(option: follow,warn,ignore)') + def create_from_args(self, args): """Create all essential data structures for VNDK computation.""" @@ -1760,7 +1885,12 @@ class VNDKCommandBase(ELFGraphCommand): 'minimum_dlopen_deps.txt') graph.load_extra_deps(minimum_dlopen_deps) - return (generic_refs, graph) + if args.tag_file: + tagged_paths = TaggedPathDict.create_from_csv_path(args.tag_file) + else: + tagged_paths = None + + return (generic_refs, graph, tagged_paths) class VNDKCommand(VNDKCommandBase): @@ -1779,15 +1909,9 @@ class VNDKCommand(VNDKCommandBase): '--full', action='store_true', help='print all classification') - parser.add_argument('--tag-file', help='lib tag file') - - parser.add_argument( - '--action-ineligible-vndk-sp', default='warn,follow', - help='action when a sp-hal uses non-vndk-sp libs') - parser.add_argument( - '--action-ineligible-vndk', default='warn,follow', - help='action when a vendor lib/exe uses fwk-only libs') + '--output-format', default='tag', + help='output format for vndk classification') def _warn_incorrect_partition_lib_set(self, lib_set, partition, error_msg): for lib in lib_set.values(): @@ -1814,8 +1938,74 @@ class VNDKCommand(VNDKCommandBase): print('warning: {}: NDK library should not be extended.' .format(lib.path), file=sys.stderr) + @staticmethod + def _extract_simple_vndk_result(vndk_result): + field_name_tags = [ + ('vndk_sp', 'vndk_sp'), + ('vndk_sp_unused', 'vndk_sp'), + ('vndk_sp_indirect', 'vndk_sp'), + ('vndk_sp_indirect_unused', 'vndk_sp'), + ('vndk_sp_indirect_private', 'vndk_sp'), + + ('vndk_sp_ext', 'vndk_sp_ext'), + ('vndk_sp_indirect_ext', 'vndk_sp_ext'), + + ('vndk_ext', 'extra_vendor_libs'), + ('extra_vendor_libs', 'extra_vendor_libs'), + ] + results = SimpleVNDKResult() + for field_name, tag in field_name_tags: + getattr(results, tag).update(getattr(vndk_result, field_name)) + return results + + def _print_tags(self, vndk_lib, full, file=sys.stdout): + if full: + result_tags = _VNDK_RESULT_FIELD_NAMES + results = vndk_lib + else: + # Simplified VNDK output with only three sets. + result_tags = _SIMPLE_VNDK_RESULT_FIELD_NAMES + results = self._extract_simple_vndk_result(vndk_lib) + + for tag in result_tags: + libs = getattr(results, tag) + tag += ':' + for lib in sorted_lib_path_list(libs): + print(tag, lib, file=file) + + def _print_make(self, vndk_lib, file=sys.stdout): + def get_module_name(path): + name = os.path.basename(path) + root, ext = os.path.splitext(name) + return root + + def get_module_names(lib_set): + return sorted({ get_module_name(lib.path) for lib in lib_set }) + + results = self._extract_simple_vndk_result(vndk_lib) + vndk_sp = get_module_names(results.vndk_sp) + vndk_sp_ext = get_module_names(results.vndk_sp_ext) + extra_vendor_libs= get_module_names(results.extra_vendor_libs) + + def format_module_names(module_names): + return '\\\n ' + ' \\\n '.join(module_names) + + script_dir = os.path.dirname(os.path.abspath(__file__)) + template_path = os.path.join(script_dir, 'templates', 'vndk.txt') + with open(template_path, 'r') as f: + template = f.read() + + template = template.replace('##_VNDK_SP_##', + format_module_names(vndk_sp)) + template = template.replace('##_VNDK_SP_EXT_##', + format_module_names(vndk_sp_ext)) + template = template.replace('##_EXTRA_VENDOR_LIBS_##', + format_module_names(extra_vendor_libs)) + + file.write(template) + def main(self, args): - generic_refs, graph = self.create_from_args(args) + generic_refs, graph, tagged_paths = self.create_from_args(args) # Check the API extensions to NDK libraries. if generic_refs: @@ -1824,25 +2014,17 @@ class VNDKCommand(VNDKCommandBase): if args.warn_incorrect_partition: self._warn_incorrect_partition(graph) - if args.tag_file: - tagged_paths = TaggedPathDict.create_from_csv_path(args.tag_file) - else: - tagged_paths = None - # Compute vndk heuristics. - sp_lib = graph.compute_sp_lib(generic_refs) vndk_lib = graph.compute_degenerated_vndk( - sp_lib, generic_refs, tagged_paths, - args.action_ineligible_vndk_sp, args.action_ineligible_vndk) + generic_refs, tagged_paths, args.action_ineligible_vndk_sp, + args.action_ineligible_vndk) # Print results. - field_names = ['extra_vndk_sp_indirect', 'vndk_ext'] - if args.full: - field_names = _VNDK_RESULT_FIELD_NAMES - for field_name in field_names: - tag = field_name + ':' - for lib in sorted_lib_path_list(getattr(vndk_lib, field_name)): - print(tag, lib) + if args.output_format == 'make': + self._print_make(vndk_lib) + else: + self._print_tags(vndk_lib, args.full) + return 0 @@ -1858,11 +2040,12 @@ class DepsInsightCommand(VNDKCommandBase): '--output', '-o', help='output directory') def main(self, args): - generic_refs, graph = self.create_from_args(args) + generic_refs, graph, tagged_paths = self.create_from_args(args) # Compute vndk heuristics. - sp_lib = graph.compute_sp_lib(generic_refs) - vndk_lib = graph.compute_degenerated_vndk(sp_lib, generic_refs) + vndk_lib = graph.compute_degenerated_vndk( + generic_refs, tagged_paths, args.action_ineligible_vndk_sp, + args.action_ineligible_vndk) # Serialize data. strs = [] |