From patchwork Sun Sep 6 21:01:59 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97422 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 890C6C79F99 for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-65-227.siemens.flowmailer.net (mta-65-227.siemens.flowmailer.net [185.136.65.227]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.21346.1788728596370200145 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=B/lqKg85; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.227, mailfrom: fm-1329275-20260906210313f7c32f03250002075d-0hvwa_@rts-flowmailer.siemens.com) Received: by mta-65-227.siemens.flowmailer.net with ESMTPSA id 20260906210313f7c32f03250002075d for ; Sun, 06 Sep 2026 23:03:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=2p7gAouxJn7TOWyp36zRSZg68tD3dgL3mff1NdheCuM=; b=B/lqKg85bwLbCesJOx/MpjyJK3I2GlH1TXLwXKZ3H1cBkG49lkuhe7bSdSNXuEjE92Li8d uyX+MMSa7EHMwgEWM6CHUTvUljWkXBknTG81RiXGpxe6YkfIqc01qlH+Jp2bpv+4lpejLiwz bHLHPp2WZQQ5P8Xujg+WwlthZEMzxqkMZUEpQeMmfQ7Nk3tCDu0to42R2HUr+FdpAC/ibjJ7 06nS+MCnD6ZNdJEcYRgZw2uN8bKO/tErPx5k76aE7jh9Yjeskbe8DkZKxDp74cYypNvT0tGZ XY79H5Df9W1fyjNV7F4GMzZxTJJ5hKVcDlWx3Bs42TDJ3zJF2cOYO0eA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 1/9] devtool: ide-sdk: fix GDB loading stale libs instead of recipe's own build Date: Sun, 6 Sep 2026 23:01:59 +0200 Message-ID: <20260906210307.2793974-2-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245214 From: Adrian Freihofer Setting GDB's sysroot to the recipe's D (image/) directory is often not enough: D only contains "usr/lib", but the target reports merged-usr paths like "/lib/libfoo.so.0", so the sysroot lookup fails and GDB falls back to solib-search-path, resolving the library from the full image's rootfs-dbg/rootfs instead. Recipes that install libraries outside the standard libdir hit this on every rebuild, silently debugging with stale symbols from the last full image build. Confirmed against gdb-17.2 gdb/solib.c (solib_find_1()) by capturing the GDB MI trace of an attach session and cross-checking against that code. Fix: add RecipeModified._find_elf_dirs(), which walks D and returns every directory containing an ELF file, and prepend those directories to additionalSOLibSearchPath, ahead of the rootfs-dbg/rootfs entries, in every generated launch config. Since with usrmerge in DISTRO_FEATURES (the default) base_libdir and libdir resolve to the same path, this can introduce literal duplicates in the list; dedupe with list(dict.fromkeys(...)) instead of a set, since the order of the list is essential: it defines GDB's solib-search-path priority. Also extend the launch.json oe-selftest assertions to check that the first additionalSOLibSearchPath entry is the recipe's own image (D) directory, not rootfs-dbg. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/devtool.py | 5 ++ scripts/lib/devtool/ide_sdk.py | 62 +++++++++++++++++-------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index 3e0eb7948f..de59feadb8 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -3591,6 +3591,11 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests): so_paths = config.get("additionalSOLibSearchPath", []) self.assertIn("/.debug", so_paths, f"Configuration '{config['name']}' should include debug symbol paths") self.assertIn("/rootfs-dbg/", so_paths, f"Configuration '{config['name']}' should include rootfs-dbg paths") + # The recipe's own D/usr/lib must come first, so GDB's solib-search-path basename fallback + # prefers freshly rebuilt libraries over a stale rootfs-dbg/rootfs copy from the last full image build. + first_so_path = so_paths.split(":", 1)[0] + self.assertIn("/image/", first_so_path, f"Configuration '{config['name']}' first SO lib search path should be the recipe's own image dir: {first_so_path}") + self.assertNotIn("rootfs-dbg", first_so_path, f"Configuration '{config['name']}' first SO lib search path should not be rootfs-dbg: {first_so_path}") # Verify source file mappings source_map = config.get("sourceFileMap", {}) diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py index 9225546c5e..6558137134 100755 --- a/scripts/lib/devtool/ide_sdk.py +++ b/scripts/lib/devtool/ide_sdk.py @@ -827,27 +827,50 @@ class RecipeModified: return True return False + @staticmethod + def _find_elf_dirs(root): + """Return every directory under root that contains an ELF file""" + elf_dirs = [] + for dirpath, _dirnames, filenames in os.walk(root): + for filename in filenames: + file_path = os.path.join(dirpath, filename) + if os.path.islink(file_path): + continue + try: + with open(file_path, 'rb') as elf_file: + is_elf = elf_file.read(4) == b'\x7fELF' + except OSError: + continue + if is_elf: + elf_dirs.append(dirpath) + break + return elf_dirs + def solib_search_path(self, image): - """Search for debug symbols in the rootfs and rootfs-dbg + """Search for debug symbols - The debug symbols of shared libraries which are provided by other packages - are grabbed from the -dbg packages in the rootfs-dbg. + This recipe's own D is searched (for ELF files, wherever they are + installed), so that this recipe's freshly rebuilt libraries take + precedence over any stale copy from the last full image build. + "set sysroot D" alone cannot achieve this: GDB's sysroot (tested with + GDB 17.2) only matches "/lib" paths, but D usually only contains + "usr/lib" (no top-level "lib" symlink), so it falls back to + solib-search-path's basename matching instead. This also covers + libraries not installed into the standard libdirs. - But most cross debugging tools like gdb, perf, and systemtap need to find - executable/library first and through it debuglink note find corresponding - symbols file. Therefore the library paths from the rootfs are added as well. - - Note: For the devtool modified recipe compiled from the IDE, the debug - symbols are taken from the unstripped binaries in the image folder. - Also, devtool deploy-target takes the files from the image folder. - debug symbols in the image folder refer to the corresponding source files - with absolute paths of the build machine. Debug symbols found in the - rootfs-dbg are relocated and contain paths which refer to the source files - installed on the target device e.g. /usr/src/... + D is listed first, ahead of rootfs-dbg/rootfs. For every other + library, i.e. one provided by another package, debug symbols are + grabbed from the -dbg packages in rootfs-dbg. gdb, perf, and + systemtap need to find the executable/library itself first, and + through its debuglink find the symbols file, so the plain rootfs + paths are added too. """ base_libdir = self.base_libdir.lstrip('/') libdir = self.libdir.lstrip('/') - so_paths = [ + # dedupe (e.g. base_libdir = libdir) while keeping the order (using dict instead of set) + so_paths = dict.fromkeys([ + # This recipe's own rebuilt libraries/plugins, ahead of rootfs-dbg/rootfs. + *self._find_elf_dirs(self.d), # debug symbols for package_debug_split_style: debug-with-srcpkg or .debug os.path.join(image.rootfs_dbg, base_libdir, ".debug"), os.path.join(image.rootfs_dbg, libdir, ".debug"), @@ -858,13 +881,12 @@ class RecipeModified: # With image-combined-dbg.bbclass the binaries are copied into rootfs-dbg os.path.join(image.rootfs_dbg, base_libdir), os.path.join(image.rootfs_dbg, libdir), - # Without image-combined-dbg.bbclass the binaries are only in rootfs. - # Note: Stepping into source files located in rootfs-dbg does not - # work without image-combined-dbg.bbclass yet. + # Without image-combined-dbg.bbclass the binaries are only in rootfs + # (stepping into rootfs-dbg sources needs image-combined-dbg.bbclass) os.path.join(image.rootfs, base_libdir), os.path.join(image.rootfs, libdir) - ] - return so_paths + ]) + return list(so_paths) def solib_search_path_str(self, image): """Return a : separated list of paths usable by GDB's set solib-search-path""" From patchwork Sun Sep 6 21:02:00 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97419 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 33FE1C79F9E for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.21705.1788728596288320424 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=dMDwqqrf; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-2026090621031396245b512800020772-gbvfmb@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 2026090621031396245b512800020772 for ; Sun, 06 Sep 2026 23:03:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=zE4ceVg4o08oskoLrbtOzvnclw8gdzi+brH/TCw08z4=; b=dMDwqqrfSkm1cfXolGAhb17fu/Ds5hYWQc1ihv1FhOmJNGwCOnnEKOXKh8HS3IzVoXEShv uWzKo7mOoEVbn4qfjZ/mtUEMSPh1uKpdq7qxg7EwejmjgQPYchbcf2OXvJ7jedhn47bNR++i 8Rnxci9Krcz4CcX02drMVJosK5YuivpZ1xJmm6qlgQnuf/sQ0I/A+1WkmekS2GUfllI1mkDi hqxOLNK35tXjag5+N7TFSje/iOz49qHw6Qre7FAVFCmbLlQEVMkTwgpK1fyQ6+P0YhbLFtj1 tUjVg2qs+zFWrXyllKlR5FG9H6pf6ifPRiPhqZsnFj++/PVxFw+86okg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 2/9] oe-selftest: devtool ide-sdk: do not guess the slirp SSH port Date: Sun, 6 Sep 2026 23:02:00 +0200 Message-ID: <20260906210307.2793974-3-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245217 From: Adrian Freihofer Falling back to a hardcoded 2222 hides the case where runqemu did not report an ip:port pair: the test would then keep running against a port that nothing listens on and fail somewhere further down. Assert the port instead, so the failure points at its actual cause. --- meta/lib/oeqa/selftest/cases/devtool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index de59feadb8..3a407a5162 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -3991,7 +3991,8 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests): with runqemu(testimage, runqemuparams="nographic slirp") as qemu: slirp_host = qemu.ip - slirp_port = qemu.port or '2222' + self.assertIsNotNone(qemu.port, 'No SSH port for the slirp target') + slirp_port = qemu.port # Re-run ide-sdk with the actual slirp address; image is already built. bitbake_sdk_cmd = ( From patchwork Sun Sep 6 21:02:01 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97420 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F2AAC79FA7 for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.21704.1788728596080129521 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=EjOGhR/t; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-20260906210313275b440e8e000207ba-3eftw_@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 20260906210313275b440e8e000207ba for ; Sun, 06 Sep 2026 23:03:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=6AlUM29nFpKNoSOB76K+XEvJKIZL8ujuRTWdSXT4bjQ=; b=EjOGhR/thKX5ZmSsXT0+GomL26y9TGb84BqGmzd4bNUTZvhTB2EXU7BXbjl/w61fQR+sLL VFCA61J8lsZMCa6ttoH1zUqIeW5op1Mu5XQCGaG1dNZJIs6rjxOzLpUeVPz8TNb7su+/J4Uq UPuz2R7oqnAQ5ux/tH66A2T0MT0TpOwjjgNB0w2IFbw47sWgLJ080srCh4Y4LsvJw56zkoPk u5btp1f4r0sHODE/n6n7TkuSnar/d4VjlXaLZ/dQjO5YS4yYcoQB/pxUfvF09HeR6rZQTG1k YXyBtokL2OQqRcm6dK4Yq/7re1e7duX6ZdiSUQf8vMjvsKTpERM5TWPg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 3/9] devtool: ide-sdk: pre-select attach process with processFilter Date: Sun, 6 Sep 2026 23:02:01 +0200 Message-ID: <20260906210307.2793974-4-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245218 From: Adrian Freihofer The ATTACH launch config now uses the extended-remote protocol, which makes cppdbg show a picker listing every process running on the target. In modified-recipe mode the binary to attach to is already known, so the picker is only extra clicking, and on a busy target it can make finding the right process among unrelated ones tedious. Set "processFilter" to a regex matching the deployed binary's path so cppdbg pre-selects it instead of showing the full process list. This is a recent cpptools feature; until it ships in a released cpptools, cppdbg silently ignores it and falls back to showing the full unfiltered process list. Require cpptools version that supports processFilter https://github.com/microsoft/vscode-cpptools/pull/14684 Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/devtool.py | 1 + scripts/lib/devtool/ide_plugins/ide_code.py | 1 + 2 files changed, 2 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index 3a407a5162..a4b7a83094 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -3569,6 +3569,7 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests): # from the process instead of killing it. self.assertTrue(config.get("useExtendedRemote"), f"Configuration '{config['name']}' should use useExtendedRemote") self.assertNotIn("cwd", config, f"Configuration '{config['name']}' should not set cwd in attach mode") + self.assertTrue(config.get("processFilter"), f"Configuration '{config['name']}' should use processFilter") else: self.fail(f"Configuration '{config['name']}' has unexpected request type: {config['request']}") diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index 937c63a4a5..6effbac654 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -387,6 +387,7 @@ class IdeVSCode(IdeBase): # this configuration is generated. Stopping the session detaches # from the process instead of killing it. launch_config["useExtendedRemote"] = True + launch_config["processFilter"] = "(^| )%s( |$)" % cross_debug_config.binary.binary_path else: # cwd, environment and externalConsole configure the process the # debugger starts, they are not part of the attach schema. From patchwork Sun Sep 6 21:02:02 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97425 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2444C79FA9 for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-64-227.siemens.flowmailer.net (mta-64-227.siemens.flowmailer.net [185.136.64.227]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.21706.1788728596337596583 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=a+1TNtrT; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-1329275-20260906210313b6cfbc5076000207a5-h4ctlc@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 20260906210313b6cfbc5076000207a5 for ; Sun, 06 Sep 2026 23:03:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=pS11joJ71i5fICEMrki89ZNucs3an6B+OJrT7MzQYDM=; b=a+1TNtrToVhvr6jaa7cv9aCFRxcyYjDRBQ1INISdyTogkagPsHzR47LEsZ/OjluP9q+CYP gqEhATwLjsGL6gcfadwr+GsdA76RXVBP9fXaDAGZ6Vaxfizkxug+sEc/q1xHwtjC2yYs8YUx KVbhmhGkRxpLN9SHM03vlndonPAduwn6tZXrcELtInaoePc4usSNby5NrUDEMmxAzt/AmYeB Nyzfla74BpVeYtkf79XyJZpd7AYDkEmb/FNvV9/mbvjdqipNhnSzDMmM0cf9twEDhZAlYxXy XXcRlQ7XJM6hYxYUf9bTSiFTY4MQOdA16CtOitHLjCLZUwdAUa9UBtpQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 4/9] oe-selftest: tinfoil: test prepared task runner Date: Sun, 6 Sep 2026 23:02:02 +0200 Message-ID: <20260906210307.2793974-5-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245219 From: Adrian Freihofer Add shell and Python marker tasks to pseudo-pyc-test, with and without fakeroot. Build the tasks normally to prepare their dependencies, remove their markers, then rerun them through Tinfoil's run_prepared_task() API. This verifies that a prepared task can be rerun through BitBake's worker path without resolving its dependencies, including shell and Python task execution within and outside a pseudo session as needed by devtool ide-sdk. Signed-off-by: Adrian Freihofer --- .../pseudo-pyc-test/pseudo-pyc-test.bb | 45 ++++++++++++++ meta/lib/oeqa/selftest/cases/tinfoil.py | 60 +++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/meta-selftest/recipes-test/pseudo-pyc-test/pseudo-pyc-test.bb b/meta-selftest/recipes-test/pseudo-pyc-test/pseudo-pyc-test.bb index 12dc91a8f3..f6b31b63cd 100644 --- a/meta-selftest/recipes-test/pseudo-pyc-test/pseudo-pyc-test.bb +++ b/meta-selftest/recipes-test/pseudo-pyc-test/pseudo-pyc-test.bb @@ -13,3 +13,48 @@ python do_install() { import pseudo_pyc_test2 print(pseudo_pyc_test2.STRING) } + +TINFOIL_TEST_MARKER_DIR = "${TMPDIR}/tinfoil-prepared-task" +TINFOIL_TEST_MARKER_VALUE ?= "" + +write_tinfoil_shell_marker() { + mkdir -p ${TINFOIL_TEST_MARKER_DIR} + printf '%s%s' "$1" "${TINFOIL_TEST_MARKER_VALUE}" > ${TINFOIL_TEST_MARKER_DIR}/"$1" +} + +do_tinfoil_dep() { + write_tinfoil_shell_marker dep +} +addtask tinfoil_dep + +do_tinfoil_shell() { + write_tinfoil_shell_marker shell +} +addtask tinfoil_shell after do_tinfoil_dep + +do_tinfoil_shell_fakeroot() { + write_tinfoil_shell_marker shell-fakeroot +} +do_tinfoil_shell_fakeroot[fakeroot] = "1" +do_tinfoil_shell_fakeroot[depends] += "virtual/fakeroot-native:do_populate_sysroot" +addtask tinfoil_shell_fakeroot after do_tinfoil_dep + +def write_tinfoil_marker(d, name): + import os + + marker_dir = d.getVar('TINFOIL_TEST_MARKER_DIR') + os.makedirs(marker_dir, exist_ok=True) + with open(os.path.join(marker_dir, name), 'w') as marker: + marker.write(name + d.getVar('TINFOIL_TEST_MARKER_VALUE')) + +python do_tinfoil_python() { + write_tinfoil_marker(d, 'python') +} +addtask tinfoil_python after do_tinfoil_dep + +python do_tinfoil_python_fakeroot() { + write_tinfoil_marker(d, 'python-fakeroot') +} +do_tinfoil_python_fakeroot[fakeroot] = "1" +do_tinfoil_python_fakeroot[depends] += "virtual/fakeroot-native:do_populate_sysroot" +addtask tinfoil_python_fakeroot after do_tinfoil_dep diff --git a/meta/lib/oeqa/selftest/cases/tinfoil.py b/meta/lib/oeqa/selftest/cases/tinfoil.py index 21c8686b2a..d8009eddfe 100644 --- a/meta/lib/oeqa/selftest/cases/tinfoil.py +++ b/meta/lib/oeqa/selftest/cases/tinfoil.py @@ -6,11 +6,14 @@ import os import re +import shutil import time import logging +import uuid import bb.tinfoil from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake class TinfoilTests(OESelftestTestCase): """ Basic tests for the tinfoil API """ @@ -77,6 +80,63 @@ class TinfoilTests(OESelftestTestCase): localdata.setVar('PN', 'hello') self.assertEqual('hello', localdata.getVar('BPN')) + def test_run_prepared_task(self): + """Verify run_prepared_task() runs only the requested task, not its + dependency. + + pseudo-pyc-test's do_tinfoil_* tasks depend on do_tinfoil_dep; both + write a marker file containing the task name plus the current value + of TINFOIL_TEST_MARKER_VALUE. A normal bitbake build is expected to + update both the dependency's and the requested tasks' markers to a + new value. Calling run_prepared_task() with another new value must + update only the requested tasks' markers, leaving do_tinfoil_dep's + marker at the value written by the earlier bitbake build. + """ + marker_dir = os.path.join( + self.builddir, 'tmp', 'tinfoil-prepared-task') + shutil.rmtree(marker_dir, ignore_errors=True) + self.track_for_cleanup(marker_dir) + + tasks = ('shell', 'shell_fakeroot', 'python', 'python_fakeroot') + + # Use a fresh, random value each run so the tasks' signatures change + # and bitbake can't skip them as "up to date" from a previous run. + value1 = uuid.uuid4().hex + bitbake(' '.join('pseudo-pyc-test:do_tinfoil_%s' % task + for task in tasks), + postconfig='TINFOIL_TEST_MARKER_VALUE = "%s"\n' % value1) + + # do_tinfoil_dep is a dependency of all the tasks above, so a normal + # bitbake build is expected to have run it too, with the same value. + with open(os.path.join(marker_dir, 'dep')) as marker: + self.assertEqual(marker.read(), 'dep' + value1) + for task in tasks: + marker_name = task.replace('_', '-') + with open(os.path.join(marker_dir, marker_name)) as marker: + self.assertEqual(marker.read(), marker_name + value1) + + with bb.tinfoil.Tinfoil() as tinfoil: + tinfoil.prepare(config_only=False, quiet=2) + # A distinct value per call proves each run_prepared_task() + # invocation re-reads the variable rather than reusing a value + # cached from an earlier call in this loop. + values2 = {task: uuid.uuid4().hex for task in tasks} + for task in tasks: + tinfoil.run_command('setVariable', 'TINFOIL_TEST_MARKER_VALUE', values2[task]) + tinfoil.run_prepared_task( + 'pseudo-pyc-test', 'do_tinfoil_%s' % task) + + # The requested tasks must have re-run and picked up their own value + for task in tasks: + marker_name = task.replace('_', '-') + with open(os.path.join(marker_dir, marker_name)) as marker: + self.assertEqual(marker.read(), marker_name + values2[task]) + + # ...but run_prepared_task() must not have run do_tinfoil_dep, so its + # marker should still hold the value written by the earlier bitbake build + with open(os.path.join(marker_dir, 'dep')) as marker: + self.assertEqual(marker.read(), 'dep' + value1) + # The config_data API to parse_recipe_file is used by: # layerindex-web layerindex/update_layer.py def test_parse_recipe_custom_data(self): From patchwork Sun Sep 6 21:02:03 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97421 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4226CC79FA1 for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-64-226.siemens.flowmailer.net (mta-64-226.siemens.flowmailer.net [185.136.64.226]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.21707.1788728596369955799 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=eFCx9aet; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.226, mailfrom: fm-1329275-202609062103138d99fd24580002077d-imvcjf@rts-flowmailer.siemens.com) Received: by mta-64-226.siemens.flowmailer.net with ESMTPSA id 202609062103138d99fd24580002077d for ; Sun, 06 Sep 2026 23:03:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=NuTHXMVx56kgah/008ySd9suXzyg1Tg8cD9ZNzEJ8lA=; b=eFCx9aet65IwpY6h700EqTGpPUgdhtbWgHWNe4YeZENlQtLp+e9MTXF+hufDSso2t2v68p 9IZgeQaP14xHFZr+pADCDLkWdBLc/BD3LgGZJabVB0RKkLD8vU+IMvZ/S6aRFTp1dS68bn7b gxxOA1oVxl1m4b7hyiscukybxAtuxVTReaSmv6E0AY0qpmbf+uzDvrSFpQwiPXFKWN+AtWux mSpCvNzAn1K/DgqXETd2JPiE/fp0emO/hTihh9NxEr81rbGQv0hYYzUaFwy72o9azCffOCXI l8xuAXIvfineVFzo55nmjtm/HvnF31YglKtWdxXa2TZGgTMwdrvWAbHQ==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 5/9] devtool: ide-sdk: run do_install through BitBake Date: Sun, 6 Sep 2026 23:02:03 +0200 Message-ID: <20260906210307.2793974-6-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245216 From: Adrian Freihofer Generate a Python install-task runner for the IDE SDK environment. It prepares Tinfoil normally, then invokes run_prepared_task() to rerun do_install through BitBake's worker path before deploying the result. The IDE owns configure, compile, and unit-test steps in the modified source tree. At deployment time, resolving task dependencies could rerun those steps, discard the IDE's build results, and add unnecessary delay. The prepared-task runner therefore executes only do_install after BitBake has prepared its prerequisites. This supports shell and Python task bodies and lets BitBake establish the fakeroot environment when the task requires pseudo. Signed-off-by: Adrian Freihofer --- scripts/lib/devtool/ide_sdk.py | 42 +++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py index 6558137134..0b76aa448b 100755 --- a/scripts/lib/devtool/ide_sdk.py +++ b/scripts/lib/devtool/ide_sdk.py @@ -1421,26 +1421,32 @@ class RecipeModified: self.fakerootcmd, self.fakerootenv)) return self.write_script(cmd_lines, 'deploy_target') + def gen_install_task_script(self): + """Generate a script which runs do_install through BitBake.""" + cmd_lines = ['#!%s' % sys.executable] + if self.cmd_compile: + cmd_lines += ['import subprocess', + 'subprocess.run(%s, cwd=%r, shell=True, check=True)' % + (repr(self.cmd_compile), self.real_srctree)] + cmd_lines += ['import os', + 'import sys', + 'sys.path.insert(0, %r)' % os.path.realpath( + os.path.join(self.bitbakepath, '..', 'lib')), + 'import bb.tinfoil', + 'os.chdir(%r)' % self.topdir, + 'tinfoil = bb.tinfoil.Tinfoil()', + 'try:', + ' tinfoil.prepare(config_only=False, quiet=2)', + ' tinfoil.run_prepared_task(%r, "do_install")' % self.pn, + 'finally:', + ' tinfoil.shutdown()'] + return self.write_script(cmd_lines, 'bb_run_do_install') + def gen_install_deploy_script(self, args): """Generate a script which does install and deploy""" - cmd_lines = ['#!/bin/sh'] - - # Save the original command-line args before 'set' overwrites $@ - cmd_lines.append('_args="$@"') - # . oe-init-build-env $BUILDDIR $BITBAKEDIR - # Using 'set' to pass the build directory to oe-init-build-env in sh syntax - cmd_lines.append('cd "%s" || { echo "cd %s failed"; exit 1; }' % ( - self.oe_init_dir, self.oe_init_dir)) - cmd_lines.append('set %s %s' % (self.topdir, self.bitbakepath.rstrip('/bin'))) - cmd_lines.append('. "%s" || { echo ". %s %s failed"; exit 1; }' % ( - self.oe_init_build_env, self.oe_init_build_env, self.topdir)) - - # bitbake -c install - cmd_lines.append( - 'bitbake %s -c install --force || { echo "bitbake %s -c install --force failed"; exit 1; }' % (self.bpn, self.bpn)) - - # Self contained devtool deploy-target - use saved args, not $@ (overwritten by 'set') - cmd_lines.append(self.gen_deploy_target_script(args) + ' $_args') + cmd_lines = ['#!/bin/sh -e'] + cmd_lines.append(self.gen_install_task_script()) + cmd_lines.append(self.gen_deploy_target_script(args) + ' "$@"') return self.write_script(cmd_lines, 'install_and_deploy') From patchwork Sun Sep 6 21:02:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97426 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA41EC79FAA for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-64-225.siemens.flowmailer.net (mta-64-225.siemens.flowmailer.net [185.136.64.225]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.21345.1788728596288271985 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=XDgm+5kh; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.225, mailfrom: fm-1329275-20260906210313ab403b38d0000207a1-fste2z@rts-flowmailer.siemens.com) Received: by mta-64-225.siemens.flowmailer.net with ESMTPSA id 20260906210313ab403b38d0000207a1 for ; Sun, 06 Sep 2026 23:03:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=5aBTMJCbJTqe33Z4Hf1g1etper4QEr6My+8fwQ3yZRs=; b=XDgm+5kh9dfgQMC9QgTMb1N4BFAidnjwyH/XjGD0K07jzIrLU/dyrZOh7FWR9BzKII5sbC vpIjsqBgQXflgxzSAnAxw2Q2gn5AajBt/vYBaexq03jrQzEQllsl1Sv0v8an8xtOpaANc88U 3X79TrlpZSFzDg82g1+p+19ysqhqzPQcKrg8fi75G7w2/tJFGm/sIQIi11wL/RCgOkF/fRs1 SopM2WnmVxEX2uPiRQjEG225d9HT7XagrCt//sybS3Oq93T+1IPAv0ACVo4O9UncB9tjmhvy oc6u/UXkP0yuXLwwIwafdfNW9MuUaSbU7PwHj2038mxvtkzcdFQm86RA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 6/9] oe-selftest: devtool ide-sdk: test install task Date: Sun, 6 Sep 2026 23:02:04 +0200 Message-ID: <20260906210307.2793974-7-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245215 From: Adrian Freihofer Verify that the ide-sdk setup generates the do_install task script and that the script runs successfully. This covers the prepared-task runner used by the IDE deployment workflow without requiring Qemu. Replace the ad-hoc dependsOn handling in _verify_launch_config() with a new helper that mirrors VS Code's task dependency resolution and execution order. This ensures that the selftest runs the same sequence of tasks as VS Code would, including compile and install/deploy prerequisites, before starting the debug server. This also aligns the gdb and lldb selftest paths to avoid behavior drift and improve test reliability. Signed-off-by: Adrian Freihofer --- meta/lib/oeqa/selftest/cases/devtool.py | 86 ++++++++++++++++++++----- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index a4b7a83094..cf7b97fdda 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -3043,7 +3043,7 @@ class DevtoolIdeSdkTests(DevtoolBase): """Verify the scripts referred by the tasks.json file are fine. This function does not depend on Qemu. Therefore it verifies the scripts - exists and the delete step works as expected. But it does not try to + exists and the install step works as expected. But it does not try to deploy to Qemu. """ recipe_id, recipe_id_pretty = self._get_recipe_ids(recipe_name) @@ -3061,6 +3061,11 @@ class DevtoolIdeSdkTests(DevtoolBase): i_and_d_script_path = os.path.join( self._workspace_scripts_dir(recipe_name), i_and_d_script) self.assertExists(i_and_d_script_path) + install_script = 'bb_run_do_install_' + recipe_id + install_script_path = os.path.join( + self._workspace_scripts_dir(recipe_name), install_script) + self.assertExists(install_script_path) + runCmd(install_script_path, cwd=tempdir, output_log=self._cmd_logger) deploy_script_path = os.path.join( self._workspace_scripts_dir(recipe_name), 'deploy_target_' + recipe_id) @@ -3295,6 +3300,60 @@ class DevtoolIdeSdkTests(DevtoolBase): self.assertEqual(actual_group, group, msg="%s not owned by group %s: got %s" % (conf_file, group, actual_group)) + def _run_vscode_task_with_dependencies(self, tempdir, task_label, run_main_task=True): + """Run a VS Code shell task and its dependsOn chain. + + The helper mirrors VS Code task dependency ordering for selftests, so + preLaunchTask prerequisites (e.g. compile and do_install/deploy tasks) + run before the debug server task. + """ + tasks_path = os.path.join(tempdir, '.vscode', 'tasks.json') + self.assertExists(tasks_path, 'tasks.json not found at %s' % tasks_path) + + with open(tasks_path) as tasks_j: + tasks_d = json.load(tasks_j) + + task_by_label = { + task.get('label'): task + for task in tasks_d.get('tasks', []) + if task.get('label') + } + self.assertIn(task_label, task_by_label, + "Task '%s' not found in tasks.json" % task_label) + + ran = set() + + def run_task(label, execute_task): + if label in ran: + return + + task = task_by_label[label] + deps = task.get('dependsOn', []) + if isinstance(deps, str): + deps = [deps] + + for dep in deps: + self.assertIn(dep, task_by_label, + "DependsOn task '%s' not found in tasks.json" % dep) + run_task(dep, True) + + if execute_task: + command = task.get('command') + if command: + args = task.get('args', []) + if not isinstance(args, list): + args = [args] + task_cmd = [command] + [str(arg) for arg in args] + + task_cwd = task.get('options', {}).get('cwd', tempdir) + if isinstance(task_cwd, str): + task_cwd = task_cwd.replace('${workspaceFolder}', tempdir) + runCmd(task_cmd, cwd=task_cwd, output_log=self._cmd_logger) + + ran.add(label) + + run_task(task_label, run_main_task) + class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests): @@ -3786,21 +3845,10 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests): (task for task in tasks if task["label"] == prelaunch_task_name), None) self.assertIsNotNone(prelaunch_task, f"PreLaunchTask '{prelaunch_task_name}' not found in tasks.json") - # Find the dependsOn task if exists (install and deploy-target) - if "dependsOn" in prelaunch_task: - depends_task_names = prelaunch_task["dependsOn"] - for depends_task_name in depends_task_names: - depends_task = next( - (task for task in tasks if task["label"] == depends_task_name), None) - self.assertIsNotNone(depends_task, f"DependsOn task '{depends_task_name}' not found in tasks.json") - # For simplicity, we assume the dependsOn task is a prerequisite and does not affect the main command - self.logger.debug(f"PreLaunchTask '{prelaunch_task_name}' depends on '{depends_task_name}'") - - # Extract command details from dependsOn task - depends_task_command = depends_task["command"] - depends_task_args = depends_task.get("args", []) - self.logger.debug(f"Would execute dependsOn task: {depends_task_command} {' '.join(depends_task_args)}") - runCmd(f"{depends_task_command} {' '.join(depends_task_args)}", output_log=self._cmd_logger) + # Execute preLaunchTask prerequisites exactly like VS Code dependsOn + # handling, but keep starting the debug server in this method. + self._run_vscode_task_with_dependencies( + tempdir, prelaunch_task_name, run_main_task=False) # Verify task structure and extract command details self.assertEqual(prelaunch_task["type"], "shell", f"Task '{prelaunch_task_name}' should be shell type") @@ -4569,6 +4617,12 @@ class DevtoolIdeSdkClangTests(DevtoolIdeSdkTests): self.assertIsNotNone(prelaunch_task, "preLaunchTask '%s' not found in tasks.json" % prelaunch_task_name) + # Run compile/install/deploy prerequisites exactly as VS Code would, + # but keep starting the debug server itself in this method so we can + # retain explicit readiness handling and diagnostics. + self._run_vscode_task_with_dependencies( + tempdir, prelaunch_task_name, run_main_task=False) + # Extract the SSH command and start lldb-server on the target task_command = prelaunch_task["command"] task_args = prelaunch_task["args"] From patchwork Sun Sep 6 21:02:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97424 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C65E7C79FAB for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-65-228.siemens.flowmailer.net (mta-65-228.siemens.flowmailer.net [185.136.65.228]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.21343.1788728596231378527 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=I+6ck53o; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.228, mailfrom: fm-1329275-20260906210313b3886ac7ab000207d2-ysn8hg@rts-flowmailer.siemens.com) Received: by mta-65-228.siemens.flowmailer.net with ESMTPSA id 20260906210313b3886ac7ab000207d2 for ; Sun, 06 Sep 2026 23:03:14 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=+VkBOLln7N50XDcExWSaiDHl8S8HyFAp6IcJgrUfoxo=; b=I+6ck53oZi/pKoLFoAFe6vc78YVK4DBQ1NWKHWKkD7kqCcDTXnF7c/XHdtEWx2x8XmX8x1 +sqFGZmH3pXu178/fpat4WButNb2zHKXvPqVPbPKQCrF/jQG5ysVRMo0cVjCku0P3htLepth DazpnLQl31g6sa94fe9/JsHgvYOzh6vbYHNTN57kySKay1rGph9AhIQu5redWItPmzRp7Yk5 /RQ2ZwGEyZdaRhwckmh2Q12+mrFXk1gEF+SnVr32GXsXma1GHCHIVEHpOj19szB3kt8QwpQ/ 4tUPLktOxHA6hlCRf1x91jg+4QdT9F/BvpqEgJNDErXT6qx8rtRJBSAg==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 7/9] runqemu-export-rootfs: set PSEUDO_INCLUDE_PATHS for unfsd Date: Sun, 6 Sep 2026 23:02:05 +0200 Message-ID: <20260906210307.2793974-8-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245212 From: Adrian Freihofer pseudo inverted its path-matching logic some time ago: when set, PSEUDO_INCLUDE_PATHS acts as an ownership-tracking allowlist, and anything outside it silently falls through to real chown()/chmod() instead of being recorded by pseudo. This script never set it, so an inherited restrictive value could leave files touched by unfsd on behalf of NFS clients with wrong ownership. Since this script only ever touches NFS_EXPORT_DIR, setting PSEUDO_INCLUDE_PATHS to it is enough. Signed-off-by: Adrian Freihofer --- scripts/runqemu-export-rootfs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/runqemu-export-rootfs b/scripts/runqemu-export-rootfs index 6a8acd0d5a..150513bc50 100755 --- a/scripts/runqemu-export-rootfs +++ b/scripts/runqemu-export-rootfs @@ -56,6 +56,8 @@ MOUNTPID=~/.runqemu-sdk/mount$NFS_INSTANCE.pid PSEUDO_OPTS="-P $OECORE_NATIVE_SYSROOT/usr" PSEUDO_LOCALSTATEDIR="$NFS_EXPORT_DIR/../$(basename $NFS_EXPORT_DIR).pseudo_state" export PSEUDO_LOCALSTATEDIR +PSEUDO_INCLUDE_PATHS="$NFS_EXPORT_DIR" +export PSEUDO_INCLUDE_PATHS if [ ! -d "$PSEUDO_LOCALSTATEDIR" ]; then echo "Error: $PSEUDO_LOCALSTATEDIR does not exist." From patchwork Sun Sep 6 21:02:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97427 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3C4EBC79FAC for ; Sun, 6 Sep 2026 21:03:24 +0000 (UTC) Received: from mta-64-228.siemens.flowmailer.net (mta-64-228.siemens.flowmailer.net [185.136.64.228]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.21342.1788728596220245324 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=DGZTPYNd; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.228, mailfrom: fm-1329275-20260906210314ed93242e4400020788-jzs8lb@rts-flowmailer.siemens.com) Received: by mta-64-228.siemens.flowmailer.net with ESMTPSA id 20260906210314ed93242e4400020788 for ; Sun, 06 Sep 2026 23:03:14 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=y4/o320ZnJGz8ndz7TqwxLbxosK772fsbOZ/LTHTpQ4=; b=DGZTPYNdY+VzgeaAT08KV7hG3vBwHjkuHdUdSigJcw615/DIzjJH+AQ8LjEB2VCb3mvrRm TG2/TcZTXORLhMyJn0SfcLpObxq1XF0RRQ+TQQpgpsqKoZcPJ6BXlZDXkGZJl0U2GnZoKVAS VWYY+Sf7m21l7OgN4EtWBQ4Rebj3R+O1Tf1tR4F82jahsLVw033QzroILAi0yL2VA7YXyXU9 /CG8wIGJsrV0SZrWOz+XfIfNjXQihWHKsuO1EOSc7YPy+/bSpyL+r3QKpAgVhXiF9G5kuYVc ls+xTxGs9CK8DCHbm7/0ELkLe4RTnwCGRRC4PLnNi2Wowr++NzpZKO0w==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 8/9] devtool: deploy: make pseudo calls independent of bitbake.conf Date: Sun, 6 Sep 2026 23:02:06 +0200 Message-ID: <20260906210307.2793974-9-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:24 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245211 From: Adrian Freihofer Relying on bitbake.conf's global PSEUDO_INCLUDE_PATHS to cover the stripped-copy directory is fragile, and will only get more fragile as devtool deploy learns to deploy to more kinds of places. Add an env_overrides parameter to exec_fakeroot_no_d() and use it to state PSEUDO_INCLUDE_PATHS explicitly for each pseudo call in the --strip path, so bitbake.conf no longer needs a devtool-specific entry. Signed-off-by: Adrian Freihofer --- meta/conf/bitbake.conf | 2 +- scripts/lib/devtool/__init__.py | 11 ++++++++++- scripts/lib/devtool/deploy.py | 11 +++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/meta/conf/bitbake.conf b/meta/conf/bitbake.conf index 63d84cf37b..a21223e216 100644 --- a/meta/conf/bitbake.conf +++ b/meta/conf/bitbake.conf @@ -752,7 +752,7 @@ SRC_URI = "" PSEUDO_LOCALSTATEDIR ?= "${WORKDIR}/pseudo/" PSEUDO_PASSWD ?= "${STAGING_DIR_TARGET}:${PSEUDO_SYSROOT}" PSEUDO_SYSROOT = "${COMPONENTS_DIR}/${BUILD_ARCH}/pseudo-native" -PSEUDO_INCLUDE_PATHS = "/proc,${WORKDIR}/image,${WORKDIR}/package,${WORKDIR}/rootfs,${WORKDIR}/sstate-build-package/,${WORKDIR}/sstate-install-package/,${WORKDIR}/pkgdata,${WORKDIR}/minidebuginfo,${WORKDIR}/devtool-deploy-target-stripped" +PSEUDO_INCLUDE_PATHS = "/proc,${WORKDIR}/image,${WORKDIR}/package,${WORKDIR}/rootfs,${WORKDIR}/sstate-build-package/,${WORKDIR}/sstate-install-package/,${WORKDIR}/pkgdata,${WORKDIR}/minidebuginfo" export PSEUDO_DISABLED = "1" #export PSEUDO_PREFIX = "${STAGING_DIR_NATIVE}${prefix_native}" diff --git a/scripts/lib/devtool/__init__.py b/scripts/lib/devtool/__init__.py index 58b02eb460..32a7bc0098 100644 --- a/scripts/lib/devtool/__init__.py +++ b/scripts/lib/devtool/__init__.py @@ -77,7 +77,14 @@ def exec_watch(cmd, **options): return buf, None -def exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, cmd, **kwargs): +def exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, cmd, env_overrides=None, **kwargs): + """Run cmd under pseudo using a recipe's own FAKEROOTCMD/FAKEROOTENV. + + env_overrides, if given, is applied after fakerootenv so callers can point + pseudo at a different database/allow-list, e.g. a target rootfs's own + PSEUDO_LOCALSTATEDIR/PSEUDO_INCLUDE_PATHS instead of the ambient ones from + FAKEROOTENV. + """ if not os.path.exists(fakerootcmd): logger.error('pseudo executable %s could not be found - have you run a build yet? pseudo-native should install this and if you have run any build then that should have been built') return 2 @@ -88,6 +95,8 @@ def exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, cmd, **kwargs): if '=' in varvalue: splitval = varvalue.split('=', 1) newenv[splitval[0]] = splitval[1] + if env_overrides: + newenv.update(env_overrides) return subprocess.call("%s %s" % (fakerootcmd, cmd), env=newenv, **kwargs) def setup_tinfoil(config_only=False, basepath=None, tracking=False): diff --git a/scripts/lib/devtool/deploy.py b/scripts/lib/devtool/deploy.py index d11b04aea2..7a83d4a23a 100644 --- a/scripts/lib/devtool/deploy.py +++ b/scripts/lib/devtool/deploy.py @@ -277,8 +277,10 @@ def deploy_no_d(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_proce srcdir = recipe_outdir recipe_outdir = os.path.join(workdir, 'devtool-deploy-target-stripped') if os.path.isdir(recipe_outdir): - exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, "rm -rf %s" % recipe_outdir, shell=True) - exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True) + exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, "rm -rf %s" % recipe_outdir, + env_overrides={'PSEUDO_INCLUDE_PATHS': recipe_outdir}, shell=True) + exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), + env_overrides={'PSEUDO_INCLUDE_PATHS': '%s,%s' % (srcdir, recipe_outdir)}, shell=True) # Strip under pseudo so that it records any inode replacements made by # the strip tool before the deployment tar reads this directory. @@ -292,7 +294,7 @@ def deploy_no_d(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_proce ret = exec_fakeroot_no_d( fakerootcmd, fakerootenv, path, '%s -c %s' % (shlex.quote(sys.executable), shlex.quote(strip_script)), - shell=True) + env_overrides={'PSEUDO_INCLUDE_PATHS': recipe_outdir}, shell=True) if ret != 0: raise DevtoolError('Failed to strip files for deployment') @@ -418,7 +420,8 @@ def deploy_no_d(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_proce remote_cmd = '%s | %s %s %s %s \'sh %s %s %s %s\'' % ( tar_cmd, ssh_sshexec, ssh_port, extraoptions, args.target, tmpscript, args.recipename, destdir, tmpfilelist) - ret = exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, remote_cmd, cwd=recipe_outdir, shell=True) + ret = exec_fakeroot_no_d(fakerootcmd, fakerootenv, path, remote_cmd, cwd=recipe_outdir, + env_overrides={'PSEUDO_INCLUDE_PATHS': recipe_outdir}, shell=True) finally: if tar_filelist_path: os.remove(tar_filelist_path) From patchwork Sun Sep 6 21:02:07 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AdrianF X-Patchwork-Id: 97423 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 954F7C79FA8 for ; Sun, 6 Sep 2026 21:03:23 +0000 (UTC) Received: from mta-65-225.siemens.flowmailer.net (mta-65-225.siemens.flowmailer.net [185.136.65.225]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.21344.1788728596287260052 for ; Sun, 06 Sep 2026 14:03:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=adrian.freihofer@siemens.com header.s=fm2 header.b=F8FH+umI; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.225, mailfrom: fm-1329275-20260906210314de6a183746000207c4-y0d_qz@rts-flowmailer.siemens.com) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 20260906210314de6a183746000207c4 for ; Sun, 06 Sep 2026 23:03:14 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm2; d=siemens.com; i=adrian.freihofer@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=zYG0e4ej8TNUoQk2tx+r2uj0vaZOTs/okZIRpj3iVQk=; b=F8FH+umI3xJIdshOV4NJP5Q49lJsWOx4UkupGGhYTH3Xze3hT6Hyegp2qgm0cBnkOaMth/ D4jDj9tv4iCR+uzllMTSV/nzlnVgdV/p2ojHnKK+4F9fC7vKDXEzyLo5306GOwZTL2qggXfu l18wtXDfGEr5uEfXchSHkHr7gECarFOcSoqq7xaN3PX/KmOpQY9K55O5TDjI3v4Y9dJPRxzr i0+wedF7X4A1fYlFpB1kuVi/PC6Tnx9OQo1SOchSnHBl5fkKj9+NxIC3ohVwRXsmjKpOfca3 oTeGbQQrDokRhP88X0CDeeWnsGxjPgA/k2P3Jv4r5QI9HLEhRjuYHacA==; From: AdrianF To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer Subject: [PATCH 9/9] devtool: deploy: remove dead files_list computation Date: Sun, 6 Sep 2026 23:02:07 +0200 Message-ID: <20260906210307.2793974-10-adrian.freihofer@siemens.com> In-Reply-To: <20260906210307.2793974-1-adrian.freihofer@siemens.com> References: <20260906210307.2793974-1-adrian.freihofer@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-1329275:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 06 Sep 2026 21:03:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/245213 From: Adrian Freihofer deploy_no_d() built a files_list from os.walk(recipe_outdir) after a successful deploy but never used it. It fed a host-side manifest file written via open(deploy_file, 'w') until commit a16a0c9334b7 ("devtool: deploy-target: write deployed files list to target", 2016-02-19), which moved manifest writing to the target's shell script and dropped that write, leaving the list-building loop as dead code ever since. Signed-off-by: Adrian Freihofer --- scripts/lib/devtool/deploy.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/lib/devtool/deploy.py b/scripts/lib/devtool/deploy.py index 7a83d4a23a..51a1944f38 100644 --- a/scripts/lib/devtool/deploy.py +++ b/scripts/lib/devtool/deploy.py @@ -431,12 +431,6 @@ def deploy_no_d(srcdir, workdir, path, strip_cmd, libdir, base_libdir, max_proce logger.info('Successfully deployed %s' % recipe_outdir) - files_list = [] - for root, _, files in os.walk(recipe_outdir): - for filename in files: - filename = os.path.relpath(os.path.join(root, filename), recipe_outdir) - files_list.append(os.path.join(destdir, filename)) - return 0 def undeploy(args, config, basepath, workspace):