#!/usr/bin/env python3.4 # # Copyright (C) 2017 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the 'License'); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an 'AS IS' BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import os from vts_spec_parser import VtsSpecParser import build_rule_gen_utils as utils class BuildRuleGen(object): """Build rule generator for test/vts-testcase/hal.""" _ANDROID_BUILD_TOP = os.environ.get('ANDROID_BUILD_TOP') if not _ANDROID_BUILD_TOP: print 'Run "lunch" command first.' sys.exit(1) _PROJECT_PATH = os.path.join(_ANDROID_BUILD_TOP, 'test', 'vts-testcase', 'hal') _VTS_BUILD_TEMPLATE = os.path.join(_PROJECT_PATH, 'script', 'build', 'template', 'vts_build_template.bp') def __init__(self, warning_header): """BuildRuleGen constructor. Args: warning_header: string, warning header for every generated file. """ self._warning_header = warning_header self._vts_spec_parser = VtsSpecParser() def UpdateBuildRule(self): """Updates build rules under test/vts-testcase/hal.""" utils.RemoveFilesInDirIf( self._PROJECT_PATH, lambda x: self._IsAutoGenerated(x)) hal_list = self._vts_spec_parser.HalNamesAndVersions() self.UpdateTopLevelBuildRule() self.UpdateSecondLevelBuildRule(hal_list) self.UpdateHalDirBuildRule(hal_list) def UpdateTopLevelBuildRule(self): """Updates test/vts-testcase/hal/Android.bp""" utils.WriteBuildRule( os.path.join(self._PROJECT_PATH, 'Android.bp'), utils.OnlySubdirsBpRule(self._warning_header, ['*'])) def UpdateSecondLevelBuildRule(self, hal_list): """Updates test/vts-testcase/hal/<hal_name>/Android.bp""" top_level_dirs = dict() for target in hal_list: hal_dir = os.path.join( utils.HalNameDir(target[0]), utils.HalVerDir(target[1])) top_dir = hal_dir.split('/', 1)[0] top_level_dirs.setdefault( top_dir, []).append(os.path.relpath(hal_dir, top_dir)) for k, v in top_level_dirs.items(): file_path = os.path.join(self._PROJECT_PATH, k, 'Android.bp') utils.WriteBuildRule( file_path, utils.OnlySubdirsBpRule(self._warning_header, v)) def UpdateHalDirBuildRule(self, hal_list): """Updates build rules for vts drivers/profilers. Updates vts drivers/profilers for each pair of (hal_name, hal_version) in hal_list. Args: hal_list: list of tuple of strings. For example, [('vibrator', '1.3'), ('sensors', '1.7')] """ for target in hal_list: hal_name = target[0] hal_version = target[1] hal_dir = os.path.join(self._PROJECT_PATH, utils.HalNameDir(hal_name), utils.HalVerDir(hal_version)) file_path = os.path.join(hal_dir, 'Android.bp') utils.WriteBuildRule( file_path, utils.OnlySubdirsBpRule(self._warning_header, ['*'])) file_path = os.path.join(hal_dir, 'build', 'Android.bp') utils.WriteBuildRule(file_path, self._VtsBuildRuleFromTemplate( self._VTS_BUILD_TEMPLATE, hal_name, hal_version)) def _VtsBuildRuleFromTemplate(self, template_path, hal_name, hal_version): """Returns build rules in string form by filling out a template. Reads template from given path and fills it out. Args: template_path: string, path to build rule template file. hal_name: string, name of the hal, e.g. 'vibrator'. hal_version: string, version of the hal, e.g '7.4' Returns: string, complete build rules in string form """ with open(template_path) as template_file: build_template = str(template_file.read()) return self._FillOutBuildRuleTemplate(hal_name, hal_version, build_template) def _FillOutBuildRuleTemplate(self, hal_name, hal_version, template): """Returns build rules in string form by filling out given template. Args: hal_name: string, name of the hal, e.g. 'vibrator'. hal_version: string, version of the hal, e.g '7.4' template: string, build rule template to fill out. Returns: string, complete build rule in string form. """ def GeneratedOutput(hal_name, hal_version, extension): """Formats list of vts spec names into a string. Formats list of vts spec name for given hal_name, hal_version into a string that can be inserted into build template. Args: hal_name: string, name of the hal, e.g. 'vibrator'. hal_version: string, version of the hal, e.g '7.4' extension: string, extension of files e.g. '.cpp'. Returns: string, to be inserted into build template. """ result = [] vts_spec_names = self._vts_spec_parser.VtsSpecNames(hal_name, hal_version) for vts_spec in vts_spec_names: result.append('"android/hardware/%s/%s/%s%s",' % (utils.HalNameDir(hal_name), hal_version, vts_spec, extension)) return '\n '.join(result) def ImportedPackages(vts_pkg_type, imported_packages): """Formats list of imported packages into a string. Formats list of imported packages for given hal_name, hal_version into a string that can be inserted into build template. Args: vts_pkg_type: string 'driver' or 'profiler' imported_packages: list of imported packages Returns: string, to be inserted into build template. """ result = [] for package in imported_packages: prefix = 'android.hardware.' if package.startswith(prefix): # TODO(b/36475863) result.append('"%s",' % package) vts_pkg_name = package + '-vts.' + vts_pkg_type result.append('"%s",' % vts_pkg_name) else: result.append('"%s",' % package) return '\n '.join(result) build_rule = self._warning_header + template build_rule = build_rule.replace('{HAL_NAME}', hal_name) build_rule = build_rule.replace('{HAL_NAME_DIR}', utils.HalNameDir(hal_name)) build_rule = build_rule.replace('{HAL_VERSION}', hal_version) build_rule = build_rule.replace( '{GENERATED_VTS_SPECS}', GeneratedOutput(hal_name, hal_version, '')) build_rule = build_rule.replace( '{GENERATED_SOURCES}', GeneratedOutput(hal_name, hal_version, '.cpp')) build_rule = build_rule.replace( '{GENERATED_HEADERS}', GeneratedOutput(hal_name, hal_version, '.h')) imported_packages = self._vts_spec_parser.ImportedPackagesList( hal_name, hal_version) build_rule = build_rule.replace( '{IMPORTED_DRIVER_PACKAGES}', ImportedPackages('driver', imported_packages)) build_rule = build_rule.replace( '{IMPORTED_PROFILER_PACKAGES}', ImportedPackages('profiler', imported_packages)) return build_rule def _IsAutoGenerated(self, abs_file_path): """Checks if file was auto-generated. Args: abs_file_path: string, absolute file path. Returns: True iff file was auto-generated by BuildRuleGen. """ [dir_name, file_name] = os.path.split(abs_file_path) if file_name != 'Android.bp': return False with open(abs_file_path) as myfile: return self._warning_header in myfile.read()