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