vndk-def: Add more output formats to vndk command

This commit adds the --output-format option to vndk command.  When
`make` is specified, VNDK definition tool will fill in the placeholders
in the boilerplates and print a make file to stdout.

Bug: 37867089
Test: ./vndk_definition_tool.py vndk --output-format=make ...
Change-Id: I0185e1690264d0cefafa8536db2e0cf34daaeee0
diff --git a/vndk/tools/definition-tool/README.md b/vndk/tools/definition-tool/README.md
index acf5824..c9afd8e 100644
--- a/vndk/tools/definition-tool/README.md
+++ b/vndk/tools/definition-tool/README.md
@@ -23,42 +23,48 @@
 
 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 58e9b51..0000000
--- 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 0000000..889b6ea
--- /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 3071280..0000000
--- 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 75a90b9..c06724c 100755
--- a/vndk/tools/definition-tool/vndk_definition_tool.py
+++ b/vndk/tools/definition-tool/vndk_definition_tool.py
@@ -1905,6 +1905,10 @@
                 help='action when a vendor lib/exe uses fwk-only libs '
                      '(option: follow,warn,ignore)')
 
+        parser.add_argument(
+                '--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():
             if not lib.num_users:
@@ -1950,6 +1954,52 @@
             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)
 
@@ -1972,19 +2022,10 @@
                 args.action_ineligible_vndk_sp, args.action_ineligible_vndk)
 
         # Print results.
-        if args.full:
-            result_tags = _VNDK_RESULT_FIELD_NAMES
-            results = vndk_lib
+        if args.output_format == 'make':
+            self._print_make(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)
+            self._print_tags(vndk_lib, args.full)
 
         return 0