#!/usr/bin/env python3 import os import shutil import common class LinuxComponent(common.Component): def add_parser_arguments(self, parser): parser.add_argument( '--config', default=[], action='append', help='''\ Add a single kernel config configs to the current build. Sample value: 'CONFIG_FORTIFY_SOURCE=y'. Can be used multiple times to add multiple configs. Takes precedence over any config files. ''' ) parser.add_argument( '--config-fragment', default=[], action='append', help='''\ Also use the given kernel configuration fragment file. Pass multiple times to use multiple fragment files. ''' ) parser.add_argument( '--custom-config-file', help='''\ Ignore all default kernel configurations and use this file instead. Still uses options explicitly passed with `--config` and `--config-fragment` on top of it. ''' ) parser.add_argument( '--config-only', default=False, action='store_true', help='''\ Configure the kernel, but don't build it. ''' ) parser.add_argument( '--initramfs', default=False, action='store_true', ) parser.add_argument( '--initrd', default=False, action='store_true', ) parser.add_argument( 'extra_make_args', default=[], metavar='extra-make-args', nargs='*' ) def do_build(self, args): build_dir = self.get_build_dir(args) if args.initrd or args.initramfs: raise Exception('just trolling, --initrd and --initramfs are broken for now') os.makedirs(build_dir, exist_ok=True) tool = 'gcc' gcc = common.get_toolchain_tool(tool) prefix = gcc[:-len(tool)] common_args = { 'cwd': common.linux_src_dir, } ccache = shutil.which('ccache') if ccache is not None: cc = '{} {}'.format(ccache, gcc) else: cc = gcc common_make_args = [ 'make', '-j', str(args.nproc), 'ARCH={}'.format(common.linux_arch), 'CROSS_COMPILE={}'.format(prefix), 'CC={}'.format(cc), 'O={}'.format(build_dir), ] if args.verbose: verbose = ['V=1'] else: verbose = [] if args.custom_config_file is not None: if not os.path.exists(args.custom_config_file): raise Exception('config fragment file does not exist: {}'.format(args.custom_config_file)) base_config_file = args.custom_config_file config_fragments = [] else: base_config_file = os.path.join(common.linux_config_dir, 'buildroot-{}'.format(args.arch)) config_fragments = ['min', 'default'] for i, config_fragment in enumerate(config_fragments): config_fragments[i] = os.path.join(common.linux_config_dir, config_fragment) config_fragments.extend(args.config_fragment) if args.config != []: cli_config_fragment_path = os.path.join(build_dir, 'lkmc_cli_config_fragment') cli_config_str = '\n'.join(args.config) common.write_string_to_file(cli_config_fragment_path, cli_config_str) config_fragments.append(cli_config_fragment_path) common.cp( base_config_file, os.path.join(build_dir, '.config'), ) common.run_cmd( [ os.path.join(common.linux_src_dir, 'scripts', 'kconfig', 'merge_config.sh'), '-m', '-O', build_dir, os.path.join(build_dir, '.config'), ] + config_fragments ) common.run_cmd( ( common_make_args + ['olddefconfig'] ), **common_args ) if not args.config_only: common.run_cmd( ( common_make_args + args.extra_make_args ), **common_args ) def get_argparse_args(self): return { 'description': '''\ Build the Linux kernel. ''' } def get_build_dir(self, args): return common.linux_build_dir if __name__ == '__main__': LinuxComponent().build()