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`. - -2. `libexample3.so` and `libexample4.so` should be copied into - `/vendor/lib[64]`. +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]`. -# 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: -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_SP_##` should be replaced by library names tagged with `vndk_sp`. -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`). +* `##_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. + +VNDK definition tool can fill in the library names and generate an `Android.mk` +when the `--output-format=make` is specified: + + $ 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: +Developers have to add the phony package name to `PRODUCT_PACKAGES` variable in +the `device.mk` for their devices. - PRODUCT_PACKAGES += libexample1.vndk-sp-ext - PRODUCT_PACKAGES += libexample2.vndk-sp-ext - PRODUCT_PACKAGES += libexample3.vndk-ext - PRODUCT_PACKAGES += libexample4.vndk-ext + 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/vndk_definition_tool.py b/vndk/tools/definition-tool/vndk_definition_tool.py index 02984f7a6..3830025f3 100755 --- a/vndk/tools/definition-tool/vndk_definition_tool.py +++ b/vndk/tools/definition-tool/vndk_definition_tool.py @@ -843,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): @@ -1277,8 +1283,7 @@ class ELFLinker(object): raise ValueError('unknown action \"{}\"'.format(flag)) return (follow, warn) - def compute_degenerated_vndk(self, sp_lib, generic_refs, - tagged_paths=None, + 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. @@ -1543,10 +1548,10 @@ class ELFLinker(object): sp_hal=sp_hal, sp_hal_dep=sp_hal_dep, # vnd_only=vnd_only, - vndk_ext=vndk_ext | extra_vendor_libs, - # vndk_sp_ext=vndk_sp_ext, - # vndk_sp_indirect_ext=vndk_sp_indirect_ext, - extra_vndk_sp_indirect=vndk_sp_ext | vndk_sp_indirect_ext) + vndk_ext=vndk_ext, + 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 @@ -1856,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.""" @@ -1868,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): @@ -1887,17 +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', - 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)') + '--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(): @@ -1924,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: @@ -1934,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 @@ -1968,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 = []