kernel_build.py: update script

1. Add mask known warnings.
2. Set return value based on the compile result.

Signed-off-by: Ma Feng <mafeng.ma@huawei.com>
This commit is contained in:
Ma Feng
2023-01-19 09:21:36 +08:00
parent 241ca649f0
commit 2b2ffa1960
+196 -26
View File
@@ -20,6 +20,139 @@ import subprocess
import shlex
import time
ignores = [
"include/trace/events/eas_sched.h: warning: format '%d' expects arguments of type 'int', but argument 9 has type 'long unsigned int' [-Wformat=]",
"drivers/block/zram/zram_drv.c: warning: left shift count >= width of type",
"include/trace/events/eas_sched.h: note: in expansion of macro",
"include/trace/events/eas_sched.h: note: format string is defined here",
"include/trace/trace_events.h: note: in expansion of macro",
"mm/vmscan.c: warning: suggest parentheses around assignment used as truth value [-Wparentheses]",
"lib/bitfiled_kunit.c: warning: the frame size of \d+ bytes is larger than \d+ bytes",
]
class Reporter:
def __init__(self, arch, path):
self.arch = arch
self.path = path
def normpath(self, filename):
if re.search("^[\.]+[^/]", filename):
filename = re.sub("^[\.]+", "", filename)
return os.path.normpath(filename)
def format_title(self, title):
title = re.sub("\u2018", "'", title)
title = re.sub("\u2019", "'", title)
return title.strip()
def report_build_warning(self, filename, regex, details):
if len(details) == 0 or filename is None:
return None
if not os.path.exists(os.path.join(self.path, filename)):
return None
line = details[0]
try:
warning = re.search(regex, line).group(0)
except:
print('Expect>>>', details)
return
report = {
'title': self.format_title("%s: %s" % (filename, warning)),
'filename': filename,
'report': '\n'.join(details),
'nr': line.split(':')[1],
}
return report
def parse_build_warning(self, blocks, regex, title_regex):
issues = {}
reports = []
details = []
filename = None
unused = False
for line in blocks:
attrs = line.split(':')
if len(attrs) < 5 and filename is None:
continue
if line.startswith(' ') or len(attrs) < 2:
if unused is True:
details.append(line)
continue
if not regex in line:
unused = False
continue
unused = True
newfile = self.normpath(attrs[0])
if newfile != filename:
if len(details) and filename:
if filename in issues:
issues[filename].extend(details)
else:
issues[filename] = details
filename = newfile
details = []
details.append(line)
if len(details) and filename:
if filename in issues:
issues[filename].extend(details)
else:
issues[filename] = details
for filename, details in issues.items():
report = self.report_build_warning(filename, title_regex, details)
if not report is None:
reports.append(report)
def parse(self, content):
blocks = content.split('\n')
reports = []
patterns = (
('[-Wunused-but-set-variable]', 'warning: .* set but not used'),
('[-Wunused-but-set-parameter]', 'warning: .* set but not used'),
('[-Wunused-const-variable=]', 'warning: .* defined but not used'),
('[-Wold-style-definition]', 'warning: .* definition'),
('[-Wold-style-declaration]', 'warning: .* declaration'),
('[-Wmaybe-uninitialized]', 'warning: .* uninitialized'),
('[-Wtype-limits]', 'warning: .* always (false|true)'),
('[-Wunused-function]', 'warning: .* defined but not used'),
('[-Wsequence-point]', 'warning: .* may be undefined'),
('[-Wformat=]', 'warning: format.*'),
('[-Wunused-variable]', 'warning: [^\[]*'),
('[-Wframe-larger-than=]', 'warning: the frame size [^\[]*'),
('[-Wshift-count-overflow]', 'warning: left shift count >= width of type'),
('definition or declaration', 'warning: .* declared inside parameter list will not be visible outside of this definition or declaration'),
('character', 'warning: missing termination .* character'),
('in expansion of macro', 'note: in expansion of macro'),
('note: fromat string is defined here', 'note: format string is defined here'),
('[-Wparentheses]', 'suggest parentheses around assignment used as truth value'),
)
for regex, title_regex in patterns:
items = self.parse_build_warning(blocks, regex, title_regex)
if items is None:
continue
reports.extend(items)
return reports
def exec_cmd(command_list, shell=False, show_output=False, cwd=None):
if isinstance(command_list, str):
command_list = shlex.split(command_list)
@@ -80,9 +213,9 @@ def make_cmd(cmd, arch, cross_compile, knl_path):
outmsg, errmsg, ret = exec_cmd(make, cwd=knl_path)
if ret:
print(f'"{make}" errors --> \n {errmsg}')
return False, f'"{make}" errors --> \n {errmsg}'
return ret, f'"{make}" errors --> \n {errmsg}'
return True, f'"{make}" success!'
return ret, f'"{make}" success!'
def make_config(arch, config, corss_compile, knl_path):
@@ -90,9 +223,9 @@ def make_config(arch, config, corss_compile, knl_path):
outmsg, errmsg, ret = exec_cmd(make, cwd=knl_path)
if ret:
print(f'"{make}" errors --> \n {errmsg}')
return False, f'"{make}" errors --> \n {errmsg}'
return ret, f'"{make}" errors --> \n {errmsg}'
return True, f'"{make}" success!'
return ret, f'"{make}" success!'
def make_j(arch, cross_compile, knl_path):
@@ -100,12 +233,30 @@ def make_j(arch, cross_compile, knl_path):
outmsg, errmsg, ret = exec_cmd(make, cwd=knl_path)
if ret:
print(f'"{make}" errors --> \n {errmsg}')
return False, f'"{make}" errors --> \n {errmsg}'
elif len(errmsg) > 0:
print(f'"{make}" warnings --> \n {errmsg}')
return False, f'"{make}" warnings --> \n {errmsg}'
result = "success"
reporter = Reporter(arch, knl_path)
known_issue = "\nKnown issue:\n"
for report in reporter.parse(errmsg):
if ignores and [i for i in ignores if re.match(i, report['title'])]:
known_issue = known_issue + report['title'] + "\n"
known_issue = known_issue + report['report'] + "\n"
continue
result = 'failed'
return True, f'"{make}" success!'
print(known_issue)
new_issue = "\nNew Issue:\n"
if result == "failed":
for report in reporter.parse(errmsg):
if ignores and [i for i in ignores if re.match(i, report['title'])]:
continue
new_issue = new_issue + report['title'] + "\n"
new_issue = new_issue + report['report'] + "\n"
print(new_issue)
return 2, f'"{make}" warning --> \n {errmsg}'
return ret, f'"{make}" warnings in ignores --> \n {errmsg}'
return ret, f'"{make}" success!'
def cp_config(arch, config, config_path, knl_path):
@@ -114,12 +265,12 @@ def cp_config(arch, config, config_path, knl_path):
outmsg, errmsg, ret = exec_cmd(cp)
if ret:
print(f'"{cp}" errors --> \n {errmsg}')
return False, f'"{cp}" errors --> \n {errmsg}'
return ret, f'"{cp}" errors --> \n {errmsg}'
else:
print(f'"{config_path.format(arch, config)}" not exists!')
return False, f'"{config_path.format(arch, config)}" not exists!'
return ret, f'"{config_path.format(arch, config)}" not exists!'
return True, f'"{cp}" success!'
return ret, f'"{cp}" success!'
def get_logger(filename):
@@ -137,53 +288,64 @@ def get_logger(filename):
def build(arch, config, config_path, cross_compile, knl_path, logger):
ret, msg = make_cmd('make defconfig', arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = make_cmd('make oldconfig', arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = make_cmd('make clean', arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = make_j(arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = cp_config(arch, config, config_path, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
else:
ret, msg = make_config(arch, config, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = make_cmd('make clean', arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = make_j(arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = make_cmd('make allmodconfig', arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
sed = f'sed -i s/^.*CONFIG_FRAME_WARN.*$/CONFIG_FRAME_WARN=2048/ .config'
outmsg, errmsg, ret = exec_cmd(sed, cwd=knl_path)
ret, msg = make_cmd('make clean', arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
ret, msg = make_j(arch, cross_compile, knl_path)
if not ret:
if ret:
logger.error(msg)
return ret, msg
return True, f'build success!'
return 0, f'build success!'
def main():
@@ -197,12 +359,20 @@ def main():
arch = 'arm'
config = 'hispark_taurus_standard_defconfig'
cross_compile = '../../../prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/arm-linux-gnueabi-'
build(arch, config, config_path, cross_compile, knl_path, logger)
arm_ret, arm_msg = build(arch, config, config_path, cross_compile, knl_path, logger)
arch = 'arm64'
config = 'rk3568_standard_defconfig'
cross_compile = '../../../prebuilts/gcc/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-'
build(arch, config, config_path, cross_compile, knl_path, logger)
arm64_ret, arm64_msg = build(arch, config, config_path, cross_compile, knl_path, logger)
print(f'arm_ret: {arm_ret}, arm64_ret: {arm64_ret}')
if any([arm_ret, arm64_ret]):
print('kernel build test failed!')
exit(arm_ret or arm64_ret)
print('kernel build test success.')
exit(0)
if __name__ == "__main__":