#!/usr/bin/env python
|
#
|
# Copyright (C) 2018 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 glob
|
import os.path
|
import re
|
import sys
|
|
PREBUILTS_VNDK_DIR = "prebuilts/vndk"
|
VENDOR_DIRECTORIES = ('/vendor', '/odm')
|
|
def find_latest_vndk_snapshot_version():
|
"""Returns latest vndk snapshot version in current source tree.
|
It will skip the test if the snapshot directories are not found.
|
|
Returns:
|
latest_version: string
|
"""
|
vndk_dir_list = glob.glob(PREBUILTS_VNDK_DIR + "/v*")
|
if not vndk_dir_list:
|
"""Exit without error because we may have source trees that do not include
|
VNDK snapshot directories in it.
|
"""
|
sys.exit(0)
|
vndk_ver_list = [re.match(r".*/v(\d+)", vndk_dir).group(1)
|
for vndk_dir in vndk_dir_list]
|
latest_version = max(vndk_ver_list)
|
if latest_version == '27':
|
"""Exit without error because VNDK v27 is not using ld.config.txt template
|
"""
|
sys.exit(0)
|
return latest_version
|
|
def get_vendor_configuration(ld_config_file):
|
"""Reads the ld.config.txt file to parse the namespace configurations.
|
It finds the configurations that include vendor directories.
|
|
Args:
|
ld_config_file: string, path (relative to build top) of the ld.config.txt
|
file.
|
Returns:
|
configs: dict{string:[string]}, dictionary of namespace configurations.
|
it has 'section + property' names as keys and the directory list
|
as values.
|
"""
|
try:
|
conf_file = open(ld_config_file)
|
except IOError:
|
print("error: could not read %s" % ld_config_file)
|
sys.exit(1)
|
|
configs = dict()
|
current_section = None
|
|
with conf_file:
|
for line in conf_file:
|
# ignore comments
|
found = line.find('#')
|
if found != -1:
|
line = line[:found]
|
line = line.strip()
|
if not line:
|
continue
|
|
if line[0] == '[' and line[-1] == ']':
|
# new section started
|
current_section = line[1:-1]
|
continue
|
|
if current_section == None:
|
continue
|
|
found = line.find('+=')
|
opr_len = 2
|
if found == -1:
|
found = line.find('=')
|
opr_len = 1
|
if found == -1:
|
continue
|
|
namespace = line[:found].strip()
|
if not namespace.endswith(".paths"):
|
# check ".paths" only
|
continue
|
namespace = '[' + current_section + ']' + namespace
|
values = line[found + opr_len:].strip()
|
directories = values.split(':')
|
|
for directory in directories:
|
if any(vendor_dir in directory for vendor_dir in VENDOR_DIRECTORIES):
|
if namespace in configs:
|
configs[namespace].append(directory)
|
else:
|
configs[namespace] = [directory]
|
|
return configs
|
|
def get_snapshot_config(version):
|
"""Finds the ld.config.{version}.txt file from the VNDK snapshot directory.
|
In the vndk prebuilt directory (prebuilts/vndk/v{version}), it searches
|
{arch}/configs/ld.config.{version}.txt file, where {arch} is one of ('arm64',
|
'arm', 'x86_64', 'x86').
|
|
Args:
|
version: string, the VNDK snapshot version to search.
|
Returns:
|
ld_config_file: string, relative path to ld.config.{version}.txt
|
"""
|
arch_list = ('arm64', 'arm', 'x86_64', 'x86')
|
for arch in arch_list:
|
ld_config_file = (PREBUILTS_VNDK_DIR
|
+ "/v{0}/{1}/configs/ld.config.{0}.txt".format(version, arch))
|
if os.path.isfile(ld_config_file):
|
return ld_config_file
|
print("error: cannot find ld.config.{0}.txt file in snapshot v{0}"
|
.format(version))
|
sys.exit(1)
|
|
def check_backward_compatibility(ld_config, vndk_snapshot_version):
|
"""Checks backward compatibility for current ld.config.txt file with the
|
old ld.config.txt file. If any of the vendor directories in the old namespace
|
configurations are missing, the test will fail. It is allowed to have new
|
vendor directories in current ld.config.txt file.
|
|
Args:
|
ld_config: string, relative path to current ld.config.txt file.
|
vndk_snapshot_version: string, the VNDK snapshot version that has an old
|
ld.config.txt file to compare.
|
Returns:
|
result: bool, True if the current configuration is backward compatible.
|
"""
|
current_config = get_vendor_configuration(ld_config)
|
old_config = get_vendor_configuration(
|
get_snapshot_config(vndk_snapshot_version))
|
for namespace in old_config:
|
if namespace not in current_config:
|
print("error: cannot find %s which was provided in ld.config.%s.txt"
|
% (namespace, vndk_snapshot_version))
|
return False
|
for path in old_config[namespace]:
|
if not path in current_config[namespace]:
|
print("error: %s for %s in ld.config.%s.txt are missing in %s"
|
% (path, namespace, vndk_snapshot_version, ld_config))
|
return False
|
return True
|
|
def main():
|
if len(sys.argv) != 2:
|
print ("Usage: %s target_ld_config_txt_file_name" % sys.argv[0])
|
sys.exit(1)
|
|
latest_vndk_snapshot_version = find_latest_vndk_snapshot_version()
|
if not check_backward_compatibility(sys.argv[1],
|
latest_vndk_snapshot_version):
|
print("error: %s has backward incompatible changes to old "
|
"vendor partition." % sys.argv[1])
|
sys.exit(1)
|
|
# Current ld.config.txt file is backward compatible
|
sys.exit(0)
|
|
if __name__ == '__main__':
|
main()
|