From patchwork Fri Oct 23 10:22:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anusmita Dutta Mazumder X-Patchwork-Id: 101783 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.3856.1792750965131725995 for ; Fri, 23 Oct 2026 03:22:45 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@arm.com header.s=foss header.b=mP/mO8Qm; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: anusmita.duttamazumder@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 66B491650; Fri, 23 Oct 2026 03:22:41 -0700 (PDT) Received: from e142472.cambridge.arm.com (e142472.arm.com [10.2.210.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 17B5D3F7B4; Fri, 23 Oct 2026 03:22:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1792750964; bh=ygnOx1XjOvnAcQ0Cj8iomVIr25giU7dODJXFQ7o7K/Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mP/mO8Qm2wcibe0tHZRLPAf/Y7774KpK4FXVpRu27VSAnkcJhBltu9Z3a8fXdzR3h 63Xz1VC3jwm+EjUmu37RI9lWcOe5LPCOvMCJQtd/cfP3MejmFW+0jEfP9mr3lReFpW yiTFRwB8m+tp/NIQMXFHYiuL4RCH7JyG0kFfglEI= From: Anusmita Dutta Mazumder To: openembedded-core@lists.openembedded.org Cc: Anusmita Dutta Mazumder Subject: [PATCH 1/5] devtool: Support multiconfig recipe workflows Date: Fri, 23 Oct 2026 11:22:11 +0100 Message-ID: <20261023102215.4043005-2-anusmita.duttamazumder@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261023102215.4043005-1-anusmita.duttamazumder@arm.com> References: <20261023102215.4043005-1-anusmita.duttamazumder@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Fri, 23 Oct 2026 10:22:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/248499 Preserve multiconfig-qualified targets when extracting and configuring sources. Use the recipe name without the multiconfig prefix for workspace lookups. Keep the prefix when calling BitBake from reset, update-recipe, and finish. Fixes [YOCTO #13933] Signed-off-by: Anusmita Dutta Mazumder --- scripts/lib/devtool/standard.py | 78 +++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py index 0d933e68b1..84fa19c7aa 100644 --- a/scripts/lib/devtool/standard.py +++ b/scripts/lib/devtool/standard.py @@ -23,6 +23,7 @@ from collections import OrderedDict from devtool import exec_build_env_command, setup_tinfoil, check_workspace_recipe, use_external_build, setup_git_repo, recipe_to_append, get_bbclassextend_targets, update_unlockedsigs, check_prerelease_version, check_git_repo_dirty, check_git_repo_op, DevtoolError from devtool import parse_recipe +import bb.runqueue import bb.utils logger = logging.getLogger('devtool') @@ -30,6 +31,21 @@ logger = logging.getLogger('devtool') override_branch_prefix = 'devtool-override-' +def _prefix_multiconfig_targets(mc, targets): + """Add a multiconfig prefix to build targets.""" + if not mc: + return targets + + return ' '.join(target if target.startswith('mc:') else + 'mc:%s:%s' % (mc, target) + for target in targets.split()) + + +def _get_multiconfig_targets(d, targets): + """Add the recipe datastore's multiconfig prefix to build targets.""" + return _prefix_multiconfig_targets(d.getVar('BB_CURRENT_MC'), targets) + + def add(args, config, basepath, workspace): """Entry point for the devtool 'add' subcommand""" import bb.data @@ -596,7 +612,7 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works task = None # Run the fetch + unpack tasks - res = tinfoil.build_targets(pn, + res = tinfoil.build_targets(_get_multiconfig_targets(d, pn), task, handle_events=True) finally: @@ -829,7 +845,8 @@ def modify(args, config, basepath, workspace): f.write('%s\n' % fname) task = 'do_configure' - res = tinfoil.build_targets(pn, task, handle_events=True) + target = _get_multiconfig_targets(rd, pn) + res = tinfoil.build_targets(target, task, handle_events=True) # Copy .config to workspace kconfpath = rd.getVar('B') @@ -1919,7 +1936,7 @@ def _update_recipe(recipename, workspace, rd, mode, appendlayerdir, wildcard_ver def update_recipe(args, config, basepath, workspace): """Entry point for the devtool 'update-recipe' subcommand""" - check_workspace_recipe(workspace, args.recipename) + workspacepn = check_workspace_recipe(workspace, args.recipename) if args.append: if not os.path.exists(args.append): @@ -1941,7 +1958,11 @@ def update_recipe(args, config, basepath, workspace): if args.dry_run: dry_run_output = tempfile.TemporaryDirectory(prefix='devtool') dry_run_outdir = dry_run_output.name - updated, _, _ = _update_recipe(args.recipename, workspace, rd, args.mode, args.append, args.wildcard_version, args.no_remove, args.initial_rev, dry_run_outdir=dry_run_outdir, no_overrides=args.no_overrides, force_patch_refresh=args.force_patch_refresh) + updated, _, _ = _update_recipe( + workspacepn, workspace, rd, args.mode, args.append, + args.wildcard_version, args.no_remove, args.initial_rev, + dry_run_outdir=dry_run_outdir, no_overrides=args.no_overrides, + force_patch_refresh=args.force_patch_refresh) if updated: rf = rd.getVar('FILE') @@ -1968,11 +1989,17 @@ def status(args, config, basepath, workspace): return 0 -def _reset(recipes, no_clean, remove_work, config, basepath, workspace): +def _reset(recipes, no_clean, remove_work, config, basepath, workspace, + bitbake_targets=None): """Reset one or more recipes""" import bb.process import oe.path + if bitbake_targets is None: + bitbake_targets = recipes + if len(bitbake_targets) != len(recipes): + raise DevtoolError('Reset recipes and BitBake targets do not match') + def clean_preferred_provider(pn, layerconf_path): """Remove PREFERRED_PROVIDER from layer.conf'""" import re @@ -2002,11 +2029,15 @@ def _reset(recipes, no_clean, remove_work, config, basepath, workspace): # it uses BBCLASSEXTEND, then we need to also clean the other # variants targets = [] - for recipe in recipes: - targets.append(recipe) + for recipe, bitbake_target in zip(recipes, bitbake_targets): + targets.append(bitbake_target) recipefile = workspace[recipe]['recipefile'] if recipefile and os.path.exists(recipefile): - targets.extend(get_bbclassextend_targets(recipefile, recipe)) + variants = get_bbclassextend_targets(recipefile, recipe) + mc, _ = bb.runqueue.split_mc(bitbake_target) + variants = _prefix_multiconfig_targets(mc, + ' '.join(variants)) + targets.extend(variants.split()) try: exec_build_env_command(config.init_path, basepath, 'bitbake -c clean %s' % ' '.join(targets)) except bb.process.ExecutionError as e: @@ -2086,23 +2117,27 @@ def _reset(recipes, no_clean, remove_work, config, basepath, workspace): def reset(args, config, basepath, workspace): """Entry point for the devtool 'reset' subcommand""" - recipes = "" + recipes = [] + bitbake_targets = [] if args.recipename: if args.all: raise DevtoolError("Recipe cannot be specified if -a/--all is used") else: for recipe in args.recipename: - check_workspace_recipe(workspace, recipe, checksrc=False) + workspacepn = check_workspace_recipe(workspace, recipe, + checksrc=False) + recipes.append(workspacepn) + bitbake_targets.append(recipe) elif not args.all: raise DevtoolError("Recipe must be specified, or specify -a/--all to " "reset all recipes") if args.all: recipes = list(workspace.keys()) - else: - recipes = args.recipename + bitbake_targets = recipes - _reset(recipes, args.no_clean, args.remove_work, config, basepath, workspace) + _reset(recipes, args.no_clean, args.remove_work, config, basepath, workspace, + bitbake_targets=bitbake_targets) return 0 @@ -2137,14 +2172,14 @@ def finish(args, config, basepath, workspace): import bb import oe.recipeutils - check_workspace_recipe(workspace, args.recipename) + workspacepn = check_workspace_recipe(workspace, args.recipename) dry_run_suffix = ' (dry-run)' if args.dry_run else '' # Grab the equivalent of COREBASE without having to initialise tinfoil corebasedir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) - srctree = workspace[args.recipename]['srctree'] + srctree = workspace[workspacepn]['srctree'] check_git_repo_op(srctree, [corebasedir]) dirty = check_git_repo_dirty(srctree) if dirty: @@ -2175,7 +2210,7 @@ def finish(args, config, basepath, workspace): # If it's an upgrade, grab the original path origpath = None origfilelist = None - append = workspace[args.recipename]['bbappend'] + append = workspace[workspacepn]['bbappend'] with open(append, 'r') as f: for line in f: if line.startswith('# original_path:'): @@ -2217,7 +2252,12 @@ def finish(args, config, basepath, workspace): if args.dry_run: dry_run_output = tempfile.TemporaryDirectory(prefix='devtool') dry_run_outdir = dry_run_output.name - updated, appendfile, removed = _update_recipe(args.recipename, workspace, rd, args.mode, appendlayerdir, wildcard_version=True, no_remove=False, no_report_remove=removing_original, initial_rev=args.initial_rev, dry_run_outdir=dry_run_outdir, no_overrides=args.no_overrides, force_patch_refresh=args.force_patch_refresh) + updated, appendfile, removed = _update_recipe( + workspacepn, workspace, rd, args.mode, appendlayerdir, + wildcard_version=True, no_remove=False, + no_report_remove=removing_original, initial_rev=args.initial_rev, + dry_run_outdir=dry_run_outdir, no_overrides=args.no_overrides, + force_patch_refresh=args.force_patch_refresh) removed = [os.path.relpath(pth, recipedir) for pth in removed] # Remove any old files in the case of an upgrade @@ -2306,7 +2346,9 @@ def finish(args, config, basepath, workspace): if args.dry_run: logger.info('Resetting recipe (dry-run)') else: - _reset([args.recipename], no_clean=no_clean, remove_work=remove_work, config=config, basepath=basepath, workspace=workspace) + _reset([workspacepn], no_clean=no_clean, remove_work=remove_work, + config=config, basepath=basepath, workspace=workspace, + bitbake_targets=[args.recipename]) return 0