diff --git a/kernel_build.py b/kernel_build.py new file mode 100644 index 0000000000000000000000000000000000000000..96c17c3bf27f1d61bd675e9a7bd9f1c927fe97ac --- /dev/null +++ b/kernel_build.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Copyright (C) 2022 Huawei Device Co., Ltd. +SPDX-License-Identifier: GPL-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 logging +import os +import re +import select +import sys +import subprocess +import shlex +import time + +def exec_cmd(command_list, shell=False, show_output=False, cwd=None): + if isinstance(command_list, str): + command_list = shlex.split(command_list) + elif not isinstance(command_list, list): + raise f"command_list to exec_cmd need to be a list or string" + command_list = ['nice'] + [str(s) for s in command_list] + + print(f"cwd: '{cwd}'") + print(f"cmd: '{command_list}'") + start = time.time() + proc = subprocess.Popen( + command_list if not shell else ' '.join(command_list), + cwd=cwd, + shell=shell, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + bufsize=1, + universal_newlines=True, + ) + + outmsg = "" + errmsg = "" + poller = select.epoll() + poller.register(proc.stdout, select.EPOLLIN) + poller.register(proc.stderr, select.EPOLLIN) + while proc.poll() is None: + for fd, event in poller.poll(): + if event is not select.EPOLLIN: + continue + if fd == proc.stdout.fileno(): + line = proc.stdout.readline() + if show_output is True: + print(">> [stdout] %s", line.strip('\n')) + outmsg += line + elif fd == proc.stderr.fileno(): + line = proc.stderr.readline() + if show_output is True: + print(">> [stderr] %s", line.strip('\n')) + errmsg += line + + for line in proc.stdout.readlines(): + if show_output is True: + print(">> [stdout] %s", line.strip('\n')) + outmsg += line + for line in proc.stderr.readlines(): + if show_output is True: + print(">> [stderr] %s", line.strip('\n')) + errmsg += line + + ret = proc.wait() + print(f"Returned {ret} in {int(time.time() - start)} seconds") + + return outmsg, errmsg, ret + + +def make_cmd(cmd, arch, cross_compile, knl_path): + make = f"{cmd} ARCH={arch} CROSS_COMPILE={cross_compile}" + 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 True, f'"{make}" success!' + + +def make_config(arch, config, corss_compile, knl_path): + make = f"make {config} ARCH={arch} CROSS_COMPILE={corss_compile}" + 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 True, f'"{make}" success!' + + +def make_j(arch, cross_compile, knl_path): + make = f'make -j{os.cpu_count()} ARCH={arch} CROSS_COMPILE={cross_compile}' + 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}' + + return True, f'"{make}" success!' + + +def cp_config(arch, config, config_path, knl_path): + if os.path.exists(config_path.format(arch, config)): + cp = f'cp ' + config_path.format(arch, config) + ' ' + os.path.join(knl_path, 'arch', arch, 'configs', config) + outmsg, errmsg, ret = exec_cmd(cp) + if ret: + print(f'"{cp}" errors --> \n {errmsg}') + return False, 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 True, f'"{cp}" success!' + + +def get_logger(filename): + log_format = '%(asctime)s %(name)s %(levelname)s %(message)s' + log_date_format = '%Y-%m-%d %H:%M:%S' + logging.basicConfig( + level=logging.INFO, + filename=filename, + format=log_format, + datefmt=log_date_format + ) + logger = logging.getLogger(__name__) + return logger + + +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: + logger.error(msg) + + ret, msg = make_cmd('make oldconfig', arch, cross_compile, knl_path) + if not ret: + logger.error(msg) + + ret, msg = make_cmd('make clean', arch, cross_compile, knl_path) + if not ret: + logger.error(msg) + + ret, msg = make_j(arch, cross_compile, knl_path) + if not ret: + logger.error(msg) + + ret, msg = cp_config(arch, config, config_path, knl_path) + if not ret: + logger.error(msg) + else: + ret, msg = make_config(arch, config, cross_compile, knl_path) + if not ret: + logger.error(msg) + + ret, msg = make_cmd('make clean', arch, cross_compile, knl_path) + if not ret: + logger.error(msg) + + ret, msg = make_j(arch, cross_compile, knl_path) + if not ret: + logger.error(msg) + + ret, msg = make_cmd('make allmodconfig', arch, cross_compile, knl_path) + if not ret: + logger.error(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: + logger.error(msg) + + ret, msg = make_j(arch, cross_compile, knl_path) + if not ret: + logger.error(msg) + + return True, f'build success!' + + +def main(): + config_path = './kernel/linux/config/linux-5.10/arch/{0}/configs/{1}' + knl_path = './kernel/linux/linux-5.10' + log_path = os.getcwd() + now_date = time.strftime("%Y%m%d%H%M%S", time.localtime()) + log_file = os.path.join(log_path, 'kernel_build_test.log') + logger = get_logger(log_file) + + 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) + + 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) + + +if __name__ == "__main__": + main()