Home | History | Annotate | Download | only in build
      1 #!/usr/bin/env python3.4
      2 #
      3 # Copyright (C) 2017 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the 'License');
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an 'AS IS' BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 
     18 import os
     19 
     20 from vts_spec_parser import VtsSpecParser
     21 import build_rule_gen_utils as utils
     22 
     23 
     24 class BuildRuleGen(object):
     25     """Build rule generator for test/vts-testcase/hal."""
     26     _ANDROID_BUILD_TOP = os.environ.get('ANDROID_BUILD_TOP')
     27     if not _ANDROID_BUILD_TOP:
     28         print 'Run "lunch" command first.'
     29         sys.exit(1)
     30     _PROJECT_PATH = os.path.join(_ANDROID_BUILD_TOP, 'test', 'vts-testcase',
     31                                  'hal')
     32     _VTS_BUILD_TEMPLATE = os.path.join(_PROJECT_PATH, 'script', 'build',
     33                                        'template', 'vts_build_template.bp')
     34 
     35     def __init__(self, warning_header):
     36         """BuildRuleGen constructor.
     37 
     38         Args:
     39             warning_header: string, warning header for every generated file.
     40         """
     41         self._warning_header = warning_header
     42         self._vts_spec_parser = VtsSpecParser()
     43 
     44     def UpdateBuildRule(self):
     45         """Updates build rules under test/vts-testcase/hal."""
     46         utils.RemoveFilesInDirIf(
     47             self._PROJECT_PATH,
     48             lambda x: self._IsAutoGenerated(x))
     49         hal_list = self._vts_spec_parser.HalNamesAndVersions()
     50         self.UpdateTopLevelBuildRule()
     51         self.UpdateSecondLevelBuildRule(hal_list)
     52         self.UpdateHalDirBuildRule(hal_list)
     53 
     54     def UpdateTopLevelBuildRule(self):
     55         """Updates test/vts-testcase/hal/Android.bp"""
     56         utils.WriteBuildRule(
     57             os.path.join(self._PROJECT_PATH, 'Android.bp'),
     58             utils.OnlySubdirsBpRule(self._warning_header, ['*']))
     59 
     60     def UpdateSecondLevelBuildRule(self, hal_list):
     61         """Updates test/vts-testcase/hal/<hal_name>/Android.bp"""
     62         top_level_dirs = dict()
     63         for target in hal_list:
     64             hal_dir = os.path.join(
     65                 utils.HalNameDir(target[0]), utils.HalVerDir(target[1]))
     66             top_dir = hal_dir.split('/', 1)[0]
     67             top_level_dirs.setdefault(
     68                 top_dir, []).append(os.path.relpath(hal_dir, top_dir))
     69 
     70         for k, v in top_level_dirs.items():
     71             file_path = os.path.join(self._PROJECT_PATH, k, 'Android.bp')
     72             utils.WriteBuildRule(
     73                 file_path,
     74                 utils.OnlySubdirsBpRule(self._warning_header, v))
     75 
     76     def UpdateHalDirBuildRule(self, hal_list):
     77         """Updates build rules for vts drivers/profilers.
     78 
     79         Updates vts drivers/profilers for each pair of (hal_name, hal_version)
     80         in hal_list.
     81 
     82         Args:
     83             hal_list: list of tuple of strings. For example,
     84                 [('vibrator', '1.3'), ('sensors', '1.7')]
     85         """
     86         for target in hal_list:
     87             hal_name = target[0]
     88             hal_version = target[1]
     89 
     90             hal_dir = os.path.join(self._PROJECT_PATH,
     91                                    utils.HalNameDir(hal_name),
     92                                    utils.HalVerDir(hal_version))
     93 
     94             file_path = os.path.join(hal_dir, 'Android.bp')
     95             utils.WriteBuildRule(
     96                 file_path,
     97                 utils.OnlySubdirsBpRule(self._warning_header, ['*']))
     98 
     99             file_path = os.path.join(hal_dir, 'build', 'Android.bp')
    100             utils.WriteBuildRule(file_path, self._VtsBuildRuleFromTemplate(
    101                 self._VTS_BUILD_TEMPLATE, hal_name, hal_version))
    102 
    103     def _VtsBuildRuleFromTemplate(self, template_path, hal_name, hal_version):
    104         """Returns build rules in string form by filling out a template.
    105 
    106         Reads template from given path and fills it out.
    107 
    108         Args:
    109           template_path: string, path to build rule template file.
    110           hal_name: string, name of the hal, e.g. 'vibrator'.
    111           hal_version: string, version of the hal, e.g '7.4'
    112 
    113         Returns:
    114           string, complete build rules in string form
    115         """
    116         with open(template_path) as template_file:
    117             build_template = str(template_file.read())
    118         return self._FillOutBuildRuleTemplate(hal_name, hal_version,
    119                                               build_template)
    120 
    121     def _FillOutBuildRuleTemplate(self, hal_name, hal_version, template):
    122         """Returns build rules in string form by filling out given template.
    123 
    124         Args:
    125           hal_name: string, name of the hal, e.g. 'vibrator'.
    126           hal_version: string, version of the hal, e.g '7.4'
    127           template: string, build rule template to fill out.
    128 
    129         Returns:
    130           string, complete build rule in string form.
    131         """
    132 
    133         def GeneratedOutput(hal_name, hal_version, extension):
    134             """Formats list of vts spec names into a string.
    135 
    136             Formats list of vts spec name for given hal_name, hal_version
    137             into a string that can be inserted into build template.
    138 
    139             Args:
    140               hal_name: string, name of the hal, e.g. 'vibrator'.
    141               hal_version: string, version of the hal, e.g '7.4'
    142               extension: string, extension of files e.g. '.cpp'.
    143 
    144             Returns:
    145               string, to be inserted into build template.
    146             """
    147             result = []
    148             vts_spec_names = self._vts_spec_parser.VtsSpecNames(hal_name,
    149                                                                 hal_version)
    150             for vts_spec in vts_spec_names:
    151                 result.append('"android/hardware/%s/%s/%s%s",' %
    152                               (utils.HalNameDir(hal_name), hal_version,
    153                                vts_spec, extension))
    154             return '\n        '.join(result)
    155 
    156         def ImportedPackages(vts_pkg_type, imported_packages):
    157             """Formats list of imported packages into a string.
    158 
    159             Formats list of imported packages for given hal_name, hal_version
    160             into a string that can be inserted into build template.
    161 
    162             Args:
    163               vts_pkg_type: string 'driver' or 'profiler'
    164               imported_packages: list of imported packages
    165 
    166             Returns:
    167               string, to be inserted into build template.
    168             """
    169             result = []
    170             for package in imported_packages:
    171                 prefix = 'android.hardware.'
    172                 if package.startswith(prefix):
    173                     # TODO(b/36475863)
    174                     result.append('"%s",' % package)
    175                     vts_pkg_name = package + '-vts.' + vts_pkg_type
    176                     result.append('"%s",' % vts_pkg_name)
    177                 else:
    178                     result.append('"%s",' % package)
    179             return '\n        '.join(result)
    180 
    181         build_rule = self._warning_header + template
    182         build_rule = build_rule.replace('{HAL_NAME}', hal_name)
    183         build_rule = build_rule.replace('{HAL_NAME_DIR}',
    184                                         utils.HalNameDir(hal_name))
    185         build_rule = build_rule.replace('{HAL_VERSION}', hal_version)
    186         build_rule = build_rule.replace(
    187             '{GENERATED_VTS_SPECS}',
    188             GeneratedOutput(hal_name, hal_version, ''))
    189         build_rule = build_rule.replace(
    190             '{GENERATED_SOURCES}',
    191             GeneratedOutput(hal_name, hal_version, '.cpp'))
    192         build_rule = build_rule.replace(
    193             '{GENERATED_HEADERS}', GeneratedOutput(hal_name, hal_version, '.h'))
    194 
    195         imported_packages = self._vts_spec_parser.ImportedPackagesList(
    196             hal_name, hal_version)
    197         build_rule = build_rule.replace(
    198             '{IMPORTED_DRIVER_PACKAGES}',
    199             ImportedPackages('driver', imported_packages))
    200         build_rule = build_rule.replace(
    201             '{IMPORTED_PROFILER_PACKAGES}',
    202             ImportedPackages('profiler', imported_packages))
    203 
    204         return build_rule
    205 
    206     def _IsAutoGenerated(self, abs_file_path):
    207         """Checks if file was auto-generated.
    208 
    209         Args:
    210             abs_file_path: string, absolute file path.
    211 
    212         Returns:
    213             True iff file was auto-generated by BuildRuleGen.
    214         """
    215         [dir_name, file_name] = os.path.split(abs_file_path)
    216         if file_name != 'Android.bp':
    217             return False
    218         with open(abs_file_path) as myfile:
    219             return self._warning_header in myfile.read()
    220