From 5f022714f7298a76139358912951018180df431d Mon Sep 17 00:00:00 2001 From: Ma Feng Date: Thu, 19 Jan 2023 09:21:36 +0800 Subject: [PATCH] kernel_build.py: update script 1. Add mask known warnings. 2. Set return value based on the compile result. Signed-off-by: Ma Feng --- kernel_build.py | 222 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 196 insertions(+), 26 deletions(-) diff --git a/kernel_build.py b/kernel_build.py index 96c17c3..ceefaa8 100644 --- a/kernel_build.py +++ b/kernel_build.py @@ -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__": -- Gitee