• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
18import os
19
20from vts_spec_parser import VtsSpecParser
21import build_rule_gen_utils as utils
22
23
24class 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