vndk-def: Fix test_elfdump.py

Before this commit, test_elfdump.py was broken because prebuilt libs
were removed from the "prebuilts" directory.  This commit searches the
NDK toolchain specified by "NDK" environment variable.

Bug: 64503245
Test: ./tests/test_elfdump.py

Change-Id: Iee3076350c5d9a549deb4c08ac64453ef9dcd981
Merged-In: I368d5ce2fa208dd00608fe0793995144ca0c9856
(cherry picked from commit 3f9d07e2ce2fd869dbb8a5579d2fa4511563347d)
diff --git a/vndk/tools/definition-tool/tests/ndk_toolchain.py b/vndk/tools/definition-tool/tests/ndk_toolchain.py
new file mode 100755
index 0000000..8ad9144
--- /dev/null
+++ b/vndk/tools/definition-tool/tests/ndk_toolchain.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import argparse
+import collections
+import os
+import re
+import subprocess
+import sys
+
+def detect_ndk_dir():
+    ndk_dir = os.getenv('NDK')
+    if not ndk_dir:
+        error_msg = '''error: NDK toolchain is required for this test case.
+error:
+error: Steps:
+error:   1. Download NDK from https://developer.android.com/ndk/downloads/
+error:   2. Unzip the archive (android-ndk-r15c-linux-x86_64.zip)
+error:   3. Set environment variable NDK to the extracted directory
+error:      (export NDK=android-ndk-r15c)
+error:'''
+        print(error_msg, file=sys.stderr)
+        raise ValueError('NDK toolchain not specified')
+
+    if not os.path.exists(ndk_dir):
+        raise ValueError('NDK toolchain not found')
+
+    return ndk_dir
+
+def detect_api_level(ndk_dir):
+    try:
+        apis = []
+        pattern = re.compile('android-(\\d+)')
+        for name in os.listdir(os.path.join(ndk_dir, 'platforms')):
+            match = pattern.match(name)
+            if match:
+                apis.append(int(match.group(1)))
+        if not apis:
+            raise ValueError('failed to find latest api')
+        return 'android-{}'.format(max(apis))
+    except IOError:
+        raise ValueError('failed to find latest api')
+
+def detect_host():
+    if sys.platform.startswith('linux'):
+        return 'linux-x86_64'
+    if sys.platform.startswith('darwin'):
+        return 'darwin-x86_64'
+    raise NotImplementedError('unknown host platform')
+
+def get_gcc_dir(ndk_dir, arch, host):
+    return os.path.join(ndk_dir, 'toolchains', arch, 'prebuilt', host)
+
+def get_clang_dir(ndk_dir, host):
+    return os.path.join(ndk_dir, 'toolchains', 'llvm', 'prebuilt', host)
+
+def get_platform_dir(ndk_dir, api, subdirs):
+    return os.path.join(ndk_dir, 'platforms', api, *subdirs)
+
+class Target(object):
+    def __init__(self, name, triple, cflags, ldflags, gcc_toolchain_dir,
+                 clang_dir, ndk_include, ndk_lib):
+        self.name = name
+        self.target_triple = triple
+        self.target_cflags = cflags
+        self.target_ldflags = ldflags
+
+        self.gcc_toolchain_dir = gcc_toolchain_dir
+        self.clang_dir = clang_dir
+        self.ndk_include = ndk_include
+        self.ndk_lib = ndk_lib
+
+    def check_paths(self):
+        def check_path(path):
+            if os.path.exists(path):
+                return True
+            print('error: File not found:', path, file=sys.stderr)
+            return False
+
+        ld_exeutable = os.path.join(
+                self.gcc_toolchain_dir, 'bin', self.target_triple + '-ld')
+
+        success = check_path(self.gcc_toolchain_dir)
+        success &= check_path(ld_exeutable)
+        success &= check_path(self.clang_dir)
+        success &= check_path(self.ndk_include)
+        success &= check_path(self.ndk_lib)
+        return success
+
+    def compile(self, obj_file, src_file, cflags):
+        clang = os.path.join(self.clang_dir, 'bin', 'clang')
+
+        cmd = [clang, '-o', obj_file, '-c', src_file]
+        cmd.extend(['-fPIE', '-fPIC'])
+        cmd.extend(['-gcc-toolchain', self.gcc_toolchain_dir])
+        cmd.extend(['-target', self.target_triple])
+        cmd.extend(['-isystem', self.ndk_include])
+        cmd.extend(cflags)
+        cmd.extend(self.target_cflags)
+        subprocess.check_call(cmd)
+
+    def link(self, out_file, obj_files, ldflags):
+        if '-shared' in ldflags:
+            crtbegin = os.path.join(self.ndk_lib, 'crtbegin_so.o')
+            crtend = os.path.join(self.ndk_lib, 'crtend_so.o')
+        else:
+            crtbegin = os.path.join(self.ndk_lib, 'crtbegin_static.o')
+            crtend = os.path.join(self.ndk_lib, 'crtend_android.o')
+
+        clang = os.path.join(self.clang_dir, 'bin', 'clang')
+
+        cmd = [clang, '-o', out_file]
+        cmd.extend(['-fPIE', '-fPIC', '-Wl,--no-undefined', '-nostdlib'])
+        cmd.append('-L' + self.ndk_lib)
+        cmd.extend(['-gcc-toolchain', self.gcc_toolchain_dir])
+        cmd.extend(['-target', self.target_triple])
+        cmd.append(crtbegin)
+        cmd.extend(obj_files)
+        cmd.append(crtend)
+        cmd.extend(ldflags)
+        cmd.extend(self.target_ldflags)
+        if '-shared' not in ldflags:
+            cmd.append('-Wl,-pie')
+        subprocess.check_call(cmd)
+
+def create_targets(ndk_dir=None, api=None, host=None):
+    if ndk_dir is None:
+        ndk_dir = detect_ndk_dir()
+    if api is None:
+        api = detect_api_level(ndk_dir)
+    if host is None:
+        host = detect_host()
+
+    targets = collections.OrderedDict()
+
+    targets['arm'] = Target(
+            'arm', 'arm-linux-androideabi', [],[],
+            get_gcc_dir(ndk_dir, 'arm-linux-androideabi-4.9', host),
+            get_clang_dir(ndk_dir, host),
+            get_platform_dir(ndk_dir, api, ['arch-arm', 'usr', 'include']),
+            get_platform_dir(ndk_dir, api, ['arch-arm', 'usr', 'lib']))
+
+    targets['arm64'] = Target(
+            'arm64', 'aarch64-linux-android', [], [],
+            get_gcc_dir(ndk_dir, 'aarch64-linux-android-4.9', host),
+            get_clang_dir(ndk_dir, host),
+            get_platform_dir(ndk_dir, api, ['arch-arm64', 'usr', 'include']),
+            get_platform_dir(ndk_dir, api, ['arch-arm64', 'usr', 'lib']))
+
+    targets['x86'] = Target(
+            'x86', 'i686-linux-android', ['-m32'], ['-m32'],
+            get_gcc_dir(ndk_dir, 'x86-4.9', host),
+            get_clang_dir(ndk_dir, host),
+            get_platform_dir(ndk_dir, api, ['arch-x86', 'usr', 'include']),
+            get_platform_dir(ndk_dir, api, ['arch-x86', 'usr', 'lib']))
+
+    targets['x86_64'] = Target(
+            'x86_64', 'x86_64-linux-android', ['-m64'], ['-m64'],
+            get_gcc_dir(ndk_dir, 'x86_64-4.9', host),
+            get_clang_dir(ndk_dir, host),
+            get_platform_dir(ndk_dir, api, ['arch-x86_64', 'usr', 'include']),
+            get_platform_dir(ndk_dir, api, ['arch-x86_64', 'usr', 'lib64']))
+
+    targets['mips'] = Target(
+            'mips', 'mipsel-linux-android', [], [],
+            get_gcc_dir(ndk_dir, 'mipsel-linux-android-4.9', host),
+            get_clang_dir(ndk_dir, host),
+            get_platform_dir(ndk_dir, api, ['arch-mips', 'usr', 'include']),
+            get_platform_dir(ndk_dir, api, ['arch-mips', 'usr', 'lib']))
+
+    targets['mips64'] = Target(
+            'mips64', 'mips64el-linux-android',
+            ['-march=mips64el', '-mcpu=mips64r6'],
+            ['-march=mips64el', '-mcpu=mips64r6'],
+            get_gcc_dir(ndk_dir, 'mips64el-linux-android-4.9', host),
+            get_clang_dir(ndk_dir, host),
+            get_platform_dir(ndk_dir, api, ['arch-mips64', 'usr', 'include']),
+            get_platform_dir(ndk_dir, api, ['arch-mips64', 'usr', 'lib64']))
+
+    return targets
+
+def main():
+    parser = argparse.ArgumentParser(
+            description='Dry-run NDK toolchain detection')
+    parser.add_argument('--ndk-dir')
+    parser.add_argument('--api-level')
+    parser.add_argument('--host')
+    args = parser.parse_args()
+
+    targets = create_targets(args.ndk_dir, args.api_level, args.host)
+
+    success = True
+    for name, target in targets.items():
+        success &= target.check_paths()
+    if not success:
+        sys.exit(1)
+
+    print('succeed')
+
+if __name__ == '__main__':
+    main()
diff --git a/vndk/tools/definition-tool/tests/targets.py b/vndk/tools/definition-tool/tests/targets.py
deleted file mode 100644
index 2b2d2ac..0000000
--- a/vndk/tools/definition-tool/tests/targets.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import subprocess
-import sys
-
-SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
-ANDROID_BUILD_TOP = os.path.abspath(os.path.join(SCRIPT_DIR, *(['..'] * 5)))
-
-NDK_VERSION = 'r11'
-API_LEVEL = 'android-24'
-
-def get_prebuilts_host():
-    if sys.platform.startswith('linux'):
-        return 'linux-x86'
-    if sys.platform.startswith('darwin'):
-        return 'darwin-x86'
-    raise NotImplementedError('unknown platform')
-
-def get_prebuilts_gcc(arch, gcc_version):
-    return os.path.join(ANDROID_BUILD_TOP, 'prebuilts', 'gcc',
-                        get_prebuilts_host(), arch, gcc_version)
-
-def get_prebuilts_clang():
-    return os.path.join(ANDROID_BUILD_TOP, 'prebuilts', 'clang', 'host',
-                        get_prebuilts_host(), 'clang-stable')
-
-def get_prebuilts_ndk(subdirs):
-    return os.path.join(ANDROID_BUILD_TOP, 'prebuilts', 'ndk', NDK_VERSION,
-                        'platforms', API_LEVEL, *subdirs)
-
-
-class Target(object):
-    def __init__(self, name, triple, cflags, ldflags, gcc_toolchain_dir,
-                 clang_dir, ndk_include, ndk_lib):
-        self.name = name
-        self.target_triple = triple
-        self.target_cflags = cflags
-        self.target_ldflags = ldflags
-
-        self.gcc_toolchain_dir = gcc_toolchain_dir
-        self.clang_dir = clang_dir
-        self.ndk_include = ndk_include
-        self.ndk_lib = ndk_lib
-
-    def compile(self, obj_file, src_file, cflags):
-        clang = os.path.join(self.clang_dir, 'bin', 'clang')
-
-        cmd = [clang, '-o', obj_file, '-c', src_file]
-        cmd.extend(['-fPIE', '-fPIC'])
-        cmd.extend(['-gcc-toolchain', self.gcc_toolchain_dir])
-        cmd.extend(['-target', self.target_triple])
-        cmd.extend(['-isystem', self.ndk_include])
-        cmd.extend(cflags)
-        cmd.extend(self.target_cflags)
-        subprocess.check_call(cmd)
-
-    def link(self, out_file, obj_files, ldflags):
-        if '-shared' in ldflags:
-            crtbegin = os.path.join(self.ndk_lib, 'crtbegin_so.o')
-            crtend = os.path.join(self.ndk_lib, 'crtend_so.o')
-        else:
-            crtbegin = os.path.join(self.ndk_lib, 'crtbegin_static.o')
-            crtend = os.path.join(self.ndk_lib, 'crtend_android.o')
-
-        clang = os.path.join(self.clang_dir, 'bin', 'clang')
-
-        cmd = [clang, '-o', out_file]
-        cmd.extend(['-fPIE', '-fPIC', '-Wl,--no-undefined', '-nostdlib'])
-        cmd.append('-L' + self.ndk_lib)
-        cmd.extend(['-gcc-toolchain', self.gcc_toolchain_dir])
-        cmd.extend(['-target', self.target_triple])
-        cmd.append(crtbegin)
-        cmd.extend(obj_files)
-        cmd.append(crtend)
-        cmd.extend(ldflags)
-        cmd.extend(self.target_ldflags)
-        if '-shared' not in ldflags:
-            cmd.append('-Wl,-pie')
-        subprocess.check_call(cmd)
-
-def create_targets():
-    return {
-        'arm': Target('arm', 'arm-linux-androideabi', [],[],
-            get_prebuilts_gcc('arm', 'arm-linux-androideabi-4.9'),
-            get_prebuilts_clang(),
-            get_prebuilts_ndk(['arch-arm', 'usr', 'include']),
-            get_prebuilts_ndk(['arch-arm', 'usr', 'lib'])),
-
-        'arm64': Target('arm64', 'aarch64-linux-android', [], [],
-            get_prebuilts_gcc('aarch64', 'aarch64-linux-android-4.9'),
-            get_prebuilts_clang(),
-            get_prebuilts_ndk(['arch-arm64', 'usr', 'include']),
-            get_prebuilts_ndk(['arch-arm64', 'usr', 'lib'])),
-
-        'x86': Target('x86', 'x86_64-linux-android', ['-m32'], ['-m32'],
-            get_prebuilts_gcc('x86', 'x86_64-linux-android-4.9'),
-            get_prebuilts_clang(),
-            get_prebuilts_ndk(['arch-x86', 'usr', 'include']),
-            get_prebuilts_ndk(['arch-x86', 'usr', 'lib'])),
-
-        'x86_64': Target('x86_64', 'x86_64-linux-android', ['-m64'], ['-m64'],
-            get_prebuilts_gcc('x86', 'x86_64-linux-android-4.9'),
-            get_prebuilts_clang(),
-            get_prebuilts_ndk(['arch-x86_64', 'usr', 'include']),
-            get_prebuilts_ndk(['arch-x86_64', 'usr', 'lib64'])),
-
-        'mips': Target('mips', 'mipsel-linux-android', [], [],
-            get_prebuilts_gcc('mips', 'mips64el-linux-android-4.9'),
-            get_prebuilts_clang(),
-            get_prebuilts_ndk(['arch-mips', 'usr', 'include']),
-            get_prebuilts_ndk(['arch-mips', 'usr', 'lib'])),
-
-        'mips64': Target('mips64', 'mips64el-linux-android',
-            ['-march=mips64el', '-mcpu=mips64r6'],
-            ['-march=mips64el', '-mcpu=mips64r6'],
-            get_prebuilts_gcc('mips', 'mips64el-linux-android-4.9'),
-            get_prebuilts_clang(),
-            get_prebuilts_ndk(['arch-mips64', 'usr', 'include']),
-            get_prebuilts_ndk(['arch-mips64', 'usr', 'lib64'])),
-    }
diff --git a/vndk/tools/definition-tool/tests/test_elfdump.py b/vndk/tools/definition-tool/tests/test_elfdump.py
index 75fe396..b8e3c1e 100755
--- a/vndk/tools/definition-tool/tests/test_elfdump.py
+++ b/vndk/tools/definition-tool/tests/test_elfdump.py
@@ -11,7 +11,7 @@
 import unittest
 
 from compat import TemporaryDirectory, makedirs
-import targets
+import ndk_toolchain
 
 
 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -30,7 +30,7 @@
 class ELFDumpTest(unittest.TestCase):
     @classmethod
     def setUpClass(cls):
-        cls.targets = targets.create_targets()
+        cls.targets = ndk_toolchain.create_targets()
 
         if test_dir_base:
             cls.test_dir_base = test_dir_base