import re
import sys
import os
import xml.etree.ElementTree as ET
class CheckGnOnline(object):
TARGET_NAME = ('ohos_shared_library',
'ohos_static_library', 'ohos_executable',
'ohos_source_set',
'ohos_copy',
'ohos_group',
'ohos_prebuilt_executable',
'ohos_prebuilt_shared_library',
'ohos_prebuilt_static_library',
'ohos_prebuilt_etc')
def __init__(self, gn_data: dict) -> None:
self.status = True
self.gn_data = gn_data
self.err_info = list()
def merge_line(self) -> dict:
ret_dict = dict()
for key, values in self.gn_data.items():
contents = ''
row_range = list()
start = -2
end = -2
for line in values:
pos = line[0]
content = line[1]
if pos == end + 1:
end = pos
contents += '\n{}'.format(content)
elif start != end:
row_range.append([start, end, contents])
contents = content
start = pos
end = pos
else:
contents = content
start = pos
end = pos
if pos == values[-1][0] and start != end:
row_range.append([start, end, contents])
ret_dict.update({key: row_range})
return ret_dict
def check_have_product_name(self, key: str, line: list) -> None:
rules = '规则4.1 部件编译脚本中禁止使用产品名称变量'
check_list = ['product_name', 'device_name']
flag = {check_list[0]: False, check_list[1]: False}
for check_item in check_list:
if line[1].find(check_item) != -1 and line[1].find("==") != -1:
flag[check_item] = True
if any(flag.values()):
issue = '存在'
issue += check_list[0] if flag[check_list[0]] else ''
issue += ',' if all(flag.values()) else ''
issue += check_list[1] if flag[check_list[1]] else ''
pos = "line:{} {}".format(line[0], line[1])
self.err_info.append([key, pos, rules, issue])
self.status = False
return
def check_abs_path(self, key: str, line: list) -> None:
rules = '规则3.1 部件编译脚本中只允许引用本部件路径,禁止引用其他部件的绝对或相对路径'
issue = '存在绝对路径'
abs_path_pattern = r'"\/(\/[^\/\n]+){1,63}"'
abs_info = list()
abs_iter = re.finditer(abs_path_pattern, line[1])
for match in abs_iter:
path = match.group().strip('"')
if path.startswith('//build') or path.startswith('//third_party'):
break
if path.startswith('//prebuilts'):
break
if path.startswith('//out'):
break
abs_info.append(path)
if len(abs_info) > 0:
pos = "line:{} {}".format(line[0], line[1])
self.err_info.append([key, pos, rules, issue])
self.status = False
return
def iter_modified_line(self, key, modified_line, target_pattern) -> None:
rules = '规则3.2 部件编译目标必须指定部件和子系统名'
check_list = ['subsystem_name', 'part_name']
for line in modified_line:
targets = re.finditer(target_pattern, line[2], re.M)
for it_target in targets:
flag = {check_list[0]: False, check_list[1]: False}
target = it_target.group()
start_target = target.split('\n')[0]
target_pos = line[2].find(start_target)
line_offset = line[2].count('\n', 1, target_pos)
if target.find(check_list[0]) == -1:
flag[check_list[0]] = True
if target.find(check_list[1]) == -1:
flag[check_list[1]] = True
if any(flag.values()):
issue = 'target不存在'
issue += check_list[0] if flag[check_list[0]] else ''
issue += ',' if all(flag.values()) else ''
issue += check_list[1] if flag[check_list[1]] else ''
pos = "line:{} {}".format(
line[0] + line_offset, start_target)
self.err_info.append([key, pos, rules, issue])
self.status = False
return
def check_pn_sn(self) -> None:
rules = '规则3.2 部件编译目标必须指定部件和子系统名'
target_pattern = r"^( *)("
for target in self.TARGET_NAME:
target_pattern += target
if target != self.TARGET_NAME[-1]:
target_pattern += r'|'
target_pattern += r")[\s|\S]*?\n\1}$"
gn_data_merge = self.merge_line()
for key, values in gn_data_merge.items():
self.iter_modified_line(key, values, target_pattern)
return
def load_ohos_xml(self, path):
ret_dict = dict()
tree = ET.parse(path)
root = tree.getroot()
for node in root.iter():
if node.tag != 'project':
continue
repo_info = node.attrib
ret_item = {repo_info['name']: repo_info['groups']}
ret_dict.update(ret_item)
return ret_dict
def is_checked(self, file, xml_dict):
repo_name = file.split(',')[0].split('/')[-3]
if repo_name in xml_dict.keys():
if not file.endswith("(new file)"):
if xml_dict[repo_name].find('ohos:mini') != -1:
return False
if xml_dict[repo_name].find('ohos:small') != -1:
return False
if repo_name.startswith('device_') or repo_name.startswith('vendor'):
return False
if repo_name.startswith('build') or repo_name.startswith('third_party'):
return False
return True
def pre_check(self):
xml_dict = self.load_ohos_xml(".repo/manifests/ohos/ohos.xml")
for key in list(self.gn_data.keys()):
if not self.is_checked(key, xml_dict):
self.gn_data.pop(key)
def check(self):
if not self.gn_data:
return
for key, values in self.gn_data.items():
for line in values:
if line[1].strip().startswith("import"):
continue;
self.check_have_product_name(key, line)
self.check_abs_path(key, line)
self.check_pn_sn()
def output(self):
self.pre_check()
self.check()
return self.status, self.err_info
if __name__ == "__main__":
data = {'a.gn': [[11, 'dsfsdf product_name'], [13, '("//build/dasd/")']],
'b.gn': [[4, 'sdfd'],
[5, 'ohos_shared_library("librawfile") {'],
[14, 'sdfd'],
[15, 'ohos_shared_library("librawfile") {'],
[16, ' include_dirs = ['],
[17, ' "//base/global/resource_management/frameworks/resmgr/include",'],
[18, ' subsystem_name = "global"'], [19, '}'],
[25, ' subsystem_name = "global"'], [29, '}']]}
a = CheckGnOnline(data)
a.output()
exit(0)