1*4882a593Smuzhiyun# Development tool - build command plugin 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# Copyright (C) 2014-2015 Intel Corporation 4*4882a593Smuzhiyun# 5*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun"""Devtool build plugin""" 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunimport os 10*4882a593Smuzhiyunimport bb 11*4882a593Smuzhiyunimport logging 12*4882a593Smuzhiyunimport argparse 13*4882a593Smuzhiyunimport tempfile 14*4882a593Smuzhiyunfrom devtool import exec_build_env_command, setup_tinfoil, check_workspace_recipe, DevtoolError 15*4882a593Smuzhiyunfrom devtool import parse_recipe 16*4882a593Smuzhiyun 17*4882a593Smuzhiyunlogger = logging.getLogger('devtool') 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun 20*4882a593Smuzhiyundef _set_file_values(fn, values): 21*4882a593Smuzhiyun remaining = list(values.keys()) 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun def varfunc(varname, origvalue, op, newlines): 24*4882a593Smuzhiyun newvalue = values.get(varname, origvalue) 25*4882a593Smuzhiyun remaining.remove(varname) 26*4882a593Smuzhiyun return (newvalue, '=', 0, True) 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun with open(fn, 'r') as f: 29*4882a593Smuzhiyun (updated, newlines) = bb.utils.edit_metadata(f, values, varfunc) 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun for item in remaining: 32*4882a593Smuzhiyun updated = True 33*4882a593Smuzhiyun newlines.append('%s = "%s"' % (item, values[item])) 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun if updated: 36*4882a593Smuzhiyun with open(fn, 'w') as f: 37*4882a593Smuzhiyun f.writelines(newlines) 38*4882a593Smuzhiyun return updated 39*4882a593Smuzhiyun 40*4882a593Smuzhiyundef _get_build_tasks(config): 41*4882a593Smuzhiyun tasks = config.get('Build', 'build_task', 'populate_sysroot,packagedata').split(',') 42*4882a593Smuzhiyun return ['do_%s' % task.strip() for task in tasks] 43*4882a593Smuzhiyun 44*4882a593Smuzhiyundef build(args, config, basepath, workspace): 45*4882a593Smuzhiyun """Entry point for the devtool 'build' subcommand""" 46*4882a593Smuzhiyun workspacepn = check_workspace_recipe(workspace, args.recipename, bbclassextend=True) 47*4882a593Smuzhiyun tinfoil = setup_tinfoil(config_only=False, basepath=basepath) 48*4882a593Smuzhiyun try: 49*4882a593Smuzhiyun rd = parse_recipe(config, tinfoil, args.recipename, appends=True, filter_workspace=False) 50*4882a593Smuzhiyun if not rd: 51*4882a593Smuzhiyun return 1 52*4882a593Smuzhiyun deploytask = 'do_deploy' in rd.getVar('__BBTASKS') 53*4882a593Smuzhiyun finally: 54*4882a593Smuzhiyun tinfoil.shutdown() 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun if args.clean: 57*4882a593Smuzhiyun # use clean instead of cleansstate to avoid messing things up in eSDK 58*4882a593Smuzhiyun build_tasks = ['do_clean'] 59*4882a593Smuzhiyun else: 60*4882a593Smuzhiyun build_tasks = _get_build_tasks(config) 61*4882a593Smuzhiyun if deploytask: 62*4882a593Smuzhiyun build_tasks.append('do_deploy') 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun bbappend = workspace[workspacepn]['bbappend'] 65*4882a593Smuzhiyun if args.disable_parallel_make: 66*4882a593Smuzhiyun logger.info("Disabling 'make' parallelism") 67*4882a593Smuzhiyun _set_file_values(bbappend, {'PARALLEL_MAKE': ''}) 68*4882a593Smuzhiyun try: 69*4882a593Smuzhiyun bbargs = [] 70*4882a593Smuzhiyun for task in build_tasks: 71*4882a593Smuzhiyun if args.recipename.endswith('-native') and 'package' in task: 72*4882a593Smuzhiyun continue 73*4882a593Smuzhiyun bbargs.append('%s:%s' % (args.recipename, task)) 74*4882a593Smuzhiyun exec_build_env_command(config.init_path, basepath, 'bitbake %s' % ' '.join(bbargs), watch=True) 75*4882a593Smuzhiyun except bb.process.ExecutionError as e: 76*4882a593Smuzhiyun # We've already seen the output since watch=True, so just ensure we return something to the user 77*4882a593Smuzhiyun return e.exitcode 78*4882a593Smuzhiyun finally: 79*4882a593Smuzhiyun if args.disable_parallel_make: 80*4882a593Smuzhiyun _set_file_values(bbappend, {'PARALLEL_MAKE': None}) 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun return 0 83*4882a593Smuzhiyun 84*4882a593Smuzhiyundef register_commands(subparsers, context): 85*4882a593Smuzhiyun """Register devtool subcommands from this plugin""" 86*4882a593Smuzhiyun parser_build = subparsers.add_parser('build', help='Build a recipe', 87*4882a593Smuzhiyun description='Builds the specified recipe using bitbake (up to and including %s)' % ', '.join(_get_build_tasks(context.config)), 88*4882a593Smuzhiyun group='working', order=50) 89*4882a593Smuzhiyun parser_build.add_argument('recipename', help='Recipe to build') 90*4882a593Smuzhiyun parser_build.add_argument('-s', '--disable-parallel-make', action="store_true", help='Disable make parallelism') 91*4882a593Smuzhiyun parser_build.add_argument('-c', '--clean', action='store_true', help='clean up recipe building results') 92*4882a593Smuzhiyun parser_build.set_defaults(func=build) 93