#!/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()